Skip to content

Commit

Permalink
Merge branch 'main' into release/2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Nov 16, 2024
2 parents 23be433 + 7683220 commit d0583bc
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 49 deletions.
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Checks: >
performance-*,
portability-*,
readability-*,
-llvm-else-after-return,
-readability-else-after-return,
-readability-use-anyofallof,
-misc-const-correctness,
-misc-unused-parameters,
Expand Down
45 changes: 24 additions & 21 deletions libnixf/src/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,41 +76,44 @@ void VariableLookupAnalysis::emitEnvLivenessWarning(

void VariableLookupAnalysis::lookupVar(const ExprVar &Var,
const std::shared_ptr<EnvNode> &Env) {
const std::string &Name = Var.id().name();

bool EnclosedWith = false; // If there is a "With" enclosed this var name.
EnvNode *WithEnv = nullptr;
EnvNode *CurEnv = Env.get();
const auto &Name = Var.id().name();
const auto *CurEnv = Env.get();
std::shared_ptr<Definition> Def;
std::vector<const EnvNode *> WithEnvs;
for (; CurEnv; CurEnv = CurEnv->parent()) {
if (CurEnv->defs().contains(Name)) {
Def = CurEnv->defs().at(Name);
break;
}
// Find the most nested `with` expression, and set uses.
if (CurEnv->isWith() && !EnclosedWith) {
EnclosedWith = true;
WithEnv = CurEnv;
// Find all nested "with" expression, variables potentially come from those.
// For example
// with lib;
// with builtins;
// generators <--- this variable may come from "lib" | "builtins"
//
// We cannot determine where it precisely come from, thus mark all Envs
// alive.
if (CurEnv->isWith()) {
WithEnvs.emplace_back(CurEnv);
}
}

if (Def) {
Def->usedBy(Var);
Results.insert({&Var, LookupResult{LookupResultKind::Defined, Def}});
return;
}
if (EnclosedWith) {
Def = WithDefs.at(WithEnv->syntax());
Def->usedBy(Var);
} else if (!WithEnvs.empty()) { // comes from enclosed "with" expressions.
for (const auto *WithEnv : WithEnvs) {
Def = WithDefs.at(WithEnv->syntax());
Def->usedBy(Var);
}
Results.insert({&Var, LookupResult{LookupResultKind::FromWith, Def}});
return;
} else {
// Otherwise, this variable is undefined.
Results.insert({&Var, LookupResult{LookupResultKind::Undefined, nullptr}});
Diagnostic &Diag =
Diags.emplace_back(Diagnostic::DK_UndefinedVariable, Var.range());
Diag << Var.id().name();
}

// Otherwise, this variable is undefined.
Results.insert({&Var, LookupResult{LookupResultKind::Undefined, nullptr}});
Diagnostic &Diag =
Diags.emplace_back(Diagnostic::DK_UndefinedVariable, Var.range());
Diag << Var.id().name();
}

void VariableLookupAnalysis::dfs(const ExprLambda &Lambda,
Expand Down
14 changes: 14 additions & 0 deletions libnixf/test/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,4 +324,18 @@ in 1
ASSERT_EQ(Diags.size(), 1);
}

TEST_F(VLATest, Issue606_NestedWith) {
const char *Src = R"(
with builtins;
with builtins;
concatLists
)";

std::shared_ptr<Node> AST = parse(Src, Diags);
VariableLookupAnalysis VLA(Diags);
VLA.runOnAST(*AST);

ASSERT_EQ(Diags.size(), 0);
}

} // namespace
5 changes: 4 additions & 1 deletion nixd/docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ Screenshots:

### Semantic Tokens

> [!WARNING]
> This feature is experimental and not enabled by default.
[nixd language server](https://github.com/nix-community/nixd) tries to make some tokens looks different by sending your editor some integers.
However, types in nix language is pretty different from standard LSP types.
So, as a result, attrnames, selection, variables are colored as different integers,
but the colors may, or may not rendered properly in your editor.

> [!TIP]
> `--semantic-tokens=false` to disable the feature.
> `--semantic-tokens=true` to enable the feature.
#### Attribute name coloring

Expand Down
2 changes: 1 addition & 1 deletion nixd/lib/Controller/LifeTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ opt<std::string> DefaultNixOSOptionsExpr{

opt<bool> EnableSemanticTokens{"semantic-tokens",
desc("Enable/Disable semantic tokens"),
init(true), cat(NixdCategory)};
init(false), cat(NixdCategory)};

// Here we try to wrap nixpkgs, nixos options in a single emtpy attrset in test.
std::string getDefaultNixpkgsExpr() {
Expand Down
26 changes: 0 additions & 26 deletions nixd/tools/nixd/test/initialize.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,32 +49,6 @@ CHECK-NEXT: "referencesProvider": true,
CHECK-NEXT: "renameProvider": {
CHECK-NEXT: "prepareProvider": true
CHECK-NEXT: },
CHECK-NEXT: "semanticTokensProvider": {
CHECK-NEXT: "full": true,
CHECK-NEXT: "legend": {
CHECK-NEXT: "tokenModifiers": [
CHECK-NEXT: "static",
CHECK-NEXT: "abstract",
CHECK-NEXT: "async"
CHECK-NEXT: ],
CHECK-NEXT: "tokenTypes": [
CHECK-NEXT: "function",
CHECK-NEXT: "string",
CHECK-NEXT: "number",
CHECK-NEXT: "type",
CHECK-NEXT: "keyword",
CHECK-NEXT: "variable",
CHECK-NEXT: "interface",
CHECK-NEXT: "variable",
CHECK-NEXT: "regexp",
CHECK-NEXT: "macro",
CHECK-NEXT: "method",
CHECK-NEXT: "regexp",
CHECK-NEXT: "regexp"
CHECK-NEXT: ]
CHECK-NEXT: },
CHECK-NEXT: "range": false
CHECK-NEXT: },
CHECK-NEXT: "textDocumentSync": {
CHECK-NEXT: "change": 2,
CHECK-NEXT: "openClose": true,
Expand Down
107 changes: 107 additions & 0 deletions nixd/tools/nixd/test/semantic-tokens/initialize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# RUN: nixd --lit-test --semantic-tokens=true < %s | FileCheck %s

Check basic handshake with the server, i.e. "initialize"

<-- initialize(0)

```json
{
"jsonrpc":"2.0",
"id":0,
"method":"initialize",
"params":{
"processId":123,
"rootPath":"",
"capabilities":{ },
"trace":"off"
}
}
```

<-- reply:initialize(0)

```
CHECK: {
CHECK-NEXT: "id": 0,
CHECK-NEXT: "jsonrpc": "2.0",
CHECK-NEXT: "result": {
CHECK-NEXT: "capabilities": {
CHECK-NEXT: "codeActionProvider": {
CHECK-NEXT: "codeActionKinds": [
CHECK-NEXT: "quickfix"
CHECK-NEXT: ],
CHECK-NEXT: "resolveProvider": false
CHECK-NEXT: },
CHECK-NEXT: "completionProvider": {
CHECK-NEXT: "resolveProvider": true,
CHECK-NEXT: "triggerCharacters": [
CHECK-NEXT: "."
CHECK-NEXT: ]
CHECK-NEXT: },
CHECK-NEXT: "definitionProvider": true,
CHECK-NEXT: "documentFormattingProvider": true,
CHECK-NEXT: "documentHighlightProvider": true,
CHECK-NEXT: "documentLinkProvider": {},
CHECK-NEXT: "documentSymbolProvider": true,
CHECK-NEXT: "hoverProvider": true,
CHECK-NEXT: "inlayHintProvider": true,
CHECK-NEXT: "referencesProvider": true,
CHECK-NEXT: "renameProvider": {
CHECK-NEXT: "prepareProvider": true
CHECK-NEXT: },
CHECK-NEXT: "semanticTokensProvider": {
CHECK-NEXT: "full": true,
CHECK-NEXT: "legend": {
CHECK-NEXT: "tokenModifiers": [
CHECK-NEXT: "static",
CHECK-NEXT: "abstract",
CHECK-NEXT: "async"
CHECK-NEXT: ],
CHECK-NEXT: "tokenTypes": [
CHECK-NEXT: "function",
CHECK-NEXT: "string",
CHECK-NEXT: "number",
CHECK-NEXT: "type",
CHECK-NEXT: "keyword",
CHECK-NEXT: "variable",
CHECK-NEXT: "interface",
CHECK-NEXT: "variable",
CHECK-NEXT: "regexp",
CHECK-NEXT: "macro",
CHECK-NEXT: "method",
CHECK-NEXT: "regexp",
CHECK-NEXT: "regexp"
CHECK-NEXT: ]
CHECK-NEXT: },
CHECK-NEXT: "range": false
CHECK-NEXT: },
CHECK-NEXT: "textDocumentSync": {
CHECK-NEXT: "change": 2,
CHECK-NEXT: "openClose": true,
CHECK-NEXT: "save": true
CHECK-NEXT: }
CHECK-NEXT: }
CHECK-NEXT: "serverInfo": {
CHECK-NEXT: "name": "nixd",
CHECK-NEXT: "version": {{.*}}
CHECK-NEXT: }
CHECK-NEXT: }
CHECK-NEXT: }
```

<-- initialized

```json
{
"jsonrpc":"2.0",
"method":"initialized",
"params":{

}
}
```


```json
{"jsonrpc":"2.0","method":"exit"}
```

0 comments on commit d0583bc

Please sign in to comment.