diff --git a/ets2panda/lsp/include/node_matchers.h b/ets2panda/lsp/include/node_matchers.h index 6fdadbebb2ae7c83b83f620bd5826a2cb7f574fd..ca378fba8b55b271b0c1f57eab32a643b7551d23 100644 --- a/ets2panda/lsp/include/node_matchers.h +++ b/ets2panda/lsp/include/node_matchers.h @@ -70,6 +70,9 @@ bool MatchSwitchStatement(ir::AstNode *childNode, const NodeInfo *info); bool MatchEtsParameterExpression(ir::AstNode *childNode, const NodeInfo *info); bool MatchTsNonNullExpression(ir::AstNode *childNode, const NodeInfo *info); bool MatchFunctionDeclaration(ir::AstNode *childNode, const NodeInfo *info); +bool MatchETSImportDeclaration(ir::AstNode *childNode, const NodeInfo *info); +bool MatchTSQualifiedName(ir::AstNode *childNode, const NodeInfo *info); + void HandleIdentifier(ir::AstNode *node, std::vector &result); void HandleMemberExpression(ir::AstNode *node, std::vector &result); void HandleSpeadeElement(ir::AstNode *node, std::vector &result); diff --git a/ets2panda/lsp/src/node_matchers.cpp b/ets2panda/lsp/src/node_matchers.cpp index 33ce4f1c868b959b4a031f0bb401f311dbfcde94..47b0e7d531947c3a8eeca78d4fe09c6171abee1f 100644 --- a/ets2panda/lsp/src/node_matchers.cpp +++ b/ets2panda/lsp/src/node_matchers.cpp @@ -517,6 +517,22 @@ bool MatchFunctionDeclaration(ir::AstNode *childNode, const NodeInfo *info) return std::string(childNode->AsFunctionDeclaration()->Function()->Id()->Name()) == info->name; } +bool MatchETSImportDeclaration(ir::AstNode *childNode, const NodeInfo *info) +{ + if (!childNode->IsETSImportDeclaration()) { + return false; + } + return std::string(childNode->AsETSImportDeclaration()->Source()->ToString()) == info->name; +} + +bool MatchTSQualifiedName(ir::AstNode *childNode, const NodeInfo *info) +{ + if (!childNode->IsTSQualifiedName()) { + return false; + } + return std::string(childNode->AsTSQualifiedName()->Right()->ToString()) == info->name; +} + ir::AstNode *ExtractIdentifierFromNode(ir::AstNode *node, const NodeInfo *info) { if (node == nullptr) { @@ -678,6 +694,11 @@ static std::unordered_map GetFunctionAndVariable [](ir::AstNode *node, const NodeInfo *) { return node->IsScriptFunction() ? node->AsScriptFunction()->Id() : node; }}, + {ir::AstNodeType::FUNCTION_DECLARATION, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsFunctionDeclaration() + ? node->AsFunctionDeclaration()->Function()->Id() : node; + }}, {ir::AstNodeType::VARIABLE_DECLARATOR, [](ir::AstNode *node, const NodeInfo *) { return node->IsVariableDeclarator() ? node->AsVariableDeclarator()->Id()->AsIdentifier() : node; @@ -728,6 +749,21 @@ static std::unordered_map GetAnnotationAndImport // clang-format on } +static std::unordered_map GetEtsImportAndTsQualifiedExtractors() +{ + // clang-format off + return {{ir::AstNodeType::ETS_IMPORT_DECLARATION, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsETSImportDeclaration() ? node->AsETSImportDeclaration()->Source() : node; + }}, + {ir::AstNodeType::TS_QUALIFIED_NAME, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsTSQualifiedName() ? node->AsTSQualifiedName()->Right() : node; + }} + }; + // clang-format on +} + const std::unordered_map &GetNodeExtractors() { static std::unordered_map nodeExtractors; @@ -741,6 +777,7 @@ const std::unordered_map &GetNodeExtractors() auto typeRefExtractors = GetTypeReferenceExtractors(); auto funcVarExtractors = GetFunctionAndVariableExtractors(); auto annotationImportExtractors = GetAnnotationAndImportExtractors(); + auto importandqualifiedExtractors = GetEtsImportAndTsQualifiedExtractors(); nodeExtractors.insert(classExtractors.begin(), classExtractors.end()); nodeExtractors.insert(enumExtractors.begin(), enumExtractors.end()); @@ -749,6 +786,7 @@ const std::unordered_map &GetNodeExtractors() nodeExtractors.insert(typeRefExtractors.begin(), typeRefExtractors.end()); nodeExtractors.insert(funcVarExtractors.begin(), funcVarExtractors.end()); nodeExtractors.insert(annotationImportExtractors.begin(), annotationImportExtractors.end()); + nodeExtractors.insert(importandqualifiedExtractors.begin(), importandqualifiedExtractors.end()); initialized = true; } @@ -796,7 +834,9 @@ const std::unordered_map &GetNodeMatchers() {ir::AstNodeType::ETS_PARAMETER_EXPRESSION, MatchEtsParameterExpression}, {ir::AstNodeType::SWITCH_STATEMENT, MatchSwitchStatement}, {ir::AstNodeType::TS_NON_NULL_EXPRESSION, MatchTsNonNullExpression}, - {ir::AstNodeType::FUNCTION_DECLARATION, MatchFunctionDeclaration}}; + {ir::AstNodeType::FUNCTION_DECLARATION, MatchFunctionDeclaration}, + {ir::AstNodeType::ETS_IMPORT_DECLARATION, MatchETSImportDeclaration}, + {ir::AstNodeType::TS_QUALIFIED_NAME, MatchTSQualifiedName}}; return NODE_MATCHERS; } diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index 0efe3075532692e53680365e9f34f2840fcc8552..dfd17f7ebaa0226005df1c39f67c792c085e0708 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -525,4 +525,8 @@ ets2panda_add_gtest(lsp_api_get_node_info_class_property_import_test CPP_SOURCES ets2panda_add_gtest(lsp_api_get_rename_locations_from_node_test CPP_SOURCES get_rename_locations_from_node_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_ts_qualified_test CPP_SOURCES + get_node_ts_qualified_test.cpp ) \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_import_test.cpp b/ets2panda/test/unit/lsp/get_node_import_test.cpp index 7d918cd3857043d07c97fb0915a3565cfdc488f0..3189712eea4a88109a0c61e2b2dee25947b0bbf2 100644 --- a/ets2panda/test/unit/lsp/get_node_import_test.cpp +++ b/ets2panda/test/unit/lsp/get_node_import_test.cpp @@ -46,7 +46,7 @@ export function add(a: number, b: number): number { } static void GenerateContexts(Initializer &initializer) { - contexts_ = initializer.CreateContext("GetNodeImportTest.ets", ES2PANDA_STATE_CHECKED, sourceCode_.c_str()); + contexts_ = initializer.CreateContext("GetNodeImportTest.ets", ES2PANDA_STATE_PARSED, sourceCode_.c_str()); } // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) static inline es2panda_Context *contexts_ = nullptr; @@ -97,4 +97,18 @@ TEST_F(LspGetNodeImportTests, GetImportNamespaceSpecifier) ASSERT_NE(extractedText.find(moduleName), std::string::npos); } +TEST_F(LspGetNodeImportTests, GetETSImportDeclarations) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "std/math"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::ETS_IMPORT_DECLARATION}); + std::vector nodeInfoPtrs; + nodeInfoPtrs.push_back(&nodeInfos[0]); + + auto res = lspApi->getDefinitionDataFromNode(contexts_, nodeInfoPtrs); + std::string extractedText(sourceCode_.substr(res.start, res.length)); + ASSERT_NE(extractedText.find(moduleName), std::string::npos); +} + } // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_ts_qualified_test.cpp b/ets2panda/test/unit/lsp/get_node_ts_qualified_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6d48c1781982a71a16070561ed9ffee36aa37698 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_ts_qualified_test.cpp @@ -0,0 +1,90 @@ +/** + * 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. + */ + +#include "ir/astNode.h" +#include "lsp/include/api.h" +#include "lsp_api_test.h" +#include "public/es2panda_lib.h" +#include "public/public.h" +#include "ir/ets/etsReExportDeclaration.h" +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeTsQualifiedTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + sourceCode_ = R"(export namespace HTTP { + export namespace Status { + export let Code = 200; + } +} +interface Response { + status: HTTP.Status.Code; +})"; + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + sourceCode_ = ""; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = + initializer.CreateContext("GetNodeTsQualifiedTest.ts", ES2PANDA_STATE_PARSED, sourceCode_.c_str()); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + static inline std::string sourceCode_; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeTsQualifiedTests, GetNodeTsQualifiedTest1) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "Code"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::TS_QUALIFIED_NAME}); + std::vector nodeInfoPtrs; + nodeInfoPtrs.push_back(&nodeInfos[0]); + + auto res = lspApi->getDefinitionDataFromNode(contexts_, nodeInfoPtrs); + std::string extractedText(sourceCode_.substr(res.start, res.length)); + ASSERT_NE(extractedText.find(moduleName), std::string::npos); +} + +TEST_F(LspGetNodeTsQualifiedTests, GetNodeTsQualifiedTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "Status"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::TS_QUALIFIED_NAME}); + std::vector nodeInfoPtrs; + nodeInfoPtrs.push_back(&nodeInfos[0]); + + auto res = lspApi->getDefinitionDataFromNode(contexts_, nodeInfoPtrs); + std::string extractedText(sourceCode_.substr(res.start, res.length)); + ASSERT_NE(extractedText.find(moduleName), std::string::npos); +} + +} // namespace \ No newline at end of file