From fe88d02f107ad3df77f190946a88eb98d381ebb5 Mon Sep 17 00:00:00 2001 From: yp9522 Date: Tue, 19 Aug 2025 17:50:41 +0800 Subject: [PATCH] Lsp supports arkts for import Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICTPRM Signed-off-by: yp9522 --- ets2panda/lsp/include/node_matchers.h | 4 + ets2panda/lsp/src/node_matchers.cpp | 46 +++++++- ets2panda/test/unit/lsp/CMakeLists.txt | 8 ++ .../test/unit/lsp/get_node_import_test.cpp | 100 ++++++++++++++++++ .../unit/lsp/get_node_ts_type_param_test.cpp | 70 ++++++++++++ 5 files changed, 226 insertions(+), 2 deletions(-) mode change 100755 => 100644 ets2panda/lsp/src/node_matchers.cpp create mode 100644 ets2panda/test/unit/lsp/get_node_import_test.cpp create mode 100644 ets2panda/test/unit/lsp/get_node_ts_type_param_test.cpp diff --git a/ets2panda/lsp/include/node_matchers.h b/ets2panda/lsp/include/node_matchers.h index a57247b70c..f6742d40e5 100755 --- a/ets2panda/lsp/include/node_matchers.h +++ b/ets2panda/lsp/include/node_matchers.h @@ -37,6 +37,10 @@ bool MatchTSTypeAliasDeclaration(ir::AstNode *childNode, const NodeInfo *info); bool MatchExportSpecifier(ir::AstNode *childNode, const NodeInfo *info); bool MatchMemberExpression(ir::AstNode *childNode, const NodeInfo *info); bool MatchTSClassImplements(ir::AstNode *childNode, const NodeInfo *info); +bool MatchImportSpecifier(ir::AstNode *childNode, const NodeInfo *info); +bool MatchImportDefaultSpecifier(ir::AstNode *childNode, const NodeInfo *info); +bool MatchImportNamespaceSpecifier(ir::AstNode *childNode, const NodeInfo *info); +bool MatchTSTypeParameter(ir::AstNode *childNode, const NodeInfo *info); ir::AstNode *ExtractExportSpecifierIdentifier(ir::AstNode *node, const NodeInfo *info); ir::AstNode *ExtractTSClassImplementsIdentifier(ir::AstNode *node, const NodeInfo *info); diff --git a/ets2panda/lsp/src/node_matchers.cpp b/ets2panda/lsp/src/node_matchers.cpp old mode 100755 new mode 100644 index f50d62cd0e..f3c796edf0 --- a/ets2panda/lsp/src/node_matchers.cpp +++ b/ets2panda/lsp/src/node_matchers.cpp @@ -149,6 +149,29 @@ ir::AstNode *ExtractTSClassImplementsIdentifier(ir::AstNode *node, const NodeInf return node; } +bool MatchImportSpecifier(ir::AstNode *childNode, const NodeInfo *info) +{ + return childNode->IsImportSpecifier() && + std::string(childNode->AsImportSpecifier()->Imported()->Name()) == info->name; +} + +bool MatchImportDefaultSpecifier(ir::AstNode *childNode, const NodeInfo *info) +{ + return childNode->IsImportDefaultSpecifier() && + std::string(childNode->AsImportDefaultSpecifier()->Local()->Name()) == info->name; +} + +bool MatchImportNamespaceSpecifier(ir::AstNode *childNode, const NodeInfo *info) +{ + return childNode->IsImportNamespaceSpecifier() && + std::string(childNode->AsImportNamespaceSpecifier()->Local()->Name()) == info->name; +} + +bool MatchTSTypeParameter(ir::AstNode *childNode, const NodeInfo *info) +{ + return childNode->IsTSTypeParameter() && std::string(childNode->AsTSTypeParameter()->Name()->Name()) == info->name; +} + const std::unordered_map nodeExtractors = { {ir::AstNodeType::CLASS_DEFINITION, [](ir::AstNode *node, const NodeInfo *) { @@ -189,7 +212,22 @@ const std::unordered_map nodeExtractors = { return node->IsMemberExpression() ? node->AsMemberExpression()->Property()->AsIdentifier() : node; }}, {ir::AstNodeType::TS_CLASS_IMPLEMENTS, - [](ir::AstNode *node, const NodeInfo *info) { return ExtractTSClassImplementsIdentifier(node, info); }}}; + [](ir::AstNode *node, const NodeInfo *info) { return ExtractTSClassImplementsIdentifier(node, info); }}, + {ir::AstNodeType::IMPORT_SPECIFIER, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsImportSpecifier() ? node->AsImportSpecifier()->Imported() : node; + }}, + {ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsImportDefaultSpecifier() ? node->AsImportDefaultSpecifier()->Local() : node; + }}, + {ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER, + [](ir::AstNode *node, const NodeInfo *) { + return node->IsImportNamespaceSpecifier() ? node->AsImportNamespaceSpecifier()->Local() : node; + }}, + {ir::AstNodeType::TS_TYPE_PARAMETER, [](ir::AstNode *node, const NodeInfo *) { + return node->IsTSTypeParameter() ? node->AsTSTypeParameter()->Name() : node; + }}}; ir::AstNode *ExtractIdentifierFromNode(ir::AstNode *node, const NodeInfo *info) { @@ -215,5 +253,9 @@ const std::unordered_map nodeMatchers = { {ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION, MatchTSTypeAliasDeclaration}, {ir::AstNodeType::EXPORT_SPECIFIER, MatchExportSpecifier}, {ir::AstNodeType::MEMBER_EXPRESSION, MatchMemberExpression}, - {ir::AstNodeType::TS_CLASS_IMPLEMENTS, MatchTSClassImplements}}; + {ir::AstNodeType::TS_CLASS_IMPLEMENTS, MatchTSClassImplements}, + {ir::AstNodeType::IMPORT_SPECIFIER, MatchImportSpecifier}, + {ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER, MatchImportDefaultSpecifier}, + {ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER, MatchImportNamespaceSpecifier}, + {ir::AstNodeType::TS_TYPE_PARAMETER, MatchTSTypeParameter}}; } // namespace ark::es2panda::lsp \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/CMakeLists.txt b/ets2panda/test/unit/lsp/CMakeLists.txt index d896777b56..20bf8738aa 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -381,3 +381,11 @@ ets2panda_add_gtest(lsp_api_get_node_export_test CPP_SOURCES ets2panda_add_gtest(lsp_api_get_node_ts_class_Implements_test CPP_SOURCES get_node_ts_class_Implements_test.cpp ) + +ets2panda_add_gtest(lsp_api_get_node_import_test CPP_SOURCES + get_node_import_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_ts_type_param_test CPP_SOURCES + get_node_ts_type_param_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 new file mode 100644 index 0000000000..4783896644 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_import_test.cpp @@ -0,0 +1,100 @@ +/** + * 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 + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeImportTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + sourceCode_ = R"(import { PI } from "std/math"; +import * as All from "std/math"; +import CommonEventManager from '@ohos.commonEventManager'; +export function add(a: number, b: number): number { + return a + b; +})"; + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + sourceCode_ = ""; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetNodeImportTest.ets", ES2PANDA_STATE_CHECKED, 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(LspGetNodeImportTests, GetImportSpecifier) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "PI"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::IMPORT_SPECIFIER}); + 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(LspGetNodeImportTests, GetImportDefaultSpecifier) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "CommonEventManager"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER}); + 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(LspGetNodeImportTests, GetImportNamespaceSpecifier) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "All"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER}); + 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_type_param_test.cpp b/ets2panda/test/unit/lsp/get_node_ts_type_param_test.cpp new file mode 100644 index 0000000000..238c612b02 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_ts_type_param_test.cpp @@ -0,0 +1,70 @@ +/** + * 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 + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeTypeParamTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + sourceCode_ = R"(function identity(arg: T): T { +return arg; +} +const result1 = identity("hello");)"; + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + sourceCode_ = ""; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetNodeTsTypeParamTest.ts", ES2PANDA_STATE_CHECKED, 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(LspGetNodeTypeParamTests, GetTSTypeParameter) +{ + LSPAPI const *lspApi = GetImpl(); + const std::string moduleName = "T"; + std::vector nodeInfos; + nodeInfos.emplace_back(NodeInfo {moduleName, ark::es2panda::ir::AstNodeType::TS_TYPE_PARAMETER}); + 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 -- Gitee