summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-language-server.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-07-29 07:35:58 -0700
committerGitHub <noreply@github.com>2025-07-29 14:35:58 +0000
commit855b1a262f3a769d44765e78f94e566d875b9286 (patch)
treeea41db3717f55aa5032b1f04d71729a452ec68b2 /source/slang/slang-language-server.cpp
parentea6f8551ad38f2bcc32b542fd52ce17f3829cbeb (diff)
[Language Server]: Show signature help on generic parameters. (#7913)
* Show signature help on generic parameters. * Fix. * Update tests. * slang-test: make vvl error go through stderr. * update slang-rhi * Update slang-rhi
Diffstat (limited to 'source/slang/slang-language-server.cpp')
-rw-r--r--source/slang/slang-language-server.cpp59
1 files changed, 54 insertions, 5 deletions
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index 048fcb44b..dcf7419bd 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -160,6 +160,7 @@ SlangResult LanguageServer::parseNextMessage()
caps.semanticTokensProvider.full = true;
caps.semanticTokensProvider.range = false;
caps.signatureHelpProvider.triggerCharacters.add("(");
+ caps.signatureHelpProvider.triggerCharacters.add("<");
caps.signatureHelpProvider.triggerCharacters.add(",");
caps.signatureHelpProvider.retriggerCharacters.add(",");
for (auto tokenType : kSemanticTokenTypes)
@@ -1705,14 +1706,33 @@ LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::
bool useOriginalExpr = true;
if (auto originalDeclRefExpr = as<DeclRefExpr>(appExpr->originalFunctionExpr))
{
+ // If the original expr doesn't map to a valid declref, we will use the checked
+ // func expr instead.
if (!originalDeclRefExpr->declRef)
{
useOriginalExpr = false;
}
}
+ if (as<GenericAppExpr>(appExpr->originalFunctionExpr))
+ {
+ if (as<DeclRefExpr>(funcExpr))
+ {
+ // If the original function is a fully specialized generic app, use the checked func
+ // expr for signature help.
+ useOriginalExpr = false;
+ }
+ }
if (useOriginalExpr)
funcExpr = appExpr->originalFunctionExpr;
}
+ if (auto partialGenAppExpr = as<PartiallyAppliedGenericExpr>(funcExpr))
+ {
+ funcExpr = partialGenAppExpr->originalExpr;
+ }
+ if (auto genAppExpr = as<GenericAppExpr>(funcExpr))
+ {
+ funcExpr = genAppExpr->functionExpr;
+ }
if (!funcExpr)
{
return std::nullopt;
@@ -1741,6 +1761,22 @@ LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::
if (!declRef.getDecl())
return;
+ // If funcExpr is a direct reference to a generic, we should either
+ // show the generic signature if we are inside `<>`, or show the function
+ // parameter signature if we are inside `()`. If we are inside `()`, we will
+ // need to form a decl ref to the inner decl and show its signature.
+ if (!as<GenericAppExpr>(appExpr))
+ {
+ if (auto genDeclRef = as<GenericDecl>(declRef))
+ {
+ declRef = createDefaultSubstitutionsIfNeeded(
+ version->linkage->getASTBuilder(),
+ &semanticsVisitor,
+ version->linkage->getASTBuilder()->getMemberDeclRef(
+ declRef,
+ genDeclRef.getDecl()->inner));
+ }
+ }
// If we have a better match than the current best, we will update response.activeSignature
// to this signature.
if (auto callableDeclRef = declRef.as<CallableDecl>())
@@ -1832,12 +1868,20 @@ LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::
{
if (auto typeType = as<TypeType>(declRefExpr->type.type))
{
- // Look for initializers
- auto ctors =
- semanticsVisitor.lookupConstructorsInType(typeType->getType(), declRefExpr->scope);
- for (auto ctor : ctors)
+ if (as<GenericDeclRefType>(typeType->getType()))
{
- addDeclRef(ctor.declRef);
+ addDeclRef(declRefExpr->declRef);
+ }
+ else
+ {
+ // Look for initializers
+ auto ctors = semanticsVisitor.lookupConstructorsInType(
+ typeType->getType(),
+ declRefExpr->scope);
+ for (auto ctor : ctors)
+ {
+ addDeclRef(ctor.declRef);
+ }
}
}
else
@@ -1847,8 +1891,13 @@ LanguageServerResult<LanguageServerProtocol::SignatureHelp> LanguageServerCore::
}
else if (auto overloadedExpr = as<OverloadedExpr>(funcExpr))
{
+ bool isGenApp = as<GenericAppExpr>(appExpr) != nullptr;
for (auto item : overloadedExpr->lookupResult2)
{
+ // Skip non-generic candidates if we are inside a generic app expr (e.g.
+ // `f<WE_ARE_HERE>`).
+ if (isGenApp && !as<GenericDecl>(item.declRef))
+ continue;
addDeclRef(item.declRef);
}
}