From 3a10fc4cd74affcf1f66823afa2c10dcee1c80dc Mon Sep 17 00:00:00 2001 From: leo9001 Date: Mon, 16 Jun 2025 23:17:50 +0800 Subject: [PATCH] support getSafeDeleteInfo new function support getSafeDeleteInfo new function Issue:https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICFLY3 Signed-off-by: leo9001 --- ets2panda/bindings/native/src/lsp.cpp | 6 +- .../bindings/src/Es2pandaNativeModule.ts | 2 +- ets2panda/bindings/src/lsp_helper.ts | 2 +- ets2panda/lsp/include/api.h | 2 +- ets2panda/lsp/include/get_safe_delete_info.h | 2 +- ets2panda/lsp/src/api.cpp | 77 +++++-- ets2panda/lsp/src/get_safe_delete_info.cpp | 151 ++++++++----- .../unit/lsp/get_safe_delete_info_test.cpp | 207 +++++++++++++++--- 8 files changed, 335 insertions(+), 114 deletions(-) diff --git a/ets2panda/bindings/native/src/lsp.cpp b/ets2panda/bindings/native/src/lsp.cpp index 286efef597..f31210d999 100644 --- a/ets2panda/bindings/native/src/lsp.cpp +++ b/ets2panda/bindings/native/src/lsp.cpp @@ -1136,13 +1136,13 @@ KNativePointer impl_getLocationFromList(KNativePointer listPtr) } TS_INTEROP_1(getLocationFromList, KNativePointer, KNativePointer) -KBoolean impl_getSafeDeleteInfo(KNativePointer context, KInt position, KStringPtr &path) +KBoolean impl_getSafeDeleteInfo(KNativePointer context, KInt position) { LSPAPI const *ctx = GetImpl(); return static_cast( - ctx->getSafeDeleteInfo(reinterpret_cast(context), position, GetStringCopy(path))); + ctx->getSafeDeleteInfo(reinterpret_cast(context), position)); } -TS_INTEROP_3(getSafeDeleteInfo, KBoolean, KNativePointer, KInt, KStringPtr) +TS_INTEROP_2(getSafeDeleteInfo, KBoolean, KNativePointer, KInt) KNativePointer impl_toLineColumnOffset(KNativePointer context, KInt position) { diff --git a/ets2panda/bindings/src/Es2pandaNativeModule.ts b/ets2panda/bindings/src/Es2pandaNativeModule.ts index 210ad83e1c..897104a2c2 100644 --- a/ets2panda/bindings/src/Es2pandaNativeModule.ts +++ b/ets2panda/bindings/src/Es2pandaNativeModule.ts @@ -716,7 +716,7 @@ export class Es2pandaNativeModule { throw new Error('Not implemented'); } - _getSafeDeleteInfo(context: KNativePointer, position: KInt, path: String): boolean { + _getSafeDeleteInfo(context: KNativePointer, position: KInt): boolean { throw new Error('Not implemented'); } diff --git a/ets2panda/bindings/src/lsp_helper.ts b/ets2panda/bindings/src/lsp_helper.ts index b543a2b07e..2e535ba91c 100644 --- a/ets2panda/bindings/src/lsp_helper.ts +++ b/ets2panda/bindings/src/lsp_helper.ts @@ -657,7 +657,7 @@ export class Lsp { lspDriverHelper.proceedToState(localCtx, Es2pandaContextState.ES2PANDA_STATE_PARSED); PluginDriver.getInstance().runPluginHook(PluginHook.PARSED); lspDriverHelper.proceedToState(localCtx, Es2pandaContextState.ES2PANDA_STATE_CHECKED); - let result = global.es2panda._getSafeDeleteInfo(localCtx, position, path.resolve(__dirname, '../../..')); + let result = global.es2panda._getSafeDeleteInfo(localCtx, position); PluginDriver.getInstance().runPluginHook(PluginHook.CLEAN); lspDriverHelper.destroyContext(localCtx); lspDriverHelper.destroyConfig(localCfg); diff --git a/ets2panda/lsp/include/api.h b/ets2panda/lsp/include/api.h index b49cab1586..cfb41c0957 100644 --- a/ets2panda/lsp/include/api.h +++ b/ets2panda/lsp/include/api.h @@ -498,7 +498,7 @@ typedef struct LSPAPI { std::vector (*getClassHierarchiesImpl)(es2panda_Context *context, const char *fileName, size_t pos); - bool (*getSafeDeleteInfo)(es2panda_Context *context, size_t position, const char *path); + bool (*getSafeDeleteInfo)(es2panda_Context *context, size_t position); References (*getReferencesAtPosition)(es2panda_Context *context, DeclInfo *declInfo); es2panda_AstNode *(*getPrecedingToken)(es2panda_Context *context, const size_t pos); std::string (*getCurrentTokenValue)(es2panda_Context *context, size_t position); diff --git a/ets2panda/lsp/include/get_safe_delete_info.h b/ets2panda/lsp/include/get_safe_delete_info.h index 8988c5b14e..b1d9979cd6 100644 --- a/ets2panda/lsp/include/get_safe_delete_info.h +++ b/ets2panda/lsp/include/get_safe_delete_info.h @@ -17,6 +17,6 @@ #include "public/es2panda_lib.h" namespace ark::es2panda::lsp { // This function judge whether indicated part can be deleted. -bool GetSafeDeleteInfoImpl(es2panda_Context *context, size_t position, const std::string &path); +bool GetSafeDeleteInfoImpl(es2panda_Context *context, size_t position); } // namespace ark::es2panda::lsp #endif \ No newline at end of file diff --git a/ets2panda/lsp/src/api.cpp b/ets2panda/lsp/src/api.cpp index 7bee9e715d..be3cb64c4a 100644 --- a/ets2panda/lsp/src/api.cpp +++ b/ets2panda/lsp/src/api.cpp @@ -49,6 +49,8 @@ namespace ark::es2panda::lsp { DefinitionInfo GetDefinitionAtPosition(es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto declInfo = GetDefinitionAtPositionImpl(context, position); DefinitionInfo result {}; auto node = declInfo.first; @@ -80,17 +82,23 @@ bool IsPackageModule(es2panda_Context *context) CompletionEntryKind GetAliasScriptElementKind(es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = GetAliasScriptElementKindImpl(context, position); return result; } References GetFileReferences(char const *fileName, es2panda_Context *context, bool isPackageModule) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); return GetFileReferencesImpl(context, fileName, isPackageModule); } DeclInfo GetDeclInfo(es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); DeclInfo result; if (context == nullptr) { return result; @@ -104,16 +112,22 @@ DeclInfo GetDeclInfo(es2panda_Context *context, size_t position) std::vector GetClassHierarchies(es2panda_Context *context, const char *fileName, size_t pos) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); return GetClassHierarchiesImpl(context, std::string(fileName), pos); } -bool GetSafeDeleteInfo(es2panda_Context *context, size_t position, const char *path) +bool GetSafeDeleteInfo(es2panda_Context *context, size_t position) { - return GetSafeDeleteInfoImpl(context, position, path); + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); + return GetSafeDeleteInfoImpl(context, position); } References GetReferencesAtPosition(es2panda_Context *context, DeclInfo *declInfo) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = GetReferencesAtPositionImpl(context, {declInfo->fileName, declInfo->fileText}); auto compare = [](const ReferenceInfo &lhs, const ReferenceInfo &rhs) { if (lhs.fileName != rhs.fileName) { @@ -131,24 +145,31 @@ References GetReferencesAtPosition(es2panda_Context *context, DeclInfo *declInfo es2panda_AstNode *GetPrecedingToken(es2panda_Context *context, const size_t pos) { auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto ast = ctx->parserProgram->Ast(); return reinterpret_cast(FindPrecedingToken(pos, ast, ctx->allocator)); } std::string GetCurrentTokenValue(es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = GetCurrentTokenValueImpl(context, position); return result; } std::vector OrganizeImportsImpl(es2panda_Context *context, char const *fileName) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = OrganizeImports::Organize(context, fileName); return result; } QuickInfo GetQuickInfoAtPosition(const char *fileName, es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto res = GetQuickInfoAtPositionImpl(context, position, fileName); return res; } @@ -157,6 +178,8 @@ QuickInfo GetQuickInfoAtPosition(const char *fileName, es2panda_Context *context CompletionEntryDetails GetCompletionEntryDetails(const char *entryName, const char *fileName, es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = GetCompletionEntryDetailsImpl(context, position, fileName, entryName); return result; } @@ -164,6 +187,7 @@ CompletionEntryDetails GetCompletionEntryDetails(const char *entryName, const ch TextSpan GetSpanOfEnclosingComment(es2panda_Context *context, size_t pos, bool onlyMultiLine) { auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto *range = ctx->allocator->New(); GetRangeOfEnclosingComment(context, pos, range); return (range != nullptr) && (!onlyMultiLine || range->kind_ == CommentKind::MULTI_LINE) @@ -175,6 +199,7 @@ DiagnosticReferences GetSemanticDiagnostics(es2panda_Context *context) { DiagnosticReferences result {}; auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SEMANTIC); for (const auto &diagnostic : diagnostics) { result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); @@ -186,10 +211,21 @@ DiagnosticReferences GetSyntacticDiagnostics(es2panda_Context *context) { DiagnosticReferences result {}; auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SYNTAX); + const auto &diagnosticsPluginError = + ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_ERROR); + const auto &diagnosticsPluginWarning = + ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_WARNING); for (const auto &diagnostic : diagnostics) { result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); } + for (const auto &diagnostic : diagnosticsPluginError) { + result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); + } + for (const auto &diagnostic : diagnosticsPluginWarning) { + result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic)); + } return result; } @@ -256,6 +292,11 @@ std::vector FindReferencesWrapper( return res; } +RenameInfoType GetRenameInfoWrapper(es2panda_Context *context, size_t pos, const char *pandaLibPath) +{ + return GetRenameInfo(context, pos, std::string(pandaLibPath)); +} + std::vector GetBraceMatchingAtPositionWrapper(char const *fileName, size_t position) { Initializer initializer = Initializer(); @@ -266,23 +307,19 @@ std::vector GetBraceMatchingAtPositionWrapper(char const *fileName, si } std::vector FindRenameLocationsWrapper( - const std::vector &srcFiles, const ark::es2panda::SourceFile &srcFile, size_t position) + const std::vector &fileContexts, es2panda_Context *context, size_t position) { - auto tmp = FindRenameLocations(srcFiles, srcFile, position); - std::vector res(tmp.size()); - for (const auto &entry : tmp) { - res.emplace_back(entry); - } - return res; + auto locations = FindRenameLocations(fileContexts, context, position); + return std::vector {locations.begin(), locations.end()}; } std::vector FindRenameLocationsWithCancellationWrapper( - ark::es2panda::lsp::CancellationToken *tkn, const std::vector &srcFiles, - const ark::es2panda::SourceFile &srcFile, size_t position) + ark::es2panda::lsp::CancellationToken *tkn, const std::vector &fileContexts, + es2panda_Context *context, size_t position) { - auto tmp = FindRenameLocations(tkn, srcFiles, srcFile, position); - std::vector res(tmp.size()); - for (const auto &entry : tmp) { + auto locations = FindRenameLocations(tkn, fileContexts, context, position); + std::vector res(locations.size()); + for (const auto &entry : locations) { res.emplace_back(entry); } return res; @@ -298,6 +335,7 @@ DiagnosticReferences GetSuggestionDiagnostics(es2panda_Context *context) { DiagnosticReferences res {}; auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto ast = ctx->parserProgram->Ast(); auto vec = GetSuggestionDiagnosticsImpl(ast); res.diagnostic.reserve(vec.size()); @@ -309,6 +347,8 @@ DiagnosticReferences GetSuggestionDiagnostics(es2panda_Context *context) ark::es2panda::lsp::CompletionInfo GetCompletionsAtPosition(es2panda_Context *context, size_t position) { + auto ctx = reinterpret_cast(context); + SetPhaseManager(ctx->phaseManager); auto result = CompletionInfo(GetCompletionsAtPositionImpl(context, position)); return result; } @@ -372,14 +412,12 @@ SignatureHelpItems GetSignatureHelpItems(es2panda_Context *context, size_t posit auto cancellationToken = ark::es2panda::lsp::CancellationToken(defaultTime, nullptr); return ark::es2panda::lsp::GetSignatureHelpItems(context, position, invokedReason, cancellationToken); } -std::vector GetCodeFixesAtPosition(const char *fileName, size_t startPosition, size_t endPosition, - std::vector &errorCodes, CodeFixOptions &codeFixOptions) +std::vector GetCodeFixesAtPosition(es2panda_Context *context, size_t startPosition, + size_t endPosition, std::vector &errorCodes, + CodeFixOptions &codeFixOptions) { - Initializer initializer = Initializer(); - auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED); auto result = ark::es2panda::lsp::GetCodeFixesAtPositionImpl(context, startPosition, endPosition, errorCodes, codeFixOptions); - initializer.DestroyContext(context); return result; } @@ -424,6 +462,7 @@ LSPAPI g_lspImpl = {GetDefinitionAtPosition, FindRenameLocationsWithCancellationWrapper, FindSafeDeleteLocation, FindReferencesWrapper, + GetRenameInfoWrapper, GetClassPropertyInfoWrapper, GetSuggestionDiagnostics, GetCompletionsAtPosition, diff --git a/ets2panda/lsp/src/get_safe_delete_info.cpp b/ets2panda/lsp/src/get_safe_delete_info.cpp index b21f5d949d..825cab7b18 100644 --- a/ets2panda/lsp/src/get_safe_delete_info.cpp +++ b/ets2panda/lsp/src/get_safe_delete_info.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include #include #include @@ -22,89 +23,119 @@ #include "public/public.h" #include "references.h" +namespace { +constexpr size_t BUILTIN_TYPE_COUNT = 9; +constexpr std::array BUILTIN_TYPES = { + "number", "string", "boolean", "void", "bigint", "never", "undefined", "null", "object"}; +} // namespace + namespace ark::es2panda::lsp { -bool NodeIsEligibleForSafeDelete(ir::AstNode *astNode) + +bool IsBuiltinTypeReference(ir::AstNode *node) { - if (astNode == nullptr) { + if (node == nullptr || node->Type() != ir::AstNodeType::IDENTIFIER) { return false; } - switch (astNode->Type()) { - case ir::AstNodeType::THIS_EXPRESSION: - case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: - case ir::AstNodeType::IDENTIFIER: - return true; - default: - return false; + auto *parent = node->Parent(); + while (parent != nullptr) { + if (parent->Type() == ir::AstNodeType::ETS_TYPE_REFERENCE_PART || + parent->Type() == ir::AstNodeType::ETS_TYPE_REFERENCE) { + std::string nameStr(node->AsIdentifier()->Name()); + auto it = + std::find_if(BUILTIN_TYPES.begin(), BUILTIN_TYPES.end(), [&](const char *s) { return nameStr == s; }); + if (it != BUILTIN_TYPES.end()) { + return true; + } + } + parent = parent->Parent(); } + return false; } -DeclInfo GetDeclInfoCur(es2panda_Context *context, size_t position) +ir::AstNode *FindNearestDeletableDecl(ir::AstNode *node) { - DeclInfo result; - if (context == nullptr) { - return result; + ir::AstNode *cur = node; + while (cur != nullptr) { + if (cur->IsFunctionDeclaration() || cur->IsVariableDeclarator() || cur->IsClassProperty() || + cur->Type() == ir::AstNodeType::METHOD_DEFINITION || cur->Type() == ir::AstNodeType::CLASS_DECLARATION || + cur->IsTSTypeParameterDeclaration() || cur->IsImportDefaultSpecifier() || + cur->Type() == ir::AstNodeType::ETS_TYPE_REFERENCE_PART || cur->IsCallExpression() || + cur->IsETSImportDeclaration() || cur->IsImportSpecifier() || cur->IsBinaryExpression() || + cur->IsTSInterfaceDeclaration() || cur->IsETSTypeReferencePart() || cur->IsImportNamespaceSpecifier() || + cur->IsTSTypeAliasDeclaration() || cur->IsExpressionStatement() || cur->IsMemberExpression() || + cur->IsTypeofExpression()) { + return cur; + } + cur = cur->Parent(); } - auto astNode = GetTouchingToken(context, position, false); - auto declInfo = GetDeclInfoImpl(astNode); - result.fileName = std::get<0>(declInfo); - result.fileText = std::get<1>(declInfo); - return result; + return nullptr; } -// This function judge whether type is standard library file defined type. -bool IsLibrayFile(ir::AstNode *node, const std::string &path) +std::string NormalizeFilePath(const std::string &filePath) { - auto declInfo = GetDeclInfoImpl(node); - auto fileName = std::get<0>(declInfo); - if (fileName.empty()) { - return false; - } - if (fileName.find("ets1.2") != std::string::npos) { - return fileName.find(path) != std::string::npos; - } - return true; + std::string normPath = filePath; + std::transform(normPath.begin(), normPath.end(), normPath.begin(), ::tolower); + std::replace(normPath.begin(), normPath.end(), '\\', '/'); + return normPath; } -bool IsAllowToDeleteDeclaration(ir::AstNode *node, const std::string &path) +bool GetSafeDeleteInfoImpl(es2panda_Context *context, size_t position) { - return (node->IsETSModule() && node->AsETSModule()->IsNamespace()) || node->IsTSTypeParameterDeclaration() || - (node->Type() == ir::AstNodeType::IDENTIFIER && node->Parent()->IsTSModuleDeclaration()) || - IsLibrayFile(node, path) || node->IsArrowFunctionExpression() || node->IsETSStringLiteralType(); -} + auto astNode = GetTouchingToken(context, position, false); + if (astNode == nullptr) { + return false; + } -bool GetSafeDeleteInfoForNode(es2panda_Context *context, size_t position, const std::string &path) -{ - auto declInfoData = GetDeclInfoCur(context, position); - DeclInfoType declInfo = {declInfoData.fileName, declInfoData.fileText}; - std::vector nodes; + auto declInfo = GetDeclInfoImpl(astNode); + auto fileName = std::get<0>(declInfo); + + if (IsBuiltinTypeReference(astNode)) { + return false; + } - auto ctx = reinterpret_cast(context); - if (ctx->parserProgram == nullptr || ctx->parserProgram->Ast() == nullptr) { + astNode = FindNearestDeletableDecl(astNode); + if (astNode == nullptr) { return false; } - auto astNode = reinterpret_cast(ctx->parserProgram->Ast()); - astNode->IterateRecursively([declInfo, &nodes](ir::AstNode *child) { - auto info = GetDeclInfoImpl(child); - if (info == declInfo) { - nodes.push_back(child); + + // Distinguish a namespace from a class by checking whether the class body contains only the $init$ method and has + // no constructor. + if (astNode->Type() == ir::AstNodeType::CLASS_DECLARATION) { + auto *classDecl = static_cast(astNode); + const auto &body = classDecl->Definition()->Body(); + bool hasConstructor = false; + bool onlyInit = true; + for (auto *member : body) { + if (member->Type() == ir::AstNodeType::METHOD_DEFINITION) { + auto *method = static_cast(member); + util::StringView keyName = method->Key()->AsIdentifier()->Name(); + if (keyName == "constructor") { + hasConstructor = true; + } + if (keyName != "_$init$_") { + onlyInit = false; + } + } } - }); - std::vector filterNodes; - std::for_each(nodes.begin(), nodes.end(), [&filterNodes, path](ir::AstNode *node) { - if (IsAllowToDeleteDeclaration(node, path)) { - filterNodes.push_back(node); + if (!hasConstructor && onlyInit) { + return false; } - }); + } - return !filterNodes.empty(); -} + if (astNode->IsTSTypeParameterDeclaration()) { + return false; + } -bool GetSafeDeleteInfoImpl(es2panda_Context *context, size_t position, const std::string &path) -{ - auto astNode = GetTouchingToken(context, position, false); - if (NodeIsEligibleForSafeDelete(astNode)) { - return GetSafeDeleteInfoForNode(context, position, path); + std::string normFileName = NormalizeFilePath(fileName); + + if (!normFileName.empty() && normFileName.find("ets1.2/build-tools/ets2panda/lib/stdlib") != std::string::npos) { + return false; } - return false; + + if (!normFileName.empty() && normFileName.find("/sdk/") != std::string::npos) { + return false; + } + + return true; } } // namespace ark::es2panda::lsp diff --git a/ets2panda/test/unit/lsp/get_safe_delete_info_test.cpp b/ets2panda/test/unit/lsp/get_safe_delete_info_test.cpp index ac249130b6..327975daf2 100644 --- a/ets2panda/test/unit/lsp/get_safe_delete_info_test.cpp +++ b/ets2panda/test/unit/lsp/get_safe_delete_info_test.cpp @@ -22,31 +22,27 @@ #include "lsp/include/api.h" #include "public/es2panda_lib.h" -using ark::es2panda::lsp::Initializer; namespace { +using ark::es2panda::lsp::Initializer; class LspGetSafeDeleteInfoTest : public LSPAPITests {}; TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase1) { - using ark::es2panda::public_lib::Context; + std::vector files = {"get-safe-delete-info-case1.ets"}; + std::vector texts = {R"(function a(): number { return 1; } a())"}; + auto filePaths = CreateTempFile(files, texts); - std::vector fileNames = {"firstFile.ets", "secondFile.ets"}; - std::vector fileContents = { - "const greet = (name: string) => {\n" - "return 'Hello, ${name}!';\n};\n" - "export default greet;\n", - "import greet from \"./firstFile.ets\""}; + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); - auto filePaths = CreateTempFile(fileNames, fileContents); - const int fileIndex = 1; + constexpr size_t OFFSET = 16; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, false); - Initializer initializer = Initializer(); - es2panda_Context *ctx = initializer.CreateContext(filePaths[fileIndex].c_str(), ES2PANDA_STATE_CHECKED); - ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); - LSPAPI const *lspApi = GetImpl(); - size_t const offset = 7; - bool result = lspApi->getSafeDeleteInfo(ctx, offset, ""); + constexpr size_t OFFSET2 = 35; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); ASSERT_EQ(result, true); initializer.DestroyContext(ctx); @@ -54,27 +50,182 @@ TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase1) TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase2) { - Initializer initializer = Initializer(); - es2panda_Context *ctx = - initializer.CreateContext("get-safe-delete-info-case2.ets", ES2PANDA_STATE_CHECKED, "class A {\n\n}"); - ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + std::vector files = {"get-safe-delete-info-case2.ets"}; + std::vector texts = {R"(export const PI = 3.1415926;)"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); LSPAPI const *lspApi = GetImpl(); - size_t const offset = 8; - bool result = lspApi->getSafeDeleteInfo(ctx, offset, ""); + + constexpr size_t OFFSET = 14; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); ASSERT_EQ(result, true); + initializer.DestroyContext(ctx); } TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase3) { - Initializer initializer = Initializer(); - es2panda_Context *ctx = initializer.CreateContext("get-safe-delete-info-case3.ets", ES2PANDA_STATE_CHECKED, - "let arr: Array;\n"); - ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED); + std::vector files = {"get-safe-delete-info-case3.ets"}; + std::vector texts = {R"( + function setAlarmDefaultTime(alarmItem?: AlarmItem) { + let hour; + let minute; + })"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); LSPAPI const *lspApi = GetImpl(); - size_t const offset = 10; - bool result = lspApi->getSafeDeleteInfo(ctx, offset, "stdlib/escompat/Array.ets"); + + constexpr size_t OFFSET = 71; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); ASSERT_EQ(result, true); + + constexpr size_t OFFSET2 = 89; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); + ASSERT_EQ(result, true); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase4) +{ + std::vector files = {"get-safe-delete-info-namespace.ets"}; + std::vector texts = {R"( + namespace Foo {} + class Foo2{} + )"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + + constexpr size_t OFFSET = 14; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, false); + + constexpr size_t OFFSET2 = 31; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); + ASSERT_EQ(result, true); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase5) +{ + std::vector files = {"get-safe-delete-info-typeparam.ets"}; + std::vector texts = {R"( + function foo(a: T) { return a; } + )"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + + LSPAPI const *lspApi = GetImpl(); + constexpr size_t OFFSET = 17; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, false); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase6) +{ + std::vector files = {"get-safe-delete-info-import.ets"}; + std::vector texts = {R"(import { foo } from "./mod";)"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + + constexpr size_t OFFSET = 9; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, true); + + constexpr size_t OFFSET2 = 23; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); + ASSERT_EQ(result, true); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase7) +{ + std::vector files = {"get-safe-delete-info-arrow.ets"}; + std::vector texts = {R"( + export const calcDistance = (time: number) => { + const ret = 0.5 * time * time; + return ret; + }; + )"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + + constexpr size_t OFFSET = 28; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, true); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase8) +{ + std::vector files = {"get-safe-delete-info-interface.ets"}; + std::vector texts = {R"( + export interface VideoPlayer { + prepare(): Promise; + } + + function bar(parameter: VideoPlayer) { + parameter.prepare(); + } + )"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + + constexpr size_t OFFSET = 31; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, true); + + constexpr size_t OFFSET2 = 143; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); + ASSERT_EQ(result, true); + + initializer.DestroyContext(ctx); +} + +TEST_F(LspGetSafeDeleteInfoTest, GetSafeDeleteInfoCase9) +{ + std::vector files = {"get-safe-delete-info-importdefault.ets"}; + std::vector texts = {R"( + import BuildProfile from 'BuildProfile'; + BuildProfile.bundleName + )"}; + auto filePaths = CreateTempFile(files, texts); + + Initializer initializer; + es2panda_Context *ctx = initializer.CreateContext(filePaths[0].c_str(), ES2PANDA_STATE_CHECKED); + LSPAPI const *lspApi = GetImpl(); + + constexpr size_t OFFSET = 15; + bool result = lspApi->getSafeDeleteInfo(ctx, OFFSET); + ASSERT_EQ(result, true); + + constexpr size_t OFFSET2 = 52; + result = lspApi->getSafeDeleteInfo(ctx, OFFSET2); + ASSERT_EQ(result, true); + initializer.DestroyContext(ctx); } } // namespace -- Gitee