Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/compiler-core/slang-json-value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Comment on lines +658 to +660
Copy link
Copy Markdown
Collaborator

@jkwak-work jkwak-work Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to test against false values like how the other cases are implemented in this function.

    case JSONValue::Type::StringLexeme:
        return !getTransientString(value).caseInsensitiveEquals(toSlice("false")) &&
               !getTransientString(value).caseInsensitiveEquals(toSlice("0"));

default:
return value.asBool();
}
Expand Down
9 changes: 6 additions & 3 deletions source/slang/slang-ast-decl-ref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
38 changes: 34 additions & 4 deletions source/slang/slang-ast-print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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...
Expand All @@ -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>())
Expand Down
2 changes: 1 addition & 1 deletion source/slang/slang-check-decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion source/slang/slang-check-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions source/slang/slang-content-assist-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct CompletionSuggestions

ScopeKind scopeKind = ScopeKind::Invalid;
FormatMode formatMode = FormatMode::Name;
Decl* currentPartialDecl = nullptr;

List<LookupResultItem> candidateItems;
Type* swizzleBaseType = nullptr;
Expand All @@ -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;
}
};

Expand Down
1 change: 1 addition & 0 deletions source/slang/slang-language-server-auto-format.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum class FormatBehavior

struct FormatOptions
{
bool enableFormatOnType = true;
String clangFormatLocation;
String style = "file";
String fallbackStyle = "{BasedOnStyle: Microsoft}";
Expand Down
32 changes: 32 additions & 0 deletions source/slang/slang-language-server-completion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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))
{
Expand Down
71 changes: 61 additions & 10 deletions source/slang/slang-language-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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,
Expand All @@ -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())
Expand Down Expand Up @@ -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";
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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")
{
Expand Down
1 change: 1 addition & 0 deletions source/slang/slang-language-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ class LanguageServer
void updateSearchInWorkspace(const JSONValue& value);
void updateCommitCharacters(const JSONValue& value);
void updateFormattingOptions(
const JSONValue& enableFormatOnType,
const JSONValue& clangFormatLoc,
const JSONValue& clangFormatStyle,
const JSONValue& clangFormatFallbackStyle,
Expand Down
13 changes: 13 additions & 0 deletions tests/language-server/existential-decl-path.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//TEST:LANG_SERVER(filecheck=CHECK):
interface IFoo
{
int getSum();
}

void test(IFoo f)
{
//HOVER:10,9
f.getSum();
}

//CHECK: IFoo.getSum
17 changes: 17 additions & 0 deletions tests/language-server/override-completion-2.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//TEST:LANG_SERVER(filecheck=CHECK):
interface IBar{ associatedtype AT; }
interface IFoo
{
associatedtype B : IBar;
//HOVER:7,12
static B.AT execute(int x);
}

struct Impl : IFoo
{
//COMPLETE:13,14
override
}

//CHECK: associatedtype This.B
//CHECK: static B.AT execute(int x)
2 changes: 1 addition & 1 deletion tests/language-server/smoke.slang.expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ content:
--------
activeParameter: 0
activeSignature: 0
func IFoo.getSum() -> int:
func T.getSum() -> int:

Returns the sum of the contents.

Expand Down
Loading