From a4683b16ef5b51781b9866dd02b8562e17a942bc Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 22 Feb 2025 15:55:47 -0800 Subject: [PATCH 1/8] Allow `.member` syntax on vector and scalars. --- source/slang/slang-check-expr.cpp | 54 +++++++++++++++++++++++++---- tests/front-end/vector-member.slang | 17 +++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 tests/front-end/vector-member.slang diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 1fb2b336f0..dfb4ccfe7e 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -4914,6 +4914,40 @@ Expr* SemanticsVisitor::checkGeneralMemberLookupExpr(MemberExpr* expr, Type* bas return createLookupResultExpr(expr->name, lookupResult, expr->baseExpression, expr->loc, expr); } +bool isValidVectorSwizzleName(Name* name) +{ + if (!name) + return false; + if (name->text.getLength() > 4 || name->text.getLength() == 0) + return false; + bool isRGBA = false; + bool isXYZW = false; + for (auto ch : name->text) + { + switch (ch) + { + case 'w': + case 'x': + case 'y': + case 'z': + isXYZW = true; + continue; + case 'r': + case 'g': + case 'b': + case 'a': + isRGBA = true; + continue; + default: + return false; + } + } + // A valid swizzle cannot mix XYZW and RGBA. + if (isXYZW && isRGBA) + return false; + return true; +} + Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) { bool needDeref = false; @@ -4955,15 +4989,21 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) } if (auto baseVecType = as(baseType)) { - return CheckSwizzleExpr( - expr, - baseVecType->getElementType(), - baseVecType->getElementCount()); + if (isValidVectorSwizzleName(expr->name)) + { + return CheckSwizzleExpr( + expr, + baseVecType->getElementType(), + baseVecType->getElementCount()); + } } - else if (auto baseScalarType = as(baseType)) + if (auto baseScalarType = as(baseType)) { - // Treat scalar like a 1-element vector when swizzling - return CheckSwizzleExpr(expr, baseScalarType, 1); + if (isValidVectorSwizzleName(expr->name)) + { + // Treat scalar like a 1-element vector when swizzling + return CheckSwizzleExpr(expr, baseScalarType, 1); + } } else if (as(baseType)) { diff --git a/tests/front-end/vector-member.slang b/tests/front-end/vector-member.slang new file mode 100644 index 0000000000..adced39e46 --- /dev/null +++ b/tests/front-end/vector-member.slang @@ -0,0 +1,17 @@ +//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK):-output-using-type + +extension float3 +{ + float sum() { return this.x + this.y + this.z; } +} + +//TEST_INPUT: set outputBuffer = out ubuffer(data=[0 0 0 0], stride = 4) +RWStructuredBuffer outputBuffer; + +[numthreads(1,1,1)] +void computeMain() +{ + float3 v = { 1, 2, 3 }; + // CHECK: 6 + outputBuffer[0] = v.sum(); +} \ No newline at end of file From 8a4d4fd0804d76531b2d7d252cbfae66a214f579 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sat, 22 Feb 2025 23:27:21 -0800 Subject: [PATCH 2/8] Fix. --- source/slang/slang-check-expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index dfb4ccfe7e..ffdc9215a7 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -5005,7 +5005,7 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) return CheckSwizzleExpr(expr, baseScalarType, 1); } } - else if (as(baseType)) + if (as(baseType)) { return _lookupStaticMember(expr, expr->baseExpression); } From cf51e9a97d448e06133352264bda19221c40feec Mon Sep 17 00:00:00 2001 From: Yong He Date: Sun, 23 Feb 2025 10:09:42 -0800 Subject: [PATCH 3/8] fix. --- source/slang/slang-check-expr.cpp | 147 ++++++------------------- tests/bugs/invalid-swizzle-count.slang | 4 +- 2 files changed, 36 insertions(+), 115 deletions(-) diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index ffdc9215a7..667cad6ec8 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -4136,12 +4136,6 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( IntegerLiteralValue baseElementRowCount, IntegerLiteralValue baseElementColCount) { - MatrixSwizzleExpr* swizExpr = m_astBuilder->create(); - swizExpr->loc = memberRefExpr->loc; - swizExpr->base = memberRefExpr->baseExpression; - swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc; - swizExpr->checked = true; - // We can have up to 4 swizzles of two elements each MatrixCoord elementCoords[4]; int elementCount = 0; @@ -4170,24 +4164,14 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( // Throw out swizzling with more than 4 output elements if (elementCount >= 4) { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } MatrixCoord elementCoord = {0, 0}; // Check for the preceding underscore if (*cursor++ != '_') { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } // Check for one or zero indexing @@ -4196,12 +4180,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( // Can't mix one and zero indexing if (zeroIndexOffset == 1) { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } zeroIndexOffset = 0; // Increment the index since we saw 'm' @@ -4212,12 +4191,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( // Can't mix one and zero indexing if (zeroIndexOffset == 0) { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } zeroIndexOffset = 1; } @@ -4229,13 +4203,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( if (ch < '0' || ch > '4') { - // An invalid character in the swizzle is an error - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } const int subIndex = ch - '0' - zeroIndexOffset; @@ -4255,12 +4223,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( // Account for off-by-one and reject 0 if oneIndexed if (subIndex >= elementLimit || subIndex < 0) { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } } // Check if we've seen this index before @@ -4275,6 +4238,12 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( elementCount++; } + MatrixSwizzleExpr* swizExpr = m_astBuilder->create(); + swizExpr->loc = memberRefExpr->loc; + swizExpr->base = memberRefExpr->baseExpression; + swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc; + swizExpr->checked = true; + // Store our list in the actual AST node for (int ee = 0; ee < elementCount; ++ee) { @@ -4324,11 +4293,7 @@ Expr* SemanticsVisitor::CheckMatrixSwizzleExpr( constantColCount->getValue()); } } - getSink()->diagnose( - memberRefExpr, - Diagnostics::unimplemented, - "swizzle on matrix of unknown size"); - return CreateErrorExpr(memberRefExpr); + return nullptr; } Expr* SemanticsVisitor::checkTupleSwizzleExpr(MemberExpr* memberExpr, TupleType* baseTupleType) @@ -4439,10 +4404,6 @@ Expr* SemanticsVisitor::CheckSwizzleExpr( Type* baseElementType, IntegerLiteralValue baseElementCount) { - SwizzleExpr* swizExpr = m_astBuilder->create(); - swizExpr->loc = memberRefExpr->loc; - swizExpr->base = memberRefExpr->baseExpression; - swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc; IntegerLiteralValue limitElement = baseElementCount; ShortList elementIndices; @@ -4518,18 +4479,18 @@ Expr* SemanticsVisitor::CheckSwizzleExpr( elementIndices.add(elementIndex); } - swizExpr->elementIndices = _Move(elementIndices); - if (anyError) { - getSink()->diagnose( - swizExpr, - Diagnostics::invalidSwizzleExpr, - swizzleText, - baseElementType->toString()); - return CreateErrorExpr(memberRefExpr); + return nullptr; } - else if (swizExpr->elementIndices.getCount() == 1) + + SwizzleExpr* swizExpr = m_astBuilder->create(); + swizExpr->loc = memberRefExpr->loc; + swizExpr->base = memberRefExpr->baseExpression; + swizExpr->memberOpLoc = memberRefExpr->memberOperatorLoc; + swizExpr->elementIndices = _Move(elementIndices); + + if (swizExpr->elementIndices.getCount() == 1) { // single-component swizzle produces a scalar // @@ -4568,11 +4529,7 @@ Expr* SemanticsVisitor::CheckSwizzleExpr( } else { - getSink()->diagnose( - memberRefExpr, - Diagnostics::unimplemented, - "swizzle on vector of unknown size"); - return CreateErrorExpr(memberRefExpr); + return nullptr; } } @@ -4914,40 +4871,6 @@ Expr* SemanticsVisitor::checkGeneralMemberLookupExpr(MemberExpr* expr, Type* bas return createLookupResultExpr(expr->name, lookupResult, expr->baseExpression, expr->loc, expr); } -bool isValidVectorSwizzleName(Name* name) -{ - if (!name) - return false; - if (name->text.getLength() > 4 || name->text.getLength() == 0) - return false; - bool isRGBA = false; - bool isXYZW = false; - for (auto ch : name->text) - { - switch (ch) - { - case 'w': - case 'x': - case 'y': - case 'z': - isXYZW = true; - continue; - case 'r': - case 'g': - case 'b': - case 'a': - isRGBA = true; - continue; - default: - return false; - } - } - // A valid swizzle cannot mix XYZW and RGBA. - if (isXYZW && isRGBA) - return false; - return true; -} - Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) { bool needDeref = false; @@ -4981,29 +4904,27 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) // if (auto baseMatrixType = as(baseType)) { - return CheckMatrixSwizzleExpr( + auto swizzle = CheckMatrixSwizzleExpr( expr, baseMatrixType->getElementType(), baseMatrixType->getRowCount(), baseMatrixType->getColumnCount()); + if (swizzle) + return swizzle; } if (auto baseVecType = as(baseType)) { - if (isValidVectorSwizzleName(expr->name)) - { - return CheckSwizzleExpr( - expr, - baseVecType->getElementType(), - baseVecType->getElementCount()); - } + auto swizzle = + CheckSwizzleExpr(expr, baseVecType->getElementType(), baseVecType->getElementCount()); + if (swizzle) + return swizzle; } if (auto baseScalarType = as(baseType)) { - if (isValidVectorSwizzleName(expr->name)) - { - // Treat scalar like a 1-element vector when swizzling - return CheckSwizzleExpr(expr, baseScalarType, 1); - } + // Treat scalar like a 1-element vector when swizzling + auto swizzle = CheckSwizzleExpr(expr, baseScalarType, 1); + if (swizzle) + return swizzle; } if (as(baseType)) { diff --git a/tests/bugs/invalid-swizzle-count.slang b/tests/bugs/invalid-swizzle-count.slang index 811cf6f444..93cb1fdcc1 100644 --- a/tests/bugs/invalid-swizzle-count.slang +++ b/tests/bugs/invalid-swizzle-count.slang @@ -1,6 +1,6 @@ //TEST:SIMPLE(filecheck=CHECK): -target spirv -stage compute -entry computeMain -emit-spirv-directly -// CHECK: error 30052 -// CHECK-NOT: error 30052 +// CHECK: error 30027 +// CHECK-NOT: error 30027 RWStructuredBuffer outputBuffer; [numthreads(1,1,1)] From a0dc4ac62546e4ca40ec263bf7fb35e69b301310 Mon Sep 17 00:00:00 2001 From: Yong He Date: Sun, 23 Feb 2025 10:10:56 -0800 Subject: [PATCH 4/8] Fix. --- source/slang/slang-check-expr.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 667cad6ec8..6ecb91bc86 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -4902,30 +4902,31 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) // to swizzle vectors interferes with any chance of looking up // members via extension, for vector or scalar types. // - if (auto baseMatrixType = as(baseType)) + if (auto baseScalarType = as(baseType)) { - auto swizzle = CheckMatrixSwizzleExpr( - expr, - baseMatrixType->getElementType(), - baseMatrixType->getRowCount(), - baseMatrixType->getColumnCount()); + // Treat scalar like a 1-element vector when swizzling + auto swizzle = CheckSwizzleExpr(expr, baseScalarType, 1); if (swizzle) return swizzle; } - if (auto baseVecType = as(baseType)) + else if (auto baseVecType = as(baseType)) { auto swizzle = CheckSwizzleExpr(expr, baseVecType->getElementType(), baseVecType->getElementCount()); if (swizzle) return swizzle; } - if (auto baseScalarType = as(baseType)) + else if (auto baseMatrixType = as(baseType)) { - // Treat scalar like a 1-element vector when swizzling - auto swizzle = CheckSwizzleExpr(expr, baseScalarType, 1); + auto swizzle = CheckMatrixSwizzleExpr( + expr, + baseMatrixType->getElementType(), + baseMatrixType->getRowCount(), + baseMatrixType->getColumnCount()); if (swizzle) return swizzle; } + if (as(baseType)) { return _lookupStaticMember(expr, expr->baseExpression); From 8d0e6f210e27d380d3468e3c79f32d29c70f521f Mon Sep 17 00:00:00 2001 From: Yong He Date: Sun, 23 Feb 2025 10:12:41 -0800 Subject: [PATCH 5/8] update comment. --- source/slang/slang-check-expr.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 6ecb91bc86..6e58c20b5a 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -4895,12 +4895,9 @@ Expr* SemanticsExprVisitor::visitMemberExpr(MemberExpr* expr) if (auto modifiedType = as(baseType)) baseType = modifiedType->getBase(); - // Note: Checking for vector types before declaration-reference types, - // because vectors are also declaration reference types... - // - // Also note: the way this is done right now means that the ability - // to swizzle vectors interferes with any chance of looking up - // members via extension, for vector or scalar types. + // Try handle swizzle-able types (scalar,vector,matrix) first. + // If checking as a swizzle failed for these types, + // we will fallback to normal member lookup. // if (auto baseScalarType = as(baseType)) { From 8563312bd81422a2874a82255368f69b95030a00 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 25 Feb 2025 13:07:48 -0800 Subject: [PATCH 6/8] Fix tests. --- source/slang/slang-check-expr.cpp | 33 +++++++++++++------ source/slang/slang-check-overload.cpp | 18 +++++----- .../slang-language-server-completion.cpp | 31 ++++++++++------- .../slang/slang-language-server-completion.h | 5 ++- .../diagnostics/matrix-swizzle.slang.expected | 26 +++++++-------- .../member-completion-broken-syntax-3.slang | 10 ++++-- tests/language-server/vector-member.slang | 7 +++- tools/slang-test/slang-test-main.cpp | 18 ++++++---- 8 files changed, 94 insertions(+), 54 deletions(-) diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 6e58c20b5a..d8c640cebd 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -4410,16 +4410,7 @@ Expr* SemanticsVisitor::CheckSwizzleExpr( bool anyDuplicates = false; bool anyError = false; - if (memberRefExpr->name == getSession()->getCompletionRequestTokenName()) - { - auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions; - suggestions.clear(); - suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle; - suggestions.swizzleBaseType = - memberRefExpr->baseExpression ? memberRefExpr->baseExpression->type : nullptr; - suggestions.elementCount[0] = baseElementCount; - suggestions.elementCount[1] = 0; - } + auto swizzleText = getText(memberRefExpr->name); for (Index i = 0; i < swizzleText.getLength(); i++) @@ -4867,6 +4858,28 @@ Expr* SemanticsVisitor::checkGeneralMemberLookupExpr(MemberExpr* expr, Type* bas if (expr->name == getSession()->getCompletionRequestTokenName()) { suggestCompletionItems(CompletionSuggestions::ScopeKind::Member, lookupResult); + if (expr->baseExpression) + { + if (auto vectorType = as(expr->baseExpression->type)) + { + auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions; + suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle; + suggestions.elementCount[1] = 0; + suggestions.swizzleBaseType = vectorType; + if (auto elementCount = as(vectorType->getElementCount())) + suggestions.elementCount[0] = elementCount->getValue(); + else + suggestions.elementCount[0] = 1; + } + else if (auto scalarType = as(expr->baseExpression->type)) + { + auto& suggestions = getLinkage()->contentAssistInfo.completionSuggestions; + suggestions.scopeKind = CompletionSuggestions::ScopeKind::Swizzle; + suggestions.elementCount[1] = 0; + suggestions.elementCount[0] = 1; + suggestions.swizzleBaseType = scalarType; + } + } } return createLookupResultExpr(expr->name, lookupResult, expr->baseExpression, expr->loc, expr); } diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp index b75f95f9a8..2cfbf612ca 100644 --- a/source/slang/slang-check-overload.cpp +++ b/source/slang/slang-check-overload.cpp @@ -1316,15 +1316,17 @@ int SemanticsVisitor::CompareLookupResultItems( // Add a special case for constructors, where we prefer the one that is not synthesized, if (auto leftCtor = as(left.declRef.getDecl())) { - auto rightCtor = as(right.declRef.getDecl()); - bool leftIsSynthesized = - leftCtor->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault); - bool rightIsSynthesized = - rightCtor->containsFlavor(ConstructorDecl::ConstructorFlavor::SynthesizedDefault); - - if (leftIsSynthesized != rightIsSynthesized) + if (auto rightCtor = as(right.declRef.getDecl())) { - return int(leftIsSynthesized) - int(rightIsSynthesized); + bool leftIsSynthesized = leftCtor->containsFlavor( + ConstructorDecl::ConstructorFlavor::SynthesizedDefault); + bool rightIsSynthesized = rightCtor->containsFlavor( + ConstructorDecl::ConstructorFlavor::SynthesizedDefault); + + if (leftIsSynthesized != rightIsSynthesized) + { + return int(leftIsSynthesized) - int(rightIsSynthesized); + } } } diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp index 77ed330029..a81ee39a92 100644 --- a/source/slang/slang-language-server-completion.cpp +++ b/source/slang/slang-language-server-completion.cpp @@ -512,11 +512,14 @@ LanguageServerResult CompletionContext::tryCompleteMemberAndSy CompletionResult CompletionContext::collectMembersAndSymbols() { + List result; + auto linkage = version->linkage; if (linkage->contentAssistInfo.completionSuggestions.scopeKind == CompletionSuggestions::ScopeKind::Swizzle) { - return createSwizzleCandidates( + createSwizzleCandidates( + result, linkage->contentAssistInfo.completionSuggestions.swizzleBaseType, linkage->contentAssistInfo.completionSuggestions.elementCount); } @@ -526,12 +529,12 @@ CompletionResult CompletionContext::collectMembersAndSymbols() { return createCapabilityCandidates(); } - List result; bool useCommitChars = true; bool addKeywords = false; switch (linkage->contentAssistInfo.completionSuggestions.scopeKind) { case CompletionSuggestions::ScopeKind::Member: + case CompletionSuggestions::ScopeKind::Swizzle: useCommitChars = (commitCharacterBehavior == CommitCharacterBehavior::MembersOnly || commitCharacterBehavior == CommitCharacterBehavior::All); @@ -698,13 +701,12 @@ CompletionResult CompletionContext::createCapabilityCandidates() return result; } -CompletionResult CompletionContext::createSwizzleCandidates( +void CompletionContext::createSwizzleCandidates( + List& result, Type* type, IntegerLiteralValue elementCount[2]) { - List result; // Hard code members for vector and matrix types. - result.clear(); if (auto vectorType = as(type)) { const char* memberNames[4] = {"x", "y", "z", "w"}; @@ -724,6 +726,19 @@ CompletionResult CompletionContext::createSwizzleCandidates( result.add(item); } } + else if (auto scalarType = as(type)) + { + const char* memberNames[1] = {"x"}; + String typeStr; + if (scalarType) + typeStr = scalarType->toString(); + LanguageServerProtocol::CompletionItem item; + item.data = 0; + item.detail = typeStr; + item.kind = LanguageServerProtocol::kCompletionItemKindVariable; + item.label = "x"; + result.add(item); + } else if (auto matrixType = as(type)) { Type* elementType = nullptr; @@ -769,12 +784,6 @@ CompletionResult CompletionContext::createSwizzleCandidates( result.add(item); } } - for (auto& item : result) - { - for (auto ch : getCommitChars()) - item.commitCharacters.add(ch); - } - return result; } LanguageServerProtocol::CompletionItem CompletionContext::generateGUIDCompletionItem() diff --git a/source/slang/slang-language-server-completion.h b/source/slang/slang-language-server-completion.h index 560702deaa..fab1c8a755 100644 --- a/source/slang/slang-language-server-completion.h +++ b/source/slang/slang-language-server-completion.h @@ -55,7 +55,10 @@ struct CompletionContext CompletionResult collectMembersAndSymbols(); - CompletionResult createSwizzleCandidates(Type* baseType, IntegerLiteralValue elementCount[2]); + void createSwizzleCandidates( + List& result, + Type* type, + IntegerLiteralValue elementCount[2]); CompletionResult createCapabilityCandidates(); CompletionResult collectAttributes(); LanguageServerProtocol::CompletionItem generateGUIDCompletionItem(); diff --git a/tests/diagnostics/matrix-swizzle.slang.expected b/tests/diagnostics/matrix-swizzle.slang.expected index 832ddd7390..3c88531612 100644 --- a/tests/diagnostics/matrix-swizzle.slang.expected +++ b/tests/diagnostics/matrix-swizzle.slang.expected @@ -1,42 +1,42 @@ result code = -1 standard error = { -tests/diagnostics/matrix-swizzle.slang(8): error 30052: invalid swizzle pattern '_14' on type 'int' +tests/diagnostics/matrix-swizzle.slang(8): error 30027: '_14' is not a member of 'matrix'. int c = m1._14; // Out of bounds ^~~ -tests/diagnostics/matrix-swizzle.slang(9): error 30052: invalid swizzle pattern '_32' on type 'int' +tests/diagnostics/matrix-swizzle.slang(9): error 30027: '_32' is not a member of 'matrix'. c = m1._32; ^~~ -tests/diagnostics/matrix-swizzle.slang(10): error 30052: invalid swizzle pattern '_m22' on type 'int' +tests/diagnostics/matrix-swizzle.slang(10): error 30027: '_m22' is not a member of 'matrix'. c = m2._m22; ^~~~ -tests/diagnostics/matrix-swizzle.slang(11): error 30052: invalid swizzle pattern '_' on type 'int' +tests/diagnostics/matrix-swizzle.slang(11): error 30027: '_' is not a member of 'matrix'. c = m2._; // unfinished ^ -tests/diagnostics/matrix-swizzle.slang(12): error 30052: invalid swizzle pattern '_m' on type 'int' +tests/diagnostics/matrix-swizzle.slang(12): error 30027: '_m' is not a member of 'matrix'. c = m2._m; ^~ -tests/diagnostics/matrix-swizzle.slang(13): error 30052: invalid swizzle pattern '_1' on type 'int' +tests/diagnostics/matrix-swizzle.slang(13): error 30027: '_1' is not a member of 'matrix'. c = m2._1; ^~ -tests/diagnostics/matrix-swizzle.slang(14): error 30052: invalid swizzle pattern '_m1' on type 'int' +tests/diagnostics/matrix-swizzle.slang(14): error 30027: '_m1' is not a member of 'matrix'. c = m2._m1; ^~~ -tests/diagnostics/matrix-swizzle.slang(15): error 30052: invalid swizzle pattern '_m12_' on type 'int' +tests/diagnostics/matrix-swizzle.slang(15): error 30027: '_m12_' is not a member of 'matrix'. c = m2._m12_; ^~~~~ -tests/diagnostics/matrix-swizzle.slang(16): error 30052: invalid swizzle pattern '_m11_11' on type 'int' +tests/diagnostics/matrix-swizzle.slang(16): error 30027: '_m11_11' is not a member of 'matrix'. int2 c2 = m1._m11_11; // Mixing of 1 and 0-indexing ^~~~~~~ -tests/diagnostics/matrix-swizzle.slang(17): error 30052: invalid swizzle pattern '_11_11_11_11_11' on type 'int' +tests/diagnostics/matrix-swizzle.slang(17): error 30027: '_11_11_11_11_11' is not a member of 'matrix'. c = m1._11_11_11_11_11; // More than 4 elements ^~~~~~~~~~~~~~~ -tests/diagnostics/matrix-swizzle.slang(18): error 30052: invalid swizzle pattern 'x' on type 'int' +tests/diagnostics/matrix-swizzle.slang(18): error 30027: 'x' is not a member of 'matrix'. c = m1.x; // Invalid character ^ -tests/diagnostics/matrix-swizzle.slang(19): error 30052: invalid swizzle pattern '_x' on type 'int' +tests/diagnostics/matrix-swizzle.slang(19): error 30027: '_x' is not a member of 'matrix'. c = m1._x; ^~ -tests/diagnostics/matrix-swizzle.slang(20): error 30052: invalid swizzle pattern 'x123' on type 'int' +tests/diagnostics/matrix-swizzle.slang(20): error 30027: 'x123' is not a member of 'matrix'. c = m1.x123; ^~~~ } diff --git a/tests/language-server/member-completion-broken-syntax-3.slang b/tests/language-server/member-completion-broken-syntax-3.slang index 316afc5418..9d497f9e13 100644 --- a/tests/language-server/member-completion-broken-syntax-3.slang +++ b/tests/language-server/member-completion-broken-syntax-3.slang @@ -1,9 +1,13 @@ -//TEST:LANG_SERVER: -//COMPLETE:7,9 +//TEST:LANG_SERVER(filecheck=CHECK): float3 m() { float3 val = 0; +//COMPLETE:7,9 val. return val; -} \ No newline at end of file +} + +// CHECK: x +// CHECK: y +// CHECK: z \ No newline at end of file diff --git a/tests/language-server/vector-member.slang b/tests/language-server/vector-member.slang index 5d624e56d2..341544ac09 100644 --- a/tests/language-server/vector-member.slang +++ b/tests/language-server/vector-member.slang @@ -1,7 +1,12 @@ -//TEST:LANG_SERVER: +//TEST:LANG_SERVER(filecheck=CHECK): void f() { float4 v; //COMPLETE:6,7 v. } + +// CHECK: x +// CHECK: y +// CHECK: z +// CHECK: w \ No newline at end of file diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 10bc99017b..57328c210f 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -2037,9 +2037,13 @@ TestResult runLanguageServerTest(TestContext* context, TestInput& input) int callId = 2; for (auto line : lines) { - if (line.startsWith("//COMPLETE:")) + line = line.trimStart(); + if (!line.startsWith("//")) + continue; + line = line.tail(2).trimStart(); + if (line.startsWith("COMPLETE:")) { - auto arg = line.tail(UnownedStringSlice("//COMPLETE:").getLength()); + auto arg = line.tail(UnownedStringSlice("COMPLETE:").getLength()); Int linePos, colPos; parseLocation(arg, 0, linePos, colPos); @@ -2074,9 +2078,9 @@ TestResult runLanguageServerTest(TestContext* context, TestInput& input) } } } - else if (line.startsWith("//SIGNATURE:")) + else if (line.startsWith("SIGNATURE:")) { - auto arg = line.tail(UnownedStringSlice("//SIGNATURE:").getLength()); + auto arg = line.tail(UnownedStringSlice("SIGNATURE:").getLength()); Int linePos, colPos; parseLocation(arg, 0, linePos, colPos); @@ -2116,9 +2120,9 @@ TestResult runLanguageServerTest(TestContext* context, TestInput& input) } } } - else if (line.startsWith("//HOVER:")) + else if (line.startsWith("HOVER:")) { - auto arg = line.tail(UnownedStringSlice("//HOVER:").getLength()); + auto arg = line.tail(UnownedStringSlice("HOVER:").getLength()); Int linePos, colPos; parseLocation(arg, 0, linePos, colPos); @@ -2150,7 +2154,7 @@ TestResult runLanguageServerTest(TestContext* context, TestInput& input) actualOutputSB << "\ncontent:\n" << hover.contents.value << "\n"; } } - else if (line.startsWith("//DIAGNOSTICS")) + else if (line.startsWith("DIAGNOSTICS")) { if (!diagnosticsReceived) { From 2bc8b8fdd8977a7efca982b8f4672d8e1f9f595b Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 25 Feb 2025 13:24:41 -0800 Subject: [PATCH 7/8] Fix warning. --- source/slang/slang-language-server-completion.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp index a81ee39a92..1e985e3ee5 100644 --- a/source/slang/slang-language-server-completion.cpp +++ b/source/slang/slang-language-server-completion.cpp @@ -728,7 +728,6 @@ void CompletionContext::createSwizzleCandidates( } else if (auto scalarType = as(type)) { - const char* memberNames[1] = {"x"}; String typeStr; if (scalarType) typeStr = scalarType->toString(); From 544163b7667c6e231212293edfb3dbd0f9063233 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 26 Feb 2025 22:57:07 -0800 Subject: [PATCH 8/8] Add more tests. --- .../slang/slang-language-server-completion.cpp | 3 +-- tests/front-end/matrix-member.slang | 17 +++++++++++++++++ tests/front-end/scalar-member.slang | 17 +++++++++++++++++ tests/language-server/scalar-member.slang | 9 +++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tests/front-end/matrix-member.slang create mode 100644 tests/front-end/scalar-member.slang create mode 100644 tests/language-server/scalar-member.slang diff --git a/source/slang/slang-language-server-completion.cpp b/source/slang/slang-language-server-completion.cpp index 1e985e3ee5..1e5bae4b05 100644 --- a/source/slang/slang-language-server-completion.cpp +++ b/source/slang/slang-language-server-completion.cpp @@ -729,8 +729,7 @@ void CompletionContext::createSwizzleCandidates( else if (auto scalarType = as(type)) { String typeStr; - if (scalarType) - typeStr = scalarType->toString(); + typeStr = scalarType->toString(); LanguageServerProtocol::CompletionItem item; item.data = 0; item.detail = typeStr; diff --git a/tests/front-end/matrix-member.slang b/tests/front-end/matrix-member.slang new file mode 100644 index 0000000000..447fe715fd --- /dev/null +++ b/tests/front-end/matrix-member.slang @@ -0,0 +1,17 @@ +//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK):-output-using-type + +extension float2x2 +{ + float sum() { return this[0][0] + this[1][1]; } +} + +//TEST_INPUT: set outputBuffer = out ubuffer(data=[0 0 0 0], stride = 4) +RWStructuredBuffer outputBuffer; + +[numthreads(1,1,1)] +void computeMain() +{ + float2x2 v = {1,2,3,4}; + // CHECK: 5 + outputBuffer[0] = v.sum(); +} \ No newline at end of file diff --git a/tests/front-end/scalar-member.slang b/tests/front-end/scalar-member.slang new file mode 100644 index 0000000000..b85b8772c3 --- /dev/null +++ b/tests/front-end/scalar-member.slang @@ -0,0 +1,17 @@ +//TEST:COMPARE_COMPUTE(filecheck-buffer=CHECK):-output-using-type + +extension float +{ + float sum() { return this + 1; } +} + +//TEST_INPUT: set outputBuffer = out ubuffer(data=[0 0 0 0], stride = 4) +RWStructuredBuffer outputBuffer; + +[numthreads(1,1,1)] +void computeMain() +{ + float v = 10.0; + // CHECK: 11 + outputBuffer[0] = v.sum(); +} \ No newline at end of file diff --git a/tests/language-server/scalar-member.slang b/tests/language-server/scalar-member.slang new file mode 100644 index 0000000000..6b12ab8976 --- /dev/null +++ b/tests/language-server/scalar-member.slang @@ -0,0 +1,9 @@ +//TEST:LANG_SERVER(filecheck=CHECK): +void f() +{ + float v; +//COMPLETE:6,7 + v. +} + +// CHECK: x \ No newline at end of file