summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-12-13 16:39:46 -0800
committerGitHub <noreply@github.com>2023-12-13 16:39:46 -0800
commit7e7d9ce142c3ef077743496cbf8cdc8f669a66af (patch)
treecabcc19ab27e638877d5d12080377f50f01e6f1a
parent3979660d4fe1fd6c1f1d9b8956e96817e17c3f4e (diff)
Polish language server and documentation. (#3410)
Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--docs/user-guide/03-convenience-features.md5
-rw-r--r--docs/user-guide/04-modules-and-access-control.md24
-rw-r--r--source/slang/slang-ast-expr.h2
-rw-r--r--source/slang/slang-ast-iterator.h1
-rw-r--r--source/slang/slang-check-expr.cpp1
-rw-r--r--source/slang/slang-language-server-ast-lookup.cpp9
-rw-r--r--source/slang/slang-language-server-semantic-tokens.cpp147
-rw-r--r--source/slang/slang-parser.cpp1
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 4957f267e..eefd9fc63 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 7f6ec91a5..68e2d06c7 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 88293a812..23c721038 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 7dc358a8e..2e8f02697 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 753f14768..59f7f2aa1 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 0e8520f3a..3da4f8554 100644
--- a/source/slang/slang-language-server-ast-lookup.cpp
+++ b/source/slang/slang-language-server-ast-lookup.cpp
@@ -187,7 +187,7 @@ public:
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 @@ public:
return true;
}
}
-
+
return dispatchIfNotNull(expr->originalExpr);
}
@@ -242,6 +242,11 @@ public:
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 8fb4b1303..837aad06c 100644
--- a/source/slang/slang-language-server-semantic-tokens.cpp
+++ b/source/slang/slang-language-server-semantic-tokens.cpp
@@ -48,6 +48,78 @@ List<SemanticToken> getSemanticTokens(Linkage* linkage, Module* module, UnownedS
token.type != SemanticTokenType::NormalText)
result.add(token);
};
+ auto handleDeclRef = [&](DeclRef<Decl> declRef, Expr* originalExpr, SourceLoc loc)
+ {
+ if (!declRef)
+ return;
+ auto decl = declRef.getDecl();
+ if (auto genDecl = as<GenericDecl>(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<AggTypeDecl>(target))
+ {
+ if (target->hasModifier<BuiltinTypeModifier>())
+ return;
+ token.type = SemanticTokenType::Type;
+ }
+ else if (as<ConstructorDecl>(target))
+ {
+ token.type = SemanticTokenType::Type;
+ token.length = doc->getTokenLength(token.line, token.col);
+ }
+ else if (as<SimpleTypeDecl>(target))
+ {
+ token.type = SemanticTokenType::Type;
+ }
+ else if (as<PropertyDecl>(target))
+ {
+ token.type = SemanticTokenType::Property;
+ }
+ else if (as<ParamDecl>(target))
+ {
+ token.type = SemanticTokenType::Parameter;
+ }
+ else if (as<VarDecl>(target))
+ {
+ if (as<MemberExpr>(originalExpr) ||
+ as<StaticMemberExpr>(originalExpr))
+ {
+ return;
+ }
+ token.type = SemanticTokenType::Variable;
+ }
+ else if (as<FunctionDeclBase>(target))
+ {
+ token.type = SemanticTokenType::Function;
+ }
+ else if (as<EnumCaseDecl>(target))
+ {
+ token.type = SemanticTokenType::EnumMember;
+ }
+ else if (as<NamespaceDecl>(target))
+ {
+ token.type = SemanticTokenType::Namespace;
+ }
+
+ if (as<CallableDecl>(target))
+ {
+ if (target->hasModifier<ImplicitConversionModifier>())
+ return;
+ }
+ maybeInsertToken(token);
+ };
iterateAST(
fileName,
manager,
@@ -56,77 +128,14 @@ List<SemanticToken> getSemanticTokens(Linkage* linkage, Module* module, UnownedS
{
if (auto declRefExpr = as<DeclRefExpr>(node))
{
- auto declRef = declRefExpr->declRef;
- auto loc = declRefExpr->loc;
- if (!declRef)
- return;
- auto decl = declRef.getDecl();
- if (auto genDecl = as<GenericDecl>(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<AggTypeDecl>(target))
- {
- if (target->hasModifier<BuiltinTypeModifier>())
- return;
- token.type = SemanticTokenType::Type;
- }
- else if (as<ConstructorDecl>(target))
- {
- token.type = SemanticTokenType::Type;
- token.length = doc->getTokenLength(token.line, token.col);
- }
- else if (as<SimpleTypeDecl>(target))
- {
- token.type = SemanticTokenType::Type;
- }
- else if (as<PropertyDecl>(target))
- {
- token.type = SemanticTokenType::Property;
- }
- else if (as<ParamDecl>(target))
- {
- token.type = SemanticTokenType::Parameter;
- }
- else if (as<VarDecl>(target))
- {
- if (as<MemberExpr>(declRefExpr->originalExpr) ||
- as<StaticMemberExpr>(declRefExpr->originalExpr))
- {
- return;
- }
- token.type = SemanticTokenType::Variable;
- }
- else if (as<FunctionDeclBase>(target))
- {
- token.type = SemanticTokenType::Function;
- }
- else if (as<EnumCaseDecl>(target))
- {
- token.type = SemanticTokenType::EnumMember;
- }
- else if (as<NamespaceDecl>(target))
- {
- token.type = SemanticTokenType::Namespace;
- }
-
- if (as<CallableDecl>(target))
+ handleDeclRef(declRefExpr->declRef, declRefExpr->originalExpr, declRefExpr->loc);
+ }
+ else if (auto overloadedExpr = as<OverloadedExpr>(node))
+ {
+ if (overloadedExpr->lookupResult2.items.getCount())
{
- if (target->hasModifier<ImplicitConversionModifier>())
- return;
+ handleDeclRef(overloadedExpr->lookupResult2.items[0].declRef, overloadedExpr->originalExpr, overloadedExpr->loc);
}
- maybeInsertToken(token);
}
else if (auto accessorDecl = as<AccessorDecl>(node))
{
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 361786b6f..1a7845a25 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -3374,6 +3374,7 @@ namespace Slang
{
namespaceDecl = parser->astBuilder->create<NamespaceDecl>();
namespaceDecl->nameAndLoc = nameAndLoc;
+ namespaceDecl->loc = nameAndLoc.loc;
}
}
if (!result)