summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2025-07-01 14:02:35 -0700
committerGitHub <noreply@github.com>2025-07-01 21:02:35 +0000
commiteb7f3357a1c316bad51cf0bfaea27d81a93f96ad (patch)
tree448a2a07d36ef11b66ef79522086765efc5e708b /source
parent5120c1cd072548654c9ce79fa85426a5e48736c4 (diff)
Misc language server improvements. (#7569)
* Misc language server improvements. * Fix. * Fix decl path printing for existential lookup. * More existential decl path fix. * Polish. * Fix test.
Diffstat (limited to 'source')
-rw-r--r--source/compiler-core/slang-json-value.cpp3
-rw-r--r--source/slang/slang-ast-decl-ref.cpp9
-rw-r--r--source/slang/slang-ast-print.cpp38
-rw-r--r--source/slang/slang-check-decl.cpp2
-rw-r--r--source/slang/slang-check-expr.cpp2
-rw-r--r--source/slang/slang-content-assist-info.h3
-rw-r--r--source/slang/slang-language-server-auto-format.h1
-rw-r--r--source/slang/slang-language-server-completion.cpp32
-rw-r--r--source/slang/slang-language-server.cpp71
-rw-r--r--source/slang/slang-language-server.h1
10 files changed, 143 insertions, 19 deletions
diff --git a/source/compiler-core/slang-json-value.cpp b/source/compiler-core/slang-json-value.cpp
index 56d003737..e2e95a968 100644
--- a/source/compiler-core/slang-json-value.cpp
+++ b/source/compiler-core/slang-json-value.cpp
@@ -655,6 +655,9 @@ bool JSONContainer::asBool(const JSONValue& value)
return asInteger(value) != 0;
case JSONValue::Type::FloatLexeme:
return asFloat(value) != 0.0;
+ case JSONValue::Type::StringLexeme:
+ return getTransientString(value).caseInsensitiveEquals(toSlice("true")) ||
+ getTransientString(value).caseInsensitiveEquals(toSlice("1"));
default:
return value.asBool();
}
diff --git a/source/slang/slang-ast-decl-ref.cpp b/source/slang/slang-ast-decl-ref.cpp
index 76d0324c6..7eec32a3a 100644
--- a/source/slang/slang-ast-decl-ref.cpp
+++ b/source/slang/slang-ast-decl-ref.cpp
@@ -131,9 +131,12 @@ DeclRefBase* LookupDeclRef::_substituteImplOverride(
void LookupDeclRef::_toTextOverride(StringBuilder& out)
{
- getLookupSource()->toText(out);
- if (out.getLength() && !out.endsWith("."))
- out << ".";
+ if (!as<ThisType>(getLookupSource()))
+ {
+ getLookupSource()->toText(out);
+ if (out.getLength() && !out.endsWith("."))
+ out << ".";
+ }
if (getDecl()->getName() && getDecl()->getName()->text.getLength() != 0)
{
out << getDecl()->getName()->text;
diff --git a/source/slang/slang-ast-print.cpp b/source/slang/slang-ast-print.cpp
index 94864b815..4b5a69f15 100644
--- a/source/slang/slang-ast-print.cpp
+++ b/source/slang/slang-ast-print.cpp
@@ -1168,8 +1168,34 @@ void ASTPrinter::_addDeclPathRec(const DeclRef<Decl>& declRef, Index depth)
{
auto& sb = m_builder;
- // Find the parent declaration
- auto parentDeclRef = declRef.getParent();
+ // Find the parent declaration.
+ DeclRef<Decl> parentDeclRef;
+
+ // If this is a lookup decl ref, prefix with the lookup source type instead of the parent.
+ if (auto lookupDeclRef = as<LookupDeclRef>(declRef.declRefBase))
+ {
+ if (auto extractExistentialType =
+ as<ExtractExistentialType>(lookupDeclRef->getLookupSource()))
+ {
+ parentDeclRef = extractExistentialType->getOriginalInterfaceDeclRef();
+ }
+ else
+ {
+ parentDeclRef = isDeclRefTypeOf<Decl>(lookupDeclRef->getLookupSource());
+ }
+ if (as<ThisTypeDecl>(parentDeclRef.getDecl()))
+ {
+ if (auto baseLookupDeclRef = as<LookupDeclRef>(parentDeclRef.declRefBase))
+ {
+ // If the base type is a lookup, we want to use its source type
+ parentDeclRef = isDeclRefTypeOf<Decl>(baseLookupDeclRef->getLookupSource());
+ }
+ }
+ }
+ else
+ {
+ parentDeclRef = declRef.getParent();
+ }
// If the immediate parent is a generic, then we probably
// want the declaration above that...
@@ -1180,9 +1206,13 @@ void ASTPrinter::_addDeclPathRec(const DeclRef<Decl>& declRef, Index depth)
}
// Depending on what the parent is, we may want to format things specially
- if (auto aggTypeDeclRef = parentDeclRef.as<AggTypeDecl>())
+ if (parentDeclRef.as<ThisTypeDecl>())
+ {
+ sb << "This.";
+ }
+ else if (parentDeclRef.as<AggTypeDecl>() || parentDeclRef.as<SimpleTypeDecl>())
{
- _addDeclPathRec(aggTypeDeclRef, depth + 1);
+ _addDeclPathRec(parentDeclRef, depth + 1);
sb << toSlice(".");
}
else if (auto namespaceDeclRef = parentDeclRef.as<NamespaceDecl>())
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 9e4d5a6d3..6d8788b4f 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -7898,7 +7898,7 @@ void SemanticsVisitor::calcOverridableCompletionCandidates(
contentAssistInfo.completionSuggestions.formatMode =
varDeclBase ? CompletionSuggestions::FormatMode::FuncSignatureWithoutReturnType
: CompletionSuggestions::FormatMode::FullSignature;
-
+ contentAssistInfo.completionSuggestions.currentPartialDecl = memberDecl;
List<LookupResultItem> candidateItems;
for (auto facet : inheritanceInfo.facets)
{
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index b90081af8..c3238bd9b 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -410,7 +410,7 @@ DeclRefExpr* SemanticsVisitor::ConstructDeclRefExpr(
SharedTypeExpr* baseTypeExpr = m_astBuilder->create<SharedTypeExpr>();
baseTypeExpr->base.type = baseExprType;
baseTypeExpr->type.type = m_astBuilder->getTypeType(baseExprType);
-
+ baseTypeExpr->base.exp = baseExpr;
auto expr = m_astBuilder->create<StaticMemberExpr>();
expr->loc = loc;
expr->type = type;
diff --git a/source/slang/slang-content-assist-info.h b/source/slang/slang-content-assist-info.h
index 77102bf66..c913e1546 100644
--- a/source/slang/slang-content-assist-info.h
+++ b/source/slang/slang-content-assist-info.h
@@ -32,6 +32,7 @@ struct CompletionSuggestions
ScopeKind scopeKind = ScopeKind::Invalid;
FormatMode formatMode = FormatMode::Name;
+ Decl* currentPartialDecl = nullptr;
List<LookupResultItem> candidateItems;
Type* swizzleBaseType = nullptr;
@@ -40,10 +41,12 @@ struct CompletionSuggestions
void clear()
{
scopeKind = ScopeKind::Invalid;
+ formatMode = FormatMode::Name;
candidateItems.clear();
elementCount[0] = 0;
elementCount[1] = 0;
swizzleBaseType = nullptr;
+ currentPartialDecl = nullptr;
}
};
diff --git a/source/slang/slang-language-server-auto-format.h b/source/slang/slang-language-server-auto-format.h
index 24e89b051..d37359730 100644
--- a/source/slang/slang-language-server-auto-format.h
+++ b/source/slang/slang-language-server-auto-format.h
@@ -27,6 +27,7 @@ enum class FormatBehavior
struct FormatOptions
{
+ bool enableFormatOnType = true;
String clangFormatLocation;
String style = "file";
String fallbackStyle = "{BasedOnStyle: Microsoft}";
diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp
index 9a88fbaa7..b5864d972 100644
--- a/source/slang/slang-language-server-completion.cpp
+++ b/source/slang/slang-language-server-completion.cpp
@@ -617,6 +617,16 @@ CompletionResult CompletionContext::collectMembersAndSymbols()
default:
return result;
}
+
+ // If we are completing an override function signature, don't add keywords to the result.
+ switch (linkage->contentAssistInfo.completionSuggestions.formatMode)
+ {
+ case CompletionSuggestions::FormatMode::FullSignature:
+ case CompletionSuggestions::FormatMode::FuncSignatureWithoutReturnType:
+ addKeywords = false;
+ break;
+ }
+
HashSet<String> deduplicateSet;
for (Index i = 0;
i < linkage->contentAssistInfo.completionSuggestions.candidateItems.getCount();
@@ -639,6 +649,28 @@ CompletionResult CompletionContext::collectMembersAndSymbols()
nameStart);
if (item.label.getLength() == 0)
continue;
+ if (linkage->contentAssistInfo.completionSuggestions.formatMode ==
+ CompletionSuggestions::FormatMode::FullSignature)
+ {
+ // If the completion item is a `static` function, but there is no `static` keyword
+ // on the current incomplete decl, then we will add `static` keyword to the completion
+ // result.
+ if (suggestedItem.declRef.getDecl() &&
+ suggestedItem.declRef.getDecl()->findModifier<HLSLStaticModifier>() &&
+ linkage->contentAssistInfo.completionSuggestions.currentPartialDecl &&
+ !linkage->contentAssistInfo.completionSuggestions.currentPartialDecl
+ ->findModifier<HLSLStaticModifier>())
+ {
+ item.label = "static " + item.label;
+ nameStart += 7;
+ // Add an item for 'static' keyword.
+ LanguageServerProtocol::CompletionItem staticItem;
+ staticItem.label = "static";
+ staticItem.kind = LanguageServerProtocol::kCompletionItemKindKeyword;
+ staticItem.data = "-1"; // Use -1 to indicate this is a keyword.
+ result.add(staticItem);
+ }
+ }
item.kind = LanguageServerProtocol::kCompletionItemKindKeyword;
if (as<TypeConstraintDecl>(member))
{
diff --git a/source/slang/slang-language-server.cpp b/source/slang/slang-language-server.cpp
index 6daeb75ad..3cc093ad7 100644
--- a/source/slang/slang-language-server.cpp
+++ b/source/slang/slang-language-server.cpp
@@ -210,15 +210,15 @@ SlangResult LanguageServer::parseNextMessage()
if (response.result.getKind() == JSONValue::Kind::Array)
{
auto arr = m_connection->getContainer()->getArray(response.result);
- if (arr.getCount() == 12)
+ if (arr.getCount() == 13)
{
updatePredefinedMacros(arr[0]);
updateSearchPaths(arr[1]);
updateSearchInWorkspace(arr[2]);
updateCommitCharacters(arr[3]);
- updateFormattingOptions(arr[4], arr[5], arr[6], arr[7], arr[8]);
- updateInlayHintOptions(arr[9], arr[10]);
- updateTraceOptions(arr[11]);
+ updateFormattingOptions(arr[4], arr[5], arr[6], arr[7], arr[8], arr[9]);
+ updateInlayHintOptions(arr[10], arr[11]);
+ updateTraceOptions(arr[12]);
}
}
break;
@@ -1876,6 +1876,9 @@ SlangResult LanguageServer::rangeFormatting(
LanguageServerResult<List<LanguageServerProtocol::TextEdit>> LanguageServerCore::rangeFormatting(
const LanguageServerProtocol::DocumentRangeFormattingParams& args)
{
+ if (!m_formatOptions.enableFormatOnType)
+ return std::nullopt;
+
String canonicalPath = uriToCanonicalPath(args.textDocument.uri);
RefPtr<DocumentVersion> doc;
if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc))
@@ -1924,6 +1927,9 @@ SlangResult LanguageServer::onTypeFormatting(
LanguageServerResult<List<LanguageServerProtocol::TextEdit>> LanguageServerCore::onTypeFormatting(
const LanguageServerProtocol::DocumentOnTypeFormattingParams& args)
{
+ if (!m_formatOptions.enableFormatOnType)
+ return std::nullopt;
+
String canonicalPath = uriToCanonicalPath(args.textDocument.uri);
RefPtr<DocumentVersion> doc;
if (!m_workspace->openedDocuments.tryGetValue(canonicalPath, doc))
@@ -2084,6 +2090,7 @@ void LanguageServer::updateCommitCharacters(const JSONValue& jsonValue)
}
void LanguageServer::updateFormattingOptions(
+ const JSONValue& enableFormatOnType,
const JSONValue& clangFormatLoc,
const JSONValue& clangFormatStyle,
const JSONValue& clangFormatFallbackStyle,
@@ -2092,6 +2099,8 @@ void LanguageServer::updateFormattingOptions(
{
auto container = m_connection->getContainer();
JSONToNativeConverter converter(container, &m_typeMap, m_connection->getSink());
+ if (enableFormatOnType.isValid())
+ converter.convert(enableFormatOnType, &m_core.m_formatOptions.enableFormatOnType);
if (clangFormatLoc.isValid())
converter.convert(clangFormatLoc, &m_core.m_formatOptions.clangFormatLocation);
if (clangFormatStyle.isValid())
@@ -2162,6 +2171,8 @@ void LanguageServer::sendConfigRequest()
args.items.add(item);
item.section = "slang.enableCommitCharactersInAutoCompletion";
args.items.add(item);
+ item.section = "slang.format.enableFormatOnType";
+ args.items.add(item);
item.section = "slang.format.clangFormatLocation";
args.items.add(item);
item.section = "slang.format.clangFormatStyle";
@@ -2611,7 +2622,7 @@ SlangResult LanguageServerCore::didChangeTextDocument(const DidChangeTextDocumen
SlangResult LanguageServer::didChangeConfiguration(
const LanguageServerProtocol::DidChangeConfigurationParams& args)
{
- if (args.settings.isValid())
+ if (args.settings.isValid() && args.settings.type != JSONValue::Type::Null)
{
updateConfigFromJSON(args.settings);
}
@@ -2657,25 +2668,65 @@ void LanguageServer::updateConfigFromJSON(const JSONValue& jsonVal)
{
updateCommitCharacters(kv.value);
}
+ else if (key == "slang.format.enableFormatOnType")
+ {
+ updateFormattingOptions(
+ kv.value,
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue());
+ }
else if (key == "slang.format.clangFormatLocation")
{
- updateFormattingOptions(kv.value, JSONValue(), JSONValue(), JSONValue(), JSONValue());
+ updateFormattingOptions(
+ JSONValue(),
+ kv.value,
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue());
}
else if (key == "slang.format.clangFormatStyle")
{
- updateFormattingOptions(JSONValue(), kv.value, JSONValue(), JSONValue(), JSONValue());
+ updateFormattingOptions(
+ JSONValue(),
+ JSONValue(),
+ kv.value,
+ JSONValue(),
+ JSONValue(),
+ JSONValue());
}
else if (key == "slang.format.clangFormatFallbackStyle")
{
- updateFormattingOptions(JSONValue(), JSONValue(), kv.value, JSONValue(), JSONValue());
+ updateFormattingOptions(
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ kv.value,
+ JSONValue(),
+ JSONValue());
}
else if (key == "slang.format.allowLineBreakChangesInOnTypeFormatting")
{
- updateFormattingOptions(JSONValue(), JSONValue(), JSONValue(), kv.value, JSONValue());
+ updateFormattingOptions(
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ kv.value,
+ JSONValue());
}
else if (key == "slang.format.allowLineBreakChangesInRangeFormatting")
{
- updateFormattingOptions(JSONValue(), JSONValue(), JSONValue(), JSONValue(), kv.value);
+ updateFormattingOptions(
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ JSONValue(),
+ kv.value);
}
else if (key == "slang.inlayHints.deducedTypes")
{
diff --git a/source/slang/slang-language-server.h b/source/slang/slang-language-server.h
index e31e77acb..43c3521eb 100644
--- a/source/slang/slang-language-server.h
+++ b/source/slang/slang-language-server.h
@@ -250,6 +250,7 @@ private:
void updateSearchInWorkspace(const JSONValue& value);
void updateCommitCharacters(const JSONValue& value);
void updateFormattingOptions(
+ const JSONValue& enableFormatOnType,
const JSONValue& clangFormatLoc,
const JSONValue& clangFormatStyle,
const JSONValue& clangFormatFallbackStyle,