diff --git a/ets2panda/bindings/test/cases.ts b/ets2panda/bindings/test/cases.ts index 34736cfaf376c7c94ec06b31bdc628c77dbe8a1f..f64151085afce54abe6f7900149c14300577f8d8 100644 --- a/ets2panda/bindings/test/cases.ts +++ b/ets2panda/bindings/test/cases.ts @@ -44,7 +44,8 @@ export const testCases: TestCases = { '7': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition13.ets'), 664], '8': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition15.ets'), 617], '9': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition17.ets'), 677], - '10': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition18.ets'), 930] + '10': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition18.ets'), 930], + '11': [resolveTestPath('test/testcases/getDefinitionAtPosition/getDefinitionAtPosition19.ets'), 634] }, getSemanticDiagnostics: { expectedFilePath: resolveTestPath('test/expected/getSemanticDiagnostics.json'), diff --git a/ets2panda/bindings/test/expected/getDefinitionAtPosition.json b/ets2panda/bindings/test/expected/getDefinitionAtPosition.json index 74bd51b3c26f3f49e8838394eed310a2e59b72d1..73b133987606044ddbf101795a4e7b21a1110a15 100644 --- a/ets2panda/bindings/test/expected/getDefinitionAtPosition.json +++ b/ets2panda/bindings/test/expected/getDefinitionAtPosition.json @@ -48,5 +48,10 @@ "fileName": "text.d.ets", "start": 7586, "length": 4 + }, + "11": { + "fileName": "taskpool.ets", + "start": 686, + "length": 4 } } \ No newline at end of file diff --git a/ets2panda/bindings/test/expected/getSyntacticDiagnostics.json b/ets2panda/bindings/test/expected/getSyntacticDiagnostics.json index a6a34075cdf81f8f71c81ee7c4cc0d512aa43ed6..baa3c0c3ad58cc3a339fcb4b84e70d6fc018dd53 100644 --- a/ets2panda/bindings/test/expected/getSyntacticDiagnostics.json +++ b/ets2panda/bindings/test/expected/getSyntacticDiagnostics.json @@ -248,7 +248,7 @@ }, { "message": "Unexpected token '{'.", - "source": "return ((a) + (b));", + "source": "{\n return ((a) + (b));\n}", "range": { "start": { "line": 16, diff --git a/ets2panda/bindings/test/run_tests.ts b/ets2panda/bindings/test/run_tests.ts index ecb0adaa1651af5c538924461a4f880994f960d2..7d6edb92a1faabc95eaec38081f2301c8df40378 100644 --- a/ets2panda/bindings/test/run_tests.ts +++ b/ets2panda/bindings/test/run_tests.ts @@ -241,6 +241,21 @@ function findTextDefinitionPosition(sourceCode: string): number { throw new Error('Could not find Text definition in source code'); } +// CC-OFFNXT(huge_cyclomatic_complexity, huge_depth, huge_method) false positive +function findTaskDefinitionPosition(sourceCode: string): number { + const taskDefinitionPattern = /export\s+class\s+Task\s+{/; + const match = taskDefinitionPattern.exec(sourceCode); + if (match) { + const classTaskPattern = /class\s+Task\s+{/; + const subMatch = classTaskPattern.exec(sourceCode.substring(match.index)); + if (subMatch) { + const positionOfT = match.index + subMatch.index + 'class '.length; + return positionOfT; + } + } + throw new Error('Could not find Task definition in source code'); +} + function compareGetDefinitionResult(testName: string, actual: any, expected: Record): boolean { // This is the definition info for the UI component. // File in the SDK might changed, so the offset needs to be checked dynamically. @@ -255,6 +270,19 @@ function compareGetDefinitionResult(testName: string, actual: any, expected: Rec }; return compareResultsHelper(testName, normalizeData(actual), expectedResult); } + // This is the definition info for the class in std library. + // File in the SDK might changed, so the offset needs to be checked dynamically. + if (expected['fileName'] === 'taskpool.ets') { + const actualDef = actual as LspDefinitionData; + const fileName = actualDef.fileName as string; + const fileContent = fs.readFileSync(fileName, 'utf8'); + const expectedStart = findTaskDefinitionPosition(fileContent); + const expectedResult = { + ...expected, + start: expectedStart + }; + return compareResultsHelper(testName, normalizeData(actual), expectedResult); + } return compareResultsHelper(testName, normalizeData(actual), expected); } diff --git a/ets2panda/bindings/test/testcases/getDefinitionAtPosition/getDefinitionAtPosition19.ets b/ets2panda/bindings/test/testcases/getDefinitionAtPosition/getDefinitionAtPosition19.ets new file mode 100644 index 0000000000000000000000000000000000000000..fc811ab595deb7697c8748ef83cea4f1b3a609eb --- /dev/null +++ b/ets2panda/bindings/test/testcases/getDefinitionAtPosition/getDefinitionAtPosition19.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const task = new taskpool.Task(()=>{}); diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index 219cb116eb826c947fb948a757aa7b9423aae787..a514a83a25e7596c3648e1d8137caf1acf7a97fa 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -54,19 +54,24 @@ DefinitionInfo GetDefinitionAtPosition(es2panda_Context *context, size_t positio auto declInfo = GetDefinitionAtPositionImpl(context, position); DefinitionInfo result {}; auto node = declInfo.first; + auto targetNode = declInfo.first->FindChild([&declInfo](ir::AstNode *childNode) { + return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == declInfo.second; + }); + std::string name; while (node != nullptr) { + if (node->Range().start.Program() != nullptr) { + name = std::string(node->Range().start.Program()->SourceFile().GetAbsolutePath().Utf8()); + break; + } if (node->IsETSModule()) { - auto name = std::string(node->AsETSModule()->Program()->SourceFilePath()); - auto targetNode = declInfo.first->FindChild([&declInfo](ir::AstNode *childNode) { - return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == declInfo.second; - }); - if (targetNode != nullptr) { - result = {name, targetNode->Start().index, targetNode->End().index - targetNode->Start().index}; - } + name = std::string(node->AsETSModule()->Program()->SourceFilePath()); break; } node = node->Parent(); } + if (targetNode != nullptr) { + result = {name, targetNode->Start().index, targetNode->End().index - targetNode->Start().index}; + } return result; } diff --git a/ets2panda/test/unit/lsp/get_definition_and_bound_span_test.cpp b/ets2panda/test/unit/lsp/get_definition_and_bound_span_test.cpp index af99f95900441c81bf160c765291950d0fe08f4f..6476359c37747437286cdd1c20a68b02522f08fd 100644 --- a/ets2panda/test/unit/lsp/get_definition_and_bound_span_test.cpp +++ b/ets2panda/test/unit/lsp/get_definition_and_bound_span_test.cpp @@ -25,7 +25,7 @@ class LSPGetDefinitionAndBoundSpanTests : public LSPAPITests {}; TEST_F(LSPGetDefinitionAndBoundSpanTests, GetDefinitionAndBoundSpan_FunctionReference) { - const auto fileName = "definition1.ets"; + const auto fileName = "GetDefinitionAndBoundSpan1.ets"; const auto fileContent = R"( function sum(a: number, b: number): number { return a + b; @@ -44,11 +44,12 @@ let total = sum(5, 10); auto filePaths = CreateTempFile(files, texts); ark::es2panda::lsp::Initializer initializer; - es2panda_Context *ctx = initializer.CreateContext(files.at(index0).c_str(), ES2PANDA_STATE_CHECKED, fileContent); + es2panda_Context *ctx = initializer.CreateContext(filePaths.at(index0).c_str(), ES2PANDA_STATE_CHECKED); const auto result = ark::es2panda::lsp::GetDefinitionAndBoundSpan(ctx, offset); EXPECT_FALSE(result.definitionInfo.fileName.empty()); + EXPECT_EQ(result.definitionInfo.fileName, filePaths.at(index0)); EXPECT_EQ(result.definitionInfo.length, index3); EXPECT_EQ(result.boundSpan.length, index3); EXPECT_EQ(result.definitionInfo.start + result.definitionInfo.length, index13); @@ -60,7 +61,7 @@ let total = sum(5, 10); TEST_F(LSPGetDefinitionAndBoundSpanTests, GetDefinitionAndBoundSpan_FunctionReferenceTwoFile) { - std::vector fileNames = {"lsp_api_test_export_1.ets", "lsp_api_test_file_1.ets"}; + std::vector fileNames = {"GetDefinitionAndBoundSpan_export.ets", "GetDefinitionAndBoundSpan2.ets"}; std::vector texts = { R"(export function A(a:number, b:number): number { return a + b; @@ -68,8 +69,8 @@ TEST_F(LSPGetDefinitionAndBoundSpanTests, GetDefinitionAndBoundSpan_FunctionRefe export function B(a:number, b:number): number { return a + b; })", - R"(import {A} from "./lsp_api_test_export_1"; -import {B} from "./lsp_api_test_export_1.ets"; + R"(import {A} from "./GetDefinitionAndBoundSpan_export"; +import {B} from "./GetDefinitionAndBoundSpan_export.ets"; A(1, 2); B(1, 2);)"}; @@ -77,15 +78,13 @@ B(1, 2);)"}; int const expectedFileCount = 2; ASSERT_EQ(filePaths.size(), expectedFileCount); - const size_t offset = 94; + const size_t offset = 116; const size_t index0 = 0; const size_t index1 = 1; const size_t index13 = 17; ark::es2panda::lsp::Initializer initializer; - es2panda_Context *ctx = - initializer.CreateContext(filePaths.at(index1).c_str(), ES2PANDA_STATE_CHECKED, texts.at(index1).c_str()); + es2panda_Context *ctx = initializer.CreateContext(filePaths.at(index1).c_str(), ES2PANDA_STATE_CHECKED); - std::cout << "offset: " << offset << std::endl; const auto result = ark::es2panda::lsp::GetDefinitionAndBoundSpan(ctx, offset); EXPECT_FALSE(result.definitionInfo.fileName.empty()); diff --git a/ets2panda/test/unit/lsp/get_definition_at_position_test.cpp b/ets2panda/test/unit/lsp/get_definition_at_position_test.cpp index 77ee5772736bc62fc8cb9df1a5f1c1a5e48857cf..e5636a2807b5ed65d5c60a5549cb7074290a336a 100644 --- a/ets2panda/test/unit/lsp/get_definition_at_position_test.cpp +++ b/ets2panda/test/unit/lsp/get_definition_at_position_test.cpp @@ -294,3 +294,23 @@ a.Foo(1, 2);)"}; ASSERT_EQ(result1.start, expectedStart1); ASSERT_EQ(result1.length, expectedLength1); } + +TEST_F(LspGetDefTests, GetDefinitionAtPositionForStdLibraryTaskPool) +{ + std::vector files = {"getDefinitionAtPositionForStdLibraryTaskPool.ets"}; + std::vector texts = {R"(const task = new taskpool.Task(()=>{});)"}; + auto filePaths = CreateTempFile(files, texts); + size_t const expectedFileCount = 1; + ASSERT_EQ(filePaths.size(), expectedFileCount); + + LSPAPI const *lspApi = GetImpl(); + size_t const offset = 21; + Initializer initializer = Initializer(); + auto ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + auto result = lspApi->getDefinitionAtPosition(ctx, offset); + initializer.DestroyContext(ctx); + std::string expectedFileName = "taskpool.ets"; + size_t const expectedLength = 8; + ASSERT_TRUE(result.fileName.find(expectedFileName) != std::string::npos); + ASSERT_EQ(result.length, expectedLength); +}