diff --git a/ets2panda/bindings/src/lsp/lspNode.ts b/ets2panda/bindings/src/lsp/lspNode.ts index 32111b13d6f9c8f16da13924fca64a93c71bc999..cdb70d290817c368fc2b4682f109f869bae12b1e 100644 --- a/ets2panda/bindings/src/lsp/lspNode.ts +++ b/ets2panda/bindings/src/lsp/lspNode.ts @@ -188,15 +188,16 @@ export class LspDefinitionData extends LspNode { } export class LspReferenceData extends LspNode { - constructor(peer: KNativePointer) { + constructor(peer: KNativePointer, filePath?: string) { super(peer); - this.fileName = unpackString(global.es2panda._getReferenceFileName(peer)); + this.fileName = filePath ? filePath : unpackString(global.es2panda._getReferenceFileName(peer)); this.start = global.es2panda._getReferenceStart(peer); this.length = global.es2panda._getReferenceLength(peer); } readonly fileName: String; readonly start: KInt; readonly length: KInt; + nodeInfos?: NodeInfo[]; } export class LspDeclInfo extends LspNode { @@ -986,9 +987,9 @@ export class LspRenameInfoFailure extends LspNode { export type LspRenameInfoType = LspRenameInfoSuccess | LspRenameInfoFailure; export class LspRenameLocation extends LspNode { - constructor(peer: KNativePointer) { + constructor(peer: KNativePointer, filePath?: string) { super(peer); - this.fileName = unpackString(global.es2panda._getRenameLocationFileName(peer)); + this.fileName = filePath ? filePath : unpackString(global.es2panda._getRenameLocationFileName(peer)); this.start = global.es2panda._getRenameLocationStart(peer); this.end = global.es2panda._getRenameLocationEnd(peer); this.line = global.es2panda._getRenameLocationLine(peer); @@ -1005,6 +1006,7 @@ export class LspRenameLocation extends LspNode { readonly line: number; readonly prefixText?: string; readonly suffixText?: string; + nodeInfos?: NodeInfo[]; } export function toAstNodeType(str: string) { diff --git a/ets2panda/bindings/src/lsp/lsp_helper.ts b/ets2panda/bindings/src/lsp/lsp_helper.ts index e5fab550454031e98f113fb2ad98fffe58e01319..8b62824947ebbdfe1cae4b1c41def289dcd44554 100644 --- a/ets2panda/bindings/src/lsp/lsp_helper.ts +++ b/ets2panda/bindings/src/lsp/lsp_helper.ts @@ -49,7 +49,8 @@ import { LspRenameInfoSuccess, LspRenameInfoFailure, LspSourceLocation, - LspNodeInfo + LspNodeInfo, + LspNode, } from './lspNode'; import { passStringArray, unpackString } from '../common/private'; import { Es2pandaContextState } from '../generated/Es2pandaEnums'; @@ -260,7 +261,7 @@ export class Lsp { getDefinitionAtPosition(filename: String, offset: number, nodeInfos?: NodeInfo[]): LspDefinitionData { if (nodeInfos) { - return this.getDefinitionAtPositionByNodeInfos(filename, nodeInfos); + return this.getAtPositionByNodeInfos(filename, nodeInfos, 'definition') as LspDefinitionData; } let ptr: KPointer; const [cfg, ctx] = this.createContext(filename); @@ -270,39 +271,13 @@ export class Lsp { this.destroyContext(cfg, ctx); } const result = new LspDefinitionData(ptr); - const moduleName = this.moduleInfos[filename.valueOf()].packageName; - const declgenOutDir = this.buildConfigs[moduleName].declgenOutDir; - if (result.fileName.endsWith(DECL_ETS_SUFFIX) && result.fileName.startsWith(declgenOutDir)) { - let ptr: KPointer; - const [declFileCfg, declFileCtx] = this.createContext(result.fileName, false); - try { - ptr = global.es2panda._getNodeInfosByDefinitionData(declFileCtx, result.start); - result.nodeInfos = new NativePtrDecoder().decode(ptr).map((elPeer: KNativePointer) => { - return new LspNodeInfo(elPeer); - }); - } finally { - this.destroyContext(declFileCfg, declFileCtx); - } + const nodeInfoTemp: NodeInfo[] = this.getNodeInfos(filename, result.fileName, result.start); + if (nodeInfoTemp.length > 0) { + result.nodeInfos = nodeInfoTemp; } return result; } - private getDefinitionAtPositionByNodeInfos(declFilePath: String, nodeInfos: NodeInfo[]): LspDefinitionData { - let ptr: KPointer; - let nodeInfoPtrs: KPointer[] = []; - const sourceFilePath = this.declFileMap[declFilePath.valueOf()]; - const [cfg, ctx] = this.createContext(sourceFilePath, false); - try { - nodeInfos.forEach((nodeInfo) => { - nodeInfoPtrs.push(global.es2panda._CreateNodeInfoPtr(nodeInfo.name, nodeInfo.kind)); - }); - ptr = global.es2panda._getDefinitionDataFromNode(ctx, passPointerArray(nodeInfoPtrs), nodeInfoPtrs.length); - } finally { - this.destroyContext(cfg, ctx); - } - return new LspDefinitionData(ptr, sourceFilePath); - } - private getMergedCompileFiles(filename: String): string[] { const moduleInfo = this.moduleInfos[path.resolve(filename.valueOf())]; return moduleInfo ? [...moduleInfo.compileFiles, ...moduleInfo.depModuleCompileFiles] : []; @@ -369,7 +344,10 @@ export class Lsp { return result; } - getReferencesAtPosition(filename: String, offset: number): LspReferenceData[] { + getReferencesAtPosition(filename: String, offset: number, nodeInfos?: NodeInfo[]): LspReferenceData[] { + if (nodeInfos) { + return [this.getAtPositionByNodeInfos(filename, nodeInfos, 'reference') as LspReferenceData]; + } let declInfo: KPointer; const [cfg, searchCtx] = this.createContext(filename); try { @@ -388,11 +366,68 @@ export class Lsp { this.destroyContext(cfg, ctx); } let refs = new LspReferences(ptr); - result.push(...refs.referenceInfos); + if (refs.referenceInfos.length === 0) { + continue; + } + refs.referenceInfos.forEach((ref) => { + const nodeInfoTemp: NodeInfo[] = this.getNodeInfos(filename, ref.fileName, ref.start); + if (nodeInfoTemp.length > 0) { + ref.nodeInfos = nodeInfoTemp; + } + result.push(ref); + }); } return Array.from(new Set(result)); } + private getNodeInfos(paramFileName: String, fileName: String, start: number): LspNodeInfo[] { + let nodeInfos: LspNodeInfo[] = []; + const moduleName = this.moduleInfos[paramFileName.valueOf()].packageName; + const declgenOutDir = this.buildConfigs[moduleName].declgenOutDir; + if (fileName.endsWith(DECL_ETS_SUFFIX) && fileName.startsWith(declgenOutDir)) { + let ptr: KPointer; + const [declFileCfg, declFileCtx] = this.createContext(fileName, false); + try { + ptr = global.es2panda._getNodeInfosByDefinitionData(declFileCtx, start); + nodeInfos = new NativePtrDecoder().decode(ptr).map((elPeer: KNativePointer) => { + return new LspNodeInfo(elPeer); + }); + } finally { + this.destroyContext(declFileCfg, declFileCtx); + } + } + return nodeInfos; + } + + private getAtPositionByNodeInfos( + declFilePath: String, + nodeInfos: NodeInfo[], + type: 'definition' | 'reference' | 'renameLocation' + ): LspNode { + let ptr: KPointer; + let nodeInfoPtrs: KPointer[] = []; + const sourceFilePath = this.declFileMap[declFilePath.valueOf()]; + const [cfg, ctx] = this.createContext(sourceFilePath, false); + try { + nodeInfos.forEach((nodeInfo) => { + nodeInfoPtrs.push(global.es2panda._CreateNodeInfoPtr(nodeInfo.name, nodeInfo.kind)); + }); + ptr = global.es2panda._getDefinitionDataFromNode(ctx, passPointerArray(nodeInfoPtrs), nodeInfoPtrs.length); + } finally { + this.destroyContext(cfg, ctx); + } + switch (type) { + case 'definition': + return new LspDefinitionData(ptr, sourceFilePath); + case 'reference': + return new LspReferenceData(ptr, sourceFilePath); + case 'renameLocation': + return new LspRenameLocation(ptr, sourceFilePath); + default: + return new LspNodeInfo(ptr); + } + } + getTypeHierarchies(filename: String, offset: number): LspTypeHierarchiesInfo | null { let ptr: KPointer; const [cfg, ctx] = this.createContext(filename); @@ -669,7 +704,10 @@ export class Lsp { return result; } - findRenameLocations(filename: String, offset: number): LspRenameLocation[] { + findRenameLocations(filename: String, offset: number, nodeInfos?: NodeInfo[]): LspRenameLocation[] { + if (nodeInfos) { + return [this.getAtPositionByNodeInfos(filename, nodeInfos, 'reference') as LspRenameLocation]; + } const [cfg, ctx] = this.createContext(filename); const needsCrossFileRename = global.es2panda._needsCrossFileRename(ctx, offset); if (!needsCrossFileRename) { @@ -701,6 +739,12 @@ export class Lsp { const result: LspRenameLocation[] = new NativePtrDecoder().decode(ptr).map((elPeer: KPointer) => { return new LspRenameLocation(elPeer); }); + result.forEach((ref) => { + const nodeInfoTemp: NodeInfo[] = this.getNodeInfos(filename, ref.fileName, ref.start); + if (nodeInfoTemp.length > 0) { + ref.nodeInfos = nodeInfoTemp; + } + }); for (let i = 0; i < fileContexts.length; i++) { this.destroyContext(fileConfigs[i], fileContexts[i]); } diff --git a/ets2panda/lsp/include/node_matchers.h b/ets2panda/lsp/include/node_matchers.h old mode 100755 new mode 100644 index 7555dd3f8a9729c04a43dced45480017aefb3aec..6fdadbebb2ae7c83b83f620bd5826a2cb7f574fd --- a/ets2panda/lsp/include/node_matchers.h +++ b/ets2panda/lsp/include/node_matchers.h @@ -21,9 +21,18 @@ #include "ir/astNode.h" #include "api.h" +#define DEFINE_SIMPLE_HANDLER(FunctionName, NodeType, NameAccessor, NodeTypeEnum) \ + void FunctionName(ir::AstNode *node, std::vector &result) \ + { \ + if (auto ident = node->As##NodeType()->NameAccessor()) { \ + result.emplace_back(std::string(ident->Name()), NodeTypeEnum); \ + } \ + } + namespace ark::es2panda::lsp { using NodeMatcher = std::function; using NodeExtractor = ir::AstNode *(*)(ir::AstNode *, const NodeInfo *); +using NodeInfoHandler = std::function &)>; bool MatchClassDefinition(ir::AstNode *childNode, const NodeInfo *info); bool MatchIdentifier(ir::AstNode *childNode, const NodeInfo *info); @@ -61,15 +70,22 @@ 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); +void HandleIdentifier(ir::AstNode *node, std::vector &result); +void HandleMemberExpression(ir::AstNode *node, std::vector &result); +void HandleSpeadeElement(ir::AstNode *node, std::vector &result); +void HandleTSEnumMember(ir::AstNode *node, std::vector &result); +void HandleCallExpression(ir::AstNode *node, std::vector &result); ir::AstNode *ExtractExportSpecifierIdentifier(ir::AstNode *node, const NodeInfo *info); ir::AstNode *ExtractTSClassImplementsIdentifier(ir::AstNode *node, const NodeInfo *info); -ir::AstNode *ExtractIdentifierFromNode(ir::AstNode *node, const NodeInfo *info); ir::AstNode *ExtractETSStringLiteralTypeIdentifier(ir::AstNode *node, const NodeInfo *info); ir::AstNode *ExtractETSKeyofTypeIdentifier(ir::AstNode *node, const NodeInfo *info); ir::AstNode *ExtractCallExpressionIdentifier(ir::AstNode *node, const NodeInfo *info); +ir::AstNode *ExtractAwaitExpressionIdentifier(ir::AstNode *node, [[maybe_unused]] const NodeInfo *info); +ir::AstNode *ExtractIdentifierFromNode(ir::AstNode *node, const NodeInfo *info); const std::unordered_map &GetNodeExtractors(); const std::unordered_map &GetNodeMatchers(); +const std::unordered_map &GetNodeInfoHandlers(); } // namespace ark::es2panda::lsp #endif // NODE_MATCHERS_H \ No newline at end of file diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index e354781aeacca35d4bf69ab84df6256eca5b85c9..ffd4b096846b80a2c8208e4a356a13c38c0792c8 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -499,17 +499,10 @@ std::vector GetNodeInfosByDefinitionData(es2panda_Context *context, si std::vector result; while (node != nullptr) { - switch (node->Type()) { - case ir::AstNodeType::IDENTIFIER: - result.emplace_back(std::string(node->AsIdentifier()->Name()), ir::AstNodeType::IDENTIFIER); - break; - case ir::AstNodeType::CLASS_DEFINITION: - if (auto ident = node->AsClassDefinition()->Ident()) { - result.emplace_back(std::string(ident->Name()), ir::AstNodeType::CLASS_DEFINITION); - } - break; - default: - break; + const auto &nodeInfoHandlers = GetNodeInfoHandlers(); + auto it = nodeInfoHandlers.find(node->Type()); + if (it != nodeInfoHandlers.end()) { + it->second(node, result); } node = node->Parent(); } diff --git a/ets2panda/lsp/src/node_matchers.cpp b/ets2panda/lsp/src/node_matchers.cpp index a6b8e9c7b562730b132745351b6af3c0e6197bf4..33ce4f1c868b959b4a031f0bb401f311dbfcde94 100644 --- a/ets2panda/lsp/src/node_matchers.cpp +++ b/ets2panda/lsp/src/node_matchers.cpp @@ -13,9 +13,9 @@ * limitations under the License. */ -#include "node_matchers.h" #include #include +#include "node_matchers.h" #include "public/es2panda_lib.h" #include "public/public.h" #include "ir/ets/etsReExportDeclaration.h" @@ -24,6 +24,38 @@ namespace ark::es2panda::lsp { +DEFINE_SIMPLE_HANDLER(HandleClassDefinition, ClassDefinition, Ident, ir::AstNodeType::CLASS_DEFINITION) +DEFINE_SIMPLE_HANDLER(HandleClassProperty, ClassProperty, Id, ir::AstNodeType::CLASS_PROPERTY) +DEFINE_SIMPLE_HANDLER(HandleProperty, Property, Key()->AsIdentifier, ir::AstNodeType::PROPERTY) +DEFINE_SIMPLE_HANDLER(HandleTSInterfaceDeclaration, TSInterfaceDeclaration, Id, + ir::AstNodeType::TS_INTERFACE_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleTSTypeAliasDeclaration, TSTypeAliasDeclaration, Id, + ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleImportSpecifier, ImportSpecifier, Imported, ir::AstNodeType::IMPORT_SPECIFIER) +DEFINE_SIMPLE_HANDLER(HandleImportDefaultSpecifier, ImportDefaultSpecifier, Local, + ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER) +DEFINE_SIMPLE_HANDLER(HandleImportNamespaceSpecifier, ImportNamespaceSpecifier, Local, + ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER) +DEFINE_SIMPLE_HANDLER(HandleStructDeclaration, ETSStructDeclaration, Definition()->Ident, + ir::AstNodeType::STRUCT_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleClassDeclaration, ClassDeclaration, Definition()->Ident, ir::AstNodeType::CLASS_DECLARATION) +DEFINE_SIMPLE_HANDLER(HanleScriptFunction, ScriptFunction, Id, ir::AstNodeType::SCRIPT_FUNCTION) +DEFINE_SIMPLE_HANDLER(HandleFunctionDeclaration, FunctionDeclaration, Function()->Id, + ir::AstNodeType::FUNCTION_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleMethodDefinition, MethodDefinition, Function()->Id, ir::AstNodeType::METHOD_DEFINITION) +DEFINE_SIMPLE_HANDLER(HanleTSEnumDeclaration, TSEnumDeclaration, Key, ir::AstNodeType::TS_ENUM_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleVariableDeclaration, VariableDeclaration, Declarators()[0]->Id()->AsIdentifier, + ir::AstNodeType::VARIABLE_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleVariableDeclarator, VariableDeclarator, Id()->AsIdentifier, + ir::AstNodeType::VARIABLE_DECLARATOR) +DEFINE_SIMPLE_HANDLER(HandleTSClassImplements, TSClassImplements, Expr()->AsETSTypeReference()->Part()->GetIdent, + ir::AstNodeType::TS_CLASS_IMPLEMENTS) +DEFINE_SIMPLE_HANDLER(HandleAnnotationDeclaration, AnnotationDeclaration, GetBaseName, + ir::AstNodeType::ANNOTATION_DECLARATION) +DEFINE_SIMPLE_HANDLER(HandleAnnotationUsage, AnnotationUsage, GetBaseName, ir::AstNodeType::ANNOTATION_USAGE) +DEFINE_SIMPLE_HANDLER(HandleAwitExpression, AwaitExpression, Argument()->AsIdentifier, + ir::AstNodeType::AWAIT_EXPRESSION) + bool MatchClassDefinition(ir::AstNode *childNode, const NodeInfo *info) { return childNode->IsClassDefinition() && std::string(childNode->AsClassDefinition()->Ident()->Name()) == info->name; @@ -499,6 +531,48 @@ ir::AstNode *ExtractIdentifierFromNode(ir::AstNode *node, const NodeInfo *info) return node; } +void HandleIdentifier(ir::AstNode *node, std::vector &result) +{ + result.emplace_back(std::string(node->AsIdentifier()->Name()), ir::AstNodeType::IDENTIFIER); +} + +void HandleMemberExpression(ir::AstNode *node, std::vector &result) +{ + if (auto ident = node->AsMemberExpression()->Property()) { + result.emplace_back(std::string(ident->ToString()), ir::AstNodeType::MEMBER_EXPRESSION); + } +} + +void HandleSpeadeElement(ir::AstNode *node, std::vector &result) +{ + if (auto ident = node->AsSpreadElement()->Argument()) { + if (ident->IsIdentifier()) { + result.emplace_back(std::string(ident->AsIdentifier()->Name()), ir::AstNodeType::SPREAD_ELEMENT); + } + if (ident->IsMemberExpression()) { + auto propertyName = std::string(ident->AsMemberExpression()->Property()->AsIdentifier()->Name()); + result.emplace_back(propertyName, ir::AstNodeType::SPREAD_ELEMENT); + } + } +} + +void HandleTSEnumMember(ir::AstNode *node, std::vector &result) +{ + result.emplace_back(std::string(node->AsTSEnumMember()->Name()), ir::AstNodeType::TS_ENUM_MEMBER); +} + +void HandleCallExpression(ir::AstNode *node, std::vector &result) +{ + if (node->AsCallExpression()->Callee()->IsMemberExpression()) { + result.emplace_back(node->AsCallExpression()->Callee()->AsMemberExpression()->Property()->ToString(), + ir::AstNodeType::CALL_EXPRESSION); + } + if (node->AsCallExpression()->Callee()->IsIdentifier()) { + result.emplace_back(std::string(node->AsCallExpression()->Callee()->AsIdentifier()->Name()), + ir::AstNodeType::CALL_EXPRESSION); + } +} + static std::unordered_map GetClassAndIdentifierExtractors() { // clang-format off @@ -725,4 +799,35 @@ const std::unordered_map &GetNodeMatchers() {ir::AstNodeType::FUNCTION_DECLARATION, MatchFunctionDeclaration}}; return NODE_MATCHERS; } + +const std::unordered_map &GetNodeInfoHandlers() +{ + static const std::unordered_map NODE_INFO_HANDLERS = { + {ir::AstNodeType::IDENTIFIER, HandleIdentifier}, + {ir::AstNodeType::CLASS_DEFINITION, HandleClassDefinition}, + {ir::AstNodeType::CLASS_PROPERTY, HandleClassProperty}, + {ir::AstNodeType::PROPERTY, HandleProperty}, + {ir::AstNodeType::VARIABLE_DECLARATION, HandleVariableDeclaration}, + {ir::AstNodeType::VARIABLE_DECLARATOR, HandleVariableDeclarator}, + {ir::AstNodeType::IMPORT_SPECIFIER, HandleImportSpecifier}, + {ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER, HandleImportDefaultSpecifier}, + {ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER, HandleImportNamespaceSpecifier}, + {ir::AstNodeType::TS_CLASS_IMPLEMENTS, HandleTSClassImplements}, + {ir::AstNodeType::MEMBER_EXPRESSION, HandleMemberExpression}, + {ir::AstNodeType::TS_INTERFACE_DECLARATION, HandleTSInterfaceDeclaration}, + {ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION, HandleTSTypeAliasDeclaration}, + {ir::AstNodeType::SPREAD_ELEMENT, HandleSpeadeElement}, + {ir::AstNodeType::STRUCT_DECLARATION, HandleStructDeclaration}, + {ir::AstNodeType::CLASS_DECLARATION, HandleClassDeclaration}, + {ir::AstNodeType::SCRIPT_FUNCTION, HanleScriptFunction}, + {ir::AstNodeType::FUNCTION_DECLARATION, HandleFunctionDeclaration}, + {ir::AstNodeType::METHOD_DEFINITION, HandleMethodDefinition}, + {ir::AstNodeType::TS_ENUM_DECLARATION, HanleTSEnumDeclaration}, + {ir::AstNodeType::TS_ENUM_MEMBER, HandleTSEnumMember}, + {ir::AstNodeType::CALL_EXPRESSION, HandleCallExpression}, + {ir::AstNodeType::ANNOTATION_DECLARATION, HandleAnnotationDeclaration}, + {ir::AstNodeType::AWAIT_EXPRESSION, HandleAwitExpression}, + {ir::AstNodeType::ANNOTATION_USAGE, HandleAnnotationUsage}}; + return NODE_INFO_HANDLERS; +} } // 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 cc13a0cfa40710c7490c2e344d64af27f3a7c6b2..70bd24df613162bbb559abc843325e6a4425fafe 100644 --- a/ets2panda/test/unit/lsp/CMakeLists.txt +++ b/ets2panda/test/unit/lsp/CMakeLists.txt @@ -480,4 +480,44 @@ ets2panda_add_gtest(lsp_api_get_node_ts_nonnull_expression CPP_SOURCES ets2panda_add_gtest(lsp_api_get_node_function_declaration_test CPP_SOURCES get_node_function_declaration_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_interface_test CPP_SOURCES + get_node_info_interface_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_typealias_declaration_test CPP_SOURCES + get_node_info_typealias_declaration.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_spread_element_test CPP_SOURCES + get_node_info_spread_element.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_sturct_decalaration_test CPP_SOURCES + get_node_info_sturct_decalaration_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_infos_annotation_declaration_test CPP_SOURCES + get_node_infos_annotation_declaration_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_infos_script_function_test CPP_SOURCES + get_node_infos_script_function_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_infos_expression_test CPP_SOURCES + get_node_infos_expression_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_await_expression_test CPP_SOURCES + get_node_info_await_expression_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_infos_annotation_usage_test CPP_SOURCES + get_node_infos_annotation_usage_test.cpp +) + +ets2panda_add_gtest(lsp_api_get_node_info_class_property_import_test CPP_SOURCES + get_node_info_class_property_import_test.cpp ) \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_await_expression_test.cpp b/ets2panda/test/unit/lsp/get_node_info_await_expression_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..98cc38e11983d1559286c15e41eb193eb5b613b8 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_await_expression_test.cpp @@ -0,0 +1,112 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoAwaitExpressionTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetNodeInfoAwaitExpression.ets", ES2PANDA_STATE_PARSED, R"('use static' +async function foo1(p: Promise>): Promise { + let result: string = await p; +} + +async function foo2(): Promise { + let x: Promise = Promise.resolve(10.0); + let result2: number = await x; +} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoAwaitExpressionTests, GetNodeInfoAwaitExpressionTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoAwaitExpressionTests, GetNodeInfoAwaitExpressionTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 252; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoAwaitExpressionTests, GetNodeInfoAwaitExpressionTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 106; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 5; + std::vector expectedResult = {{"foo1", ark::es2panda::ir::AstNodeType::FUNCTION_DECLARATION}, + {"foo1", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"result", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"result", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"p", ark::es2panda::ir::AstNodeType::AWAIT_EXPRESSION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoAwaitExpressionTests, GetNodeInfoAwaitExpressionTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 239; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 6; + std::vector expectedResult = {{"foo2", ark::es2panda::ir::AstNodeType::FUNCTION_DECLARATION}, + {"foo2", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"result2", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"result2", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"x", ark::es2panda::ir::AstNodeType::AWAIT_EXPRESSION}, + {"x", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_class_property_import_test.cpp b/ets2panda/test/unit/lsp/get_node_info_class_property_import_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eaa5390b8489dc9ad73eea901a5a2546019b8032 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_class_property_import_test.cpp @@ -0,0 +1,196 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoClassPropertyImportTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = + initializer.CreateContext("GetNodeInfoClassPropertyImport.ets", ES2PANDA_STATE_PARSED, R"('use static' +const obj = { + prop: 'value' +}; +interface Printable {} +class Document1 implements Printable { +} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 460; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 33; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"obj", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"obj", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"prop", ark::es2panda::ir::AstNodeType::PROPERTY}, + {"prop", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 103; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"Document1", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Document1", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Printable", ark::es2panda::ir::AstNodeType::TS_CLASS_IMPLEMENTS}, + {"Printable", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest5) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"(class Foo { + Foo = 1; +})"; + es2panda_Context *contexts = + initializer.CreateContext("GetNodeInfoClassPropertyImport5.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 16; + const size_t expectedSize = 4; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_PROPERTY}, + {"Foo", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest6) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"(export { PI } from "std/math";)"; + es2panda_Context *contexts = + initializer.CreateContext("GetNodeInfoClassPropertyImport6.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 9; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + std::vector expectedResult = {{"PI", ark::es2panda::ir::AstNodeType::IMPORT_SPECIFIER}, + {"PI", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest7) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"(import PI from "std/math";)"; + es2panda_Context *contexts = + initializer.CreateContext("GetNodeInfoClassPropertyImport7.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 7; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + std::vector expectedResult = {{"PI", ark::es2panda::ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER}, + {"PI", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +TEST_F(LspGetNodeInfoClassPropertyImportTests, GetNodeInfoClassPropertyImportTest8) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"(import * as All from "std/math";)"; + es2panda_Context *contexts = + initializer.CreateContext("GetNodeInfoClassPropertyImport8.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 12; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + std::vector expectedResult = {{"All", ark::es2panda::ir::AstNodeType::IMPORT_NAMESPACE_SPECIFIER}, + {"All", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_interface_test.cpp b/ets2panda/test/unit/lsp/get_node_info_interface_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..ad114a4aa329ad6169975dfc679fc8e9bb280191 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_interface_test.cpp @@ -0,0 +1,118 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoIntrfaceTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("LspGetNodeInfoIntrfaceTests.ets", ES2PANDA_STATE_PARSED, R"('use static' +export namespace a { + export interface User { + bar(): void; + } + export namespace b { + export interface Client extends a.User {} + } +} +export interface Worker extends a.User {} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoIntrfaceTests, GetNodeInfoInterfaceTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoIntrfaceTests, GetNodeInfoInterfaceTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 230; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoIntrfaceTests, GetNodeInfoInterfaceTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 47; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 1; + std::vector expectedResult = {{"User", ark::es2panda::ir::AstNodeType::TS_INTERFACE_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoIntrfaceTests, GetNodeInfoInterfaceTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 145; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 1; + std::vector expectedResult = {{"Client", ark::es2panda::ir::AstNodeType::TS_INTERFACE_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoIntrfaceTests, GetNodeInfoInterfaceTest5) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 188; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 1; + std::vector expectedResult = {{"Worker", ark::es2panda::ir::AstNodeType::TS_INTERFACE_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_spread_element.cpp b/ets2panda/test/unit/lsp/get_node_info_spread_element.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9c7f498fce9717987804cd69700ec926dd6ef627 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_spread_element.cpp @@ -0,0 +1,142 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoSpreadElementTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetNodeInfoSpreadElement.ets", ES2PANDA_STATE_PARSED, R"('use static' +const numbers = [1, 2, 3]; +const moreNumbers = [0, ...numbers, 4, 5]; +const part1 = [1, 2]; +const part2 = [3, 4]; +const combined = [...part1, ...part2, 5]; +const original = [10, 20, 30]; +const copy = [...original]; +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 460; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 69; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"moreNumbers", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"moreNumbers", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"numbers", ark::es2panda::ir::AstNodeType::SPREAD_ELEMENT}, + {"numbers", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 152; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"combined", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"combined", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"part1", ark::es2panda::ir::AstNodeType::SPREAD_ELEMENT}, + {"part1", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest5) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 162; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"combined", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"combined", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"part2", ark::es2panda::ir::AstNodeType::SPREAD_ELEMENT}, + {"part2", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoSpreadElementTests, GetNodeInfoSpreadElementTest6) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 223; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 4; + std::vector expectedResult = {{"copy", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATION}, + {"copy", ark::es2panda::ir::AstNodeType::VARIABLE_DECLARATOR}, + {"original", ark::es2panda::ir::AstNodeType::SPREAD_ELEMENT}, + {"original", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_sturct_decalaration_test.cpp b/ets2panda/test/unit/lsp/get_node_info_sturct_decalaration_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c431347d8e422bf141aad5897ed916d2ead21e5a --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_sturct_decalaration_test.cpp @@ -0,0 +1,101 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoStructDecalarationTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = + initializer.CreateContext("GetNodeInfoStructDecalaration.ets", ES2PANDA_STATE_PARSED, R"('use static' +struct Index {}; +struct Person { + name: string; + age: number; +} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoStructDecalarationTests, GetNodeInfoStructDecalarationTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoStructDecalarationTests, GetNodeInfoStructDecalarationTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 90; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoStructDecalarationTests, GetNodeInfoStructDecalarationTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 20; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 3; + std::vector expectedResult = {{"Index", ark::es2panda::ir::AstNodeType::STRUCT_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < expectedResult.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoStructDecalarationTests, GetNodeInfoStructDecalarationTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 38; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 3; + std::vector expectedResult = {{"Person", ark::es2panda::ir::AstNodeType::STRUCT_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < expectedResult.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_info_typealias_declaration.cpp b/ets2panda/test/unit/lsp/get_node_info_typealias_declaration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..960369ad6ec208c56e78ce9eed760becc088ba61 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_info_typealias_declaration.cpp @@ -0,0 +1,135 @@ +/** + * 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 +#include + +namespace { +using ark::es2panda::lsp::Initializer; + +class LspGetNodeInfoTypeAliasDeclarationTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("LspGetNodeInfosTypeAliasDeclarationTest.ets", ES2PANDA_STATE_PARSED, + R"('use static' +type ID = string | number; +type Status = "active" | "inactive" | "pending"; +type List = T[]; +namespace Models { + namespace Utils { + type Formatter = (input: T) => string; + } +} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest1) +{ + LSPAPI const *lspApi = GetImpl(); + auto result = lspApi->getNodeInfosByDefinitionData(nullptr, 0); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest2) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 220; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest3) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 19; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 2; + std::vector expectedResult = {{"ID", ark::es2panda::ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION}, + {"ID", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest4) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 47; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 2; + std::vector expectedResult = {{"Status", ark::es2panda::ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION}, + {"Status", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest5) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 98; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 1; + std::vector expectedResult = {{"List", ark::es2panda::ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfoTypeAliasDeclarationTests, GetNodeInfoTypeAliasDeclarationTest6) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 169; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + const size_t expectedSize = 2; + std::vector expectedResult = {{"Formatter", ark::es2panda::ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION}, + {"Formatter", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_infos_annotation_declaration_test.cpp b/ets2panda/test/unit/lsp/get_node_infos_annotation_declaration_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f0eff4314237f5dafaa616849c9c04a5ab4fcbbf --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_infos_annotation_declaration_test.cpp @@ -0,0 +1,152 @@ +/** + * 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 LspGetInfosAnnotationDeclarationTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + sourceCode_ = R"( + @interface Validate { + } + + @interface Log { + level: string; + } + + @interface Component { + name: string; + version: number; + } + + @interface Deprecated { + } + + @Component({name: "Service", version: 1}) + class Service { + @Validate + @Log({level: 'info'}) + doSomething() { + // ... + } + + @Deprecated + oldMethod() { + // ... + } + } + )"; + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetInfosAnnotationDeclarationTest.ets", 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(LspGetInfosAnnotationDeclarationTests, GetSimpleAnnotationDeclarationInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 24; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Validate", ark::es2panda::ir::AstNodeType::ANNOTATION_DECLARATION}, + {"Validate", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfosAnnotationDeclarationTests, GetAnnotationDeclarationWithPropertiesInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 73; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Log", ark::es2panda::ir::AstNodeType::ANNOTATION_DECLARATION}, + {"Log", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfosAnnotationDeclarationTests, GetComplexAnnotationDeclarationInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 148; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Component", ark::es2panda::ir::AstNodeType::ANNOTATION_DECLARATION}, + {"Component", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfosAnnotationDeclarationTests, GetAnotherSimpleAnnotationDeclarationInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 261; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Deprecated", ark::es2panda::ir::AstNodeType::ANNOTATION_DECLARATION}, + {"Deprecated", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfosAnnotationDeclarationTests, GetAnnotationDeclarationInfo_Error) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 660; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + ASSERT_TRUE(result.empty()); +} +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_infos_annotation_usage_test.cpp b/ets2panda/test/unit/lsp/get_node_infos_annotation_usage_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ccfd6043b01e4f4829e91d858e9f56627da7f0d --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_infos_annotation_usage_test.cpp @@ -0,0 +1,170 @@ +/** + * 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 LspGetInfoAnnotationUsageTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + sourceCode_ = R"( + @interface Injectable { + } + + @interface Component { + name: string; + } + + @interface Log { + level: string; + } + + @interface Deprecated { + } + + @Injectable + class DatabaseService { + connect() { + return "Connected to DB"; + } + } + + @Component({name: "test"}) + class TestComponent { + @Log({level: "info"}) + doSomething() { + // ... + } + + @Deprecated + oldMethod() { + // ... + } + } + )"; + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + sourceCode_ = ""; + } + + static void GenerateContexts(Initializer &initializer) + { + contexts_ = + initializer.CreateContext("GetInfoAnnotationUsageTest.ets", 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(LspGetInfoAnnotationUsageTests, GetInfoClassAnnotationUsage) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 307; + const size_t expectedSize = 4; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"DatabaseService", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"DatabaseService", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Injectable", ark::es2panda::ir::AstNodeType::ANNOTATION_USAGE}, + {"Injectable", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfoAnnotationUsageTests, GetInfoClassAnnotationUsageWithProperties) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 486; + const size_t expectedSize = 4; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Component", ark::es2panda::ir::AstNodeType::ANNOTATION_USAGE}, + {"Component", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfoAnnotationUsageTests, GetInfoMethodAnnotationUsage) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 563; + const size_t expectedSize = 6; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"doSomething", ark::es2panda::ir::AstNodeType::METHOD_DEFINITION}, + {"doSomething", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"Log", ark::es2panda::ir::AstNodeType::ANNOTATION_USAGE}, + {"Log", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfoAnnotationUsageTests, GetInfoAnotherMethodAnnotationUsage) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 695; + const size_t expectedSize = 6; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"TestComponent", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"oldMethod", ark::es2panda::ir::AstNodeType::METHOD_DEFINITION}, + {"oldMethod", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"Deprecated", ark::es2panda::ir::AstNodeType::ANNOTATION_USAGE}, + {"Deprecated", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetInfoAnnotationUsageTests, GetNonInfoAnnotationUsage) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 850; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_infos_expression_test.cpp b/ets2panda/test/unit/lsp/get_node_infos_expression_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..575fac73f65de18134c6120e09416ed875b25076 --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_infos_expression_test.cpp @@ -0,0 +1,137 @@ +/** + * 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 LspGetNodeInfosExpressionTests : public LSPAPITests { +protected: + static void SetUpTestSuite() + { + initializer_ = new Initializer(); + GenerateContexts(*initializer_); + } + + static void TearDownTestSuite() + { + initializer_->DestroyContext(contexts_); + delete initializer_; + initializer_ = nullptr; + } + static void GenerateContexts(Initializer &initializer) + { + contexts_ = initializer.CreateContext("GetNodeInfosExpresion.ts", ES2PANDA_STATE_PARSED, R"( +class Foo { + bar() {} +} +let foo = new Foo(); +foo.bar(); + +let obj: Record = { + prop: "value" +}; +let propName = "prop"; +obj[propName]; + +function a() { + return "hello"; +} +a(); + +class Parent { + name: string; + + constructor(name: string) { + this.name = name; + } +} + +class Child extends Parent { + age: number; + + constructor(name: string, age: number) { + super(name); + this.age = age; + } +} +)"); + } + // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) + static inline es2panda_Context *contexts_ = nullptr; + static inline Initializer *initializer_ = nullptr; + // NOLINTEND(fuchsia-statically-constructed-objects, cert-err58-cpp) +}; + +TEST_F(LspGetNodeInfosExpressionTests, GetMemberExpressionInfo_Error) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 450; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); + ASSERT_TRUE(result.empty()); +} + +TEST_F(LspGetNodeInfosExpressionTests, GetMemberExpressionInfo_PROPERTY) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 53; + const size_t expectedSize = 3; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"bar", ark::es2panda::ir::AstNodeType::CALL_EXPRESSION}, + {"bar", ark::es2panda::ir::AstNodeType::MEMBER_EXPRESSION}, + {"bar", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfosExpressionTests, GetMemberExpressionInfo_ELEMENT) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 145; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"propName", ark::es2panda::ir::AstNodeType::MEMBER_EXPRESSION}, + {"propName", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfosExpressionTests, GetCallExpression_IdentifierInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 194; + const size_t expectedSize = 2; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"a", ark::es2panda::ir::AstNodeType::CALL_EXPRESSION}, + {"a", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_infos_script_function_test.cpp b/ets2panda/test/unit/lsp/get_node_infos_script_function_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e92e3a83d96a792e65959aa3214b63f41f6ac23d --- /dev/null +++ b/ets2panda/test/unit/lsp/get_node_infos_script_function_test.cpp @@ -0,0 +1,107 @@ +/** + * 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 LspGetNodeInfoScriptFunctionTests : public LSPAPITests {}; + +TEST_F(LspGetNodeInfoScriptFunctionTests, GetScriptFunctionInfo_Simple_TEST) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"(function test() {} +)"; + es2panda_Context *contexts = + initializer.CreateContext("ScriptFunctionInfo.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t errorOffset = 20; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, errorOffset); + ASSERT_TRUE(result.empty()); + + const size_t offset = 9; + const size_t expectedSize = 3; + result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + + std::vector expectedResult = {{"test", ark::es2panda::ir::AstNodeType::FUNCTION_DECLARATION}, + {"test", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"test", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +TEST_F(LspGetNodeInfoScriptFunctionTests, GetScriptFunctionInfo_Arrow_TEST) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"( +function add(a: number, b: number): number { return a + b; } +)"; + es2panda_Context *contexts = + initializer.CreateContext("ScriptFunctionInfo.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 10; + const size_t expectedSize = 3; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + + std::vector expectedResult = {{"add", ark::es2panda::ir::AstNodeType::FUNCTION_DECLARATION}, + {"add", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"add", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} + +TEST_F(LspGetNodeInfoScriptFunctionTests, GetScriptFunctionInfo_Async_TEST) +{ + Initializer initializer = Initializer(); + const std::string sourceCode = R"( +async function fetchData(): Promise { + return "data"; +} +)"; + es2panda_Context *contexts = + initializer.CreateContext("ScriptFunctionInfo.ets", ES2PANDA_STATE_PARSED, sourceCode.c_str()); + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 16; + const size_t expectedSize = 3; + auto result = lspApi->getNodeInfosByDefinitionData(contexts, offset); + + std::vector expectedResult = {{"fetchData", ark::es2panda::ir::AstNodeType::FUNCTION_DECLARATION}, + {"fetchData", ark::es2panda::ir::AstNodeType::SCRIPT_FUNCTION}, + {"fetchData", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } + + initializer.DestroyContext(contexts); +} +} // namespace \ No newline at end of file diff --git a/ets2panda/test/unit/lsp/get_node_infos_test.cpp b/ets2panda/test/unit/lsp/get_node_infos_test.cpp index 86478e2aef0c16cd9004438bb5d69e0b7eef0953..4aa7be4f6aea1d519cf258574f7ff93a5b2a8cff 100644 --- a/ets2panda/test/unit/lsp/get_node_infos_test.cpp +++ b/ets2panda/test/unit/lsp/get_node_infos_test.cpp @@ -43,6 +43,12 @@ protected: contexts_ = initializer.CreateContext("LspGetNodeInfosTests.ets", ES2PANDA_STATE_CHECKED, R"('use static' declare class Foo { foo(): void; + bar() {} + enum Color { + Red, + Green, + Blue + }; })"); } // NOLINTBEGIN(fuchsia-statically-constructed-objects, cert-err58-cpp) @@ -61,7 +67,7 @@ TEST_F(LspGetNodeInfosTests, GetNodeInfosTests1) TEST_F(LspGetNodeInfosTests, GetNodeInfosTests2) { LSPAPI const *lspApi = GetImpl(); - const size_t errorOffset = 52; + const size_t errorOffset = 150; auto result = lspApi->getNodeInfosByDefinitionData(contexts_, errorOffset); ASSERT_TRUE(result.empty()); } @@ -71,8 +77,9 @@ TEST_F(LspGetNodeInfosTests, GetNodeInfosTests3) LSPAPI const *lspApi = GetImpl(); const size_t offset = 27; auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); - const size_t expectedSize = 2; - std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + const size_t expectedSize = 3; + std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, {"Foo", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; ASSERT_EQ(result.size(), expectedSize); for (size_t i = 0; i < result.size(); i++) { @@ -81,4 +88,55 @@ TEST_F(LspGetNodeInfosTests, GetNodeInfosTests3) } } +TEST_F(LspGetNodeInfosTests, GetMethodDefinitionInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 54; + const size_t expectedSize = 4; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"bar", ark::es2panda::ir::AstNodeType::METHOD_DEFINITION}, + {"bar", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfosTests, GetTsEnumDeclarationInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 72; + const size_t expectedSize = 4; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Color", ark::es2panda::ir::AstNodeType::TS_ENUM_DECLARATION}, + {"Color", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} + +TEST_F(LspGetNodeInfosTests, GetTsEnumMemberInfo) +{ + LSPAPI const *lspApi = GetImpl(); + const size_t offset = 101; + const size_t expectedSize = 5; + auto result = lspApi->getNodeInfosByDefinitionData(contexts_, offset); + std::vector expectedResult = {{"Foo", ark::es2panda::ir::AstNodeType::CLASS_DECLARATION}, + {"Foo", ark::es2panda::ir::AstNodeType::CLASS_DEFINITION}, + {"Color", ark::es2panda::ir::AstNodeType::TS_ENUM_DECLARATION}, + {"Green", ark::es2panda::ir::AstNodeType::TS_ENUM_MEMBER}, + {"Green", ark::es2panda::ir::AstNodeType::IDENTIFIER}}; + ASSERT_EQ(result.size(), expectedSize); + for (size_t i = 0; i < result.size(); i++) { + ASSERT_EQ(result[i].name, expectedResult[i].name); + ASSERT_EQ(result[i].kind, expectedResult[i].kind); + } +} } // namespace \ No newline at end of file