From 9092fc71350957d7f5f204f5539f8b8994e773ae Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 13 Dec 2023 16:24:56 -0800 Subject: [PATCH] Polish language server and documentation. --- docs/user-guide/03-convenience-features.md | 5 +- .../04-modules-and-access-control.md | 24 ++- source/slang/slang-ast-expr.h | 2 + source/slang/slang-ast-iterator.h | 1 + source/slang/slang-check-expr.cpp | 1 + .../slang-language-server-ast-lookup.cpp | 9 +- .../slang-language-server-semantic-tokens.cpp | 147 ++++++++++-------- source/slang/slang-parser.cpp | 1 + 8 files changed, 111 insertions(+), 79 deletions(-) diff --git a/docs/user-guide/03-convenience-features.md b/docs/user-guide/03-convenience-features.md index 4957f267e6..eefd9fc632 100644 --- a/docs/user-guide/03-convenience-features.md +++ b/docs/user-guide/03-convenience-features.md @@ -87,13 +87,16 @@ namespace ns You can also use the `using` keyword to pull symbols defined in a different namespace to the current scope, removing the requirement for using fully qualified names. -```csharp +```cpp namespace ns1.ns2 { int f(); } using ns1.ns2; +// or: +using namespace ns1.ns2; // alternative syntax. + void test() { f(); } // OK. ``` diff --git a/docs/user-guide/04-modules-and-access-control.md b/docs/user-guide/04-modules-and-access-control.md index 7f6ec91a54..68e2d06c7f 100644 --- a/docs/user-guide/04-modules-and-access-control.md +++ b/docs/user-guide/04-modules-and-access-control.md @@ -59,9 +59,13 @@ void f_b() { f_a(); } // c.slang implementing "m.slang"; // alternate syntax. -// OK to use f_a and f_b because they are part of module `m`, even -// if we are not including `a` and `b` here. -void f_c() { f_a(); f_b(); } + +void f_c() +{ + // OK, `c.slang` is part of module `m` because it is `__include`'d by + // `m.slang`. + f_a(); f_b(); +} // m.slang module m; @@ -79,8 +83,14 @@ __include "dir/file-name.slang"; __include "dir/file-name"; ``` +Also note that a file is considered a part of a module only if the file can be discovered +via transitive `__include`s from the primary module file. It is possible to have a dangling +file with the `implementing` declaration that is not `__include`'d by any other files in +the module. Such dangling files will not be considered as part of the module and will not +be compiled. The `implementing` declaration is for the purpose of verification and language server code assisting, and does not carry any other semantics that affect compilation. + > #### Note #### -> When using the identifier token syntax, Slang will translate any underscores(`_`) to hyphenators("-") to obtain the file name. +> When using the identifier token syntax, Slang will translate any underscores(`_`) to hyphens("-") to obtain the file name. ## Importing a Module @@ -150,14 +160,14 @@ module a; __include b; public struct PS { - int internalMember; + internal int internalMember; public int publicMember; } internal void f() { f_b(); } // OK, f_b defined in the same module. // b.slang implementing a; -internal void f_b(); // Defines f_b in module a so they can within the module. +internal void f_b(); // Defines f_b in module `a`. public void publicFunc(); // m.slang @@ -190,7 +200,7 @@ The Slang compiler enforces the following rules regarding access control: Slang used to not have support for access control, and all symbols were treated as having `public` visibility. To provide compatibility with existing code, the Slang compiler will detect if the module is written in the legacy language, and treat all symbols as `public` if so. A module is determined to be written in legacy language if all the following conditions are met: -- The module is lacking `module` declaration at the begining. +- The module is lacking `module` declaration at the beginning. - There is no use of `__include`. - There is no use of any visibility modifiers -- `public`, `private` or `internal`. diff --git a/source/slang/slang-ast-expr.h b/source/slang/slang-ast-expr.h index 88293a812b..23c721038b 100644 --- a/source/slang/slang-ast-expr.h +++ b/source/slang/slang-ast-expr.h @@ -53,6 +53,8 @@ class OverloadedExpr : public Expr // arose from a member-reference expression. Expr* base = nullptr; + Expr* originalExpr = nullptr; + // The lookup result that was ambiguous LookupResult lookupResult2; }; diff --git a/source/slang/slang-ast-iterator.h b/source/slang/slang-ast-iterator.h index 7dc358a8e2..2e8f026979 100644 --- a/source/slang/slang-ast-iterator.h +++ b/source/slang/slang-ast-iterator.h @@ -150,6 +150,7 @@ struct ASTIterator { iterator->maybeDispatchCallback(expr); dispatchIfNotNull(expr->base); + dispatchIfNotNull(expr->originalExpr); } void visitOverloadedExpr2(OverloadedExpr2* expr) { diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 753f147683..59f7f2aa1e 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -814,6 +814,7 @@ namespace Slang m_astBuilder->getOverloadedType()); overloadedExpr->base = baseExpr; overloadedExpr->lookupResult2 = lookupResult; + overloadedExpr->originalExpr = originalExpr; return overloadedExpr; } else diff --git a/source/slang/slang-language-server-ast-lookup.cpp b/source/slang/slang-language-server-ast-lookup.cpp index 0e8520f3a8..3da4f85549 100644 --- a/source/slang/slang-language-server-ast-lookup.cpp +++ b/source/slang/slang-language-server-ast-lookup.cpp @@ -187,7 +187,7 @@ struct ASTLookupExprVisitor: public ExprVisitor declLength = _getDeclNameLength(expr->name, expr->declRef.getDecl()); } if (_isLocInRange( - context, expr->loc, declLength)) + context, expr->loc, declLength)) { ASTLookupResult result; result.path = context->nodePath; @@ -196,7 +196,7 @@ struct ASTLookupExprVisitor: public ExprVisitor return true; } } - + return dispatchIfNotNull(expr->originalExpr); } @@ -242,6 +242,11 @@ struct ASTLookupExprVisitor: public ExprVisitor if (dispatchIfNotNull(expr->base)) return true; } + { + PushNode pushNode(context, expr); + if (dispatchIfNotNull(expr->originalExpr)) + return true; + } if (expr->lookupResult2.getName() && _isLocInRange( context, diff --git a/source/slang/slang-language-server-semantic-tokens.cpp b/source/slang/slang-language-server-semantic-tokens.cpp index 8fb4b13034..837aad06c4 100644 --- a/source/slang/slang-language-server-semantic-tokens.cpp +++ b/source/slang/slang-language-server-semantic-tokens.cpp @@ -48,6 +48,78 @@ List getSemanticTokens(Linkage* linkage, Module* module, UnownedS token.type != SemanticTokenType::NormalText) result.add(token); }; + auto handleDeclRef = [&](DeclRef declRef, Expr* originalExpr, SourceLoc loc) + { + if (!declRef) + return; + auto decl = declRef.getDecl(); + if (auto genDecl = as(decl)) + decl = genDecl->inner; + if (!decl) + return; + auto name = declRef.getDecl()->getName(); + if (!name) + return; + // Don't look at the expr if it is defined in a different file. + if (!manager->getHumaneLoc(loc, SourceLocType::Actual) + .pathInfo.foundPath.getUnownedSlice() + .endsWithCaseInsensitive(fileName)) + return; + SemanticToken token = + _createSemanticToken(manager, loc, name); + auto target = decl; + if (as(target)) + { + if (target->hasModifier()) + return; + token.type = SemanticTokenType::Type; + } + else if (as(target)) + { + token.type = SemanticTokenType::Type; + token.length = doc->getTokenLength(token.line, token.col); + } + else if (as(target)) + { + token.type = SemanticTokenType::Type; + } + else if (as(target)) + { + token.type = SemanticTokenType::Property; + } + else if (as(target)) + { + token.type = SemanticTokenType::Parameter; + } + else if (as(target)) + { + if (as(originalExpr) || + as(originalExpr)) + { + return; + } + token.type = SemanticTokenType::Variable; + } + else if (as(target)) + { + token.type = SemanticTokenType::Function; + } + else if (as(target)) + { + token.type = SemanticTokenType::EnumMember; + } + else if (as(target)) + { + token.type = SemanticTokenType::Namespace; + } + + if (as(target)) + { + if (target->hasModifier()) + return; + } + maybeInsertToken(token); + }; iterateAST( fileName, manager, @@ -56,77 +128,14 @@ List getSemanticTokens(Linkage* linkage, Module* module, UnownedS { if (auto declRefExpr = as(node)) { - auto declRef = declRefExpr->declRef; - auto loc = declRefExpr->loc; - if (!declRef) - return; - auto decl = declRef.getDecl(); - if (auto genDecl = as(decl)) - decl = genDecl->inner; - if (!decl) - return; - auto name = declRef.getDecl()->getName(); - if (!name) - return; - // Don't look at the expr if it is defined in a different file. - if (!manager->getHumaneLoc(loc, SourceLocType::Actual) - .pathInfo.foundPath.getUnownedSlice() - .endsWithCaseInsensitive(fileName)) - return; - SemanticToken token = - _createSemanticToken(manager, loc, name); - auto target = decl; - if (as(target)) - { - if (target->hasModifier()) - return; - token.type = SemanticTokenType::Type; - } - else if (as(target)) - { - token.type = SemanticTokenType::Type; - token.length = doc->getTokenLength(token.line, token.col); - } - else if (as(target)) - { - token.type = SemanticTokenType::Type; - } - else if (as(target)) - { - token.type = SemanticTokenType::Property; - } - else if (as(target)) - { - token.type = SemanticTokenType::Parameter; - } - else if (as(target)) - { - if (as(declRefExpr->originalExpr) || - as(declRefExpr->originalExpr)) - { - return; - } - token.type = SemanticTokenType::Variable; - } - else if (as(target)) - { - token.type = SemanticTokenType::Function; - } - else if (as(target)) - { - token.type = SemanticTokenType::EnumMember; - } - else if (as(target)) - { - token.type = SemanticTokenType::Namespace; - } - - if (as(target)) + handleDeclRef(declRefExpr->declRef, declRefExpr->originalExpr, declRefExpr->loc); + } + else if (auto overloadedExpr = as(node)) + { + if (overloadedExpr->lookupResult2.items.getCount()) { - if (target->hasModifier()) - return; + handleDeclRef(overloadedExpr->lookupResult2.items[0].declRef, overloadedExpr->originalExpr, overloadedExpr->loc); } - maybeInsertToken(token); } else if (auto accessorDecl = as(node)) { diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 361786b6f9..1a7845a258 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -3374,6 +3374,7 @@ namespace Slang { namespaceDecl = parser->astBuilder->create(); namespaceDecl->nameAndLoc = nameAndLoc; + namespaceDecl->loc = nameAndLoc.loc; } } if (!result)