• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "api.h"
17 #include <cstddef>
18 #include <string>
19 #include <vector>
20 #include "class_hierarchy.h"
21 #include "lsp/include/organize_imports.h"
22 #include "compiler/lowering/util.h"
23 #include "get_safe_delete_info.h"
24 #include "internal_api.h"
25 #include "ir/astNode.h"
26 #include "find_safe_delete_location.h"
27 #include "references.h"
28 #include "public/es2panda_lib.h"
29 #include "cancellation_token.h"
30 #include "generate_constructor.h"
31 #include "public/public.h"
32 #include "util/options.h"
33 #include "quick_info.h"
34 #include "suggestion_diagnostics.h"
35 #include "brace_matching.h"
36 #include "line_column_offset.h"
37 #include "script_element_kind.h"
38 #include "services/services.h"
39 #include "get_class_property_info.h"
40 #include "inlay_hints.h"
41 #include "signature_help.h"
42 #include "completions_details.h"
43 #include "get_name_or_dotted_name_span.h"
44 
45 using ark::es2panda::lsp::details::GetCompletionEntryDetailsImpl;
46 
47 extern "C" {
48 namespace ark::es2panda::lsp {
49 
GetDefinitionAtPosition(es2panda_Context * context,size_t position)50 DefinitionInfo GetDefinitionAtPosition(es2panda_Context *context, size_t position)
51 {
52     auto declInfo = GetDefinitionAtPositionImpl(context, position);
53     DefinitionInfo result {};
54     auto node = declInfo.first;
55     auto targetNode = declInfo.first->FindChild([&declInfo](ir::AstNode *childNode) {
56         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == declInfo.second;
57     });
58     std::string name;
59     while (node != nullptr) {
60         if (node->Range().start.Program() != nullptr) {
61             name = std::string(node->Range().start.Program()->SourceFile().GetAbsolutePath().Utf8());
62             break;
63         }
64         if (node->IsETSModule()) {
65             name = std::string(node->AsETSModule()->Program()->SourceFilePath());
66             break;
67         }
68         node = node->Parent();
69     }
70     if (targetNode != nullptr) {
71         result = {name, targetNode->Start().index, targetNode->End().index - targetNode->Start().index};
72     }
73     return result;
74 }
75 
GetImplementationAtPosition(es2panda_Context * context,size_t position)76 DefinitionInfo GetImplementationAtPosition(es2panda_Context *context, size_t position)
77 {
78     return GetDefinitionAtPosition(context, position);
79 }
80 
IsPackageModule(es2panda_Context * context)81 bool IsPackageModule(es2panda_Context *context)
82 {
83     return reinterpret_cast<public_lib::Context *>(context)->parserProgram->IsPackage();
84 }
85 
GetAliasScriptElementKind(es2panda_Context * context,size_t position)86 CompletionEntryKind GetAliasScriptElementKind(es2panda_Context *context, size_t position)
87 {
88     auto result = GetAliasScriptElementKindImpl(context, position);
89     return result;
90 }
91 
GetFileReferences(char const * fileName,es2panda_Context * context,bool isPackageModule)92 References GetFileReferences(char const *fileName, es2panda_Context *context, bool isPackageModule)
93 {
94     return GetFileReferencesImpl(context, fileName, isPackageModule);
95 }
96 
GetDeclInfo(es2panda_Context * context,size_t position)97 DeclInfo GetDeclInfo(es2panda_Context *context, size_t position)
98 {
99     DeclInfo result;
100     if (context == nullptr) {
101         return result;
102     }
103     auto astNode = GetTouchingToken(context, position, false);
104     auto declInfo = GetDeclInfoImpl(astNode);
105     result.fileName = std::get<0>(declInfo);
106     result.fileText = std::get<1>(declInfo);
107     return result;
108 }
109 
GetClassHierarchies(es2panda_Context * context,const char * fileName,size_t pos)110 std::vector<ClassHierarchyItemInfo> GetClassHierarchies(es2panda_Context *context, const char *fileName, size_t pos)
111 {
112     return GetClassHierarchiesImpl(context, std::string(fileName), pos);
113 }
114 
GetSafeDeleteInfo(es2panda_Context * context,size_t position)115 bool GetSafeDeleteInfo(es2panda_Context *context, size_t position)
116 {
117     return GetSafeDeleteInfoImpl(context, position);
118 }
119 
GetReferencesAtPosition(es2panda_Context * context,DeclInfo * declInfo)120 References GetReferencesAtPosition(es2panda_Context *context, DeclInfo *declInfo)
121 {
122     auto result = GetReferencesAtPositionImpl(context, {declInfo->fileName, declInfo->fileText});
123     auto compare = [](const ReferenceInfo &lhs, const ReferenceInfo &rhs) {
124         if (lhs.fileName != rhs.fileName) {
125             return lhs.fileName < rhs.fileName;
126         }
127         if (lhs.start != rhs.start) {
128             return lhs.start < rhs.start;
129         }
130         return lhs.length < rhs.length;
131     };
132     RemoveDuplicates(result.referenceInfos, compare);
133     return result;
134 }
135 
GetPrecedingToken(es2panda_Context * context,const size_t pos)136 es2panda_AstNode *GetPrecedingToken(es2panda_Context *context, const size_t pos)
137 {
138     auto ctx = reinterpret_cast<public_lib::Context *>(context);
139     auto ast = ctx->parserProgram->Ast();
140     return reinterpret_cast<es2panda_AstNode *>(FindPrecedingToken(pos, ast, ctx->allocator));
141 }
142 
GetCurrentTokenValue(es2panda_Context * context,size_t position)143 std::string GetCurrentTokenValue(es2panda_Context *context, size_t position)
144 {
145     auto result = GetCurrentTokenValueImpl(context, position);
146     return result;
147 }
148 
OrganizeImportsImpl(es2panda_Context * context,char const * fileName)149 std::vector<FileTextChanges> OrganizeImportsImpl(es2panda_Context *context, char const *fileName)
150 {
151     auto result = OrganizeImports::Organize(context, fileName);
152     return result;
153 }
154 
GetQuickInfoAtPosition(const char * fileName,es2panda_Context * context,size_t position)155 QuickInfo GetQuickInfoAtPosition(const char *fileName, es2panda_Context *context, size_t position)
156 {
157     auto res = GetQuickInfoAtPositionImpl(context, position, fileName);
158     return res;
159 }
160 
161 // find the Definition node by using the entryname And return CompletionEntryDetails
GetCompletionEntryDetails(const char * entryName,const char * fileName,es2panda_Context * context,size_t position)162 CompletionEntryDetails GetCompletionEntryDetails(const char *entryName, const char *fileName, es2panda_Context *context,
163                                                  size_t position)
164 {
165     auto result = GetCompletionEntryDetailsImpl(context, position, fileName, entryName);
166     return result;
167 }
168 
GetSpanOfEnclosingComment(es2panda_Context * context,size_t pos,bool onlyMultiLine)169 TextSpan GetSpanOfEnclosingComment(es2panda_Context *context, size_t pos, bool onlyMultiLine)
170 {
171     auto ctx = reinterpret_cast<public_lib::Context *>(context);
172     auto *range = ctx->allocator->New<CommentRange>();
173     GetRangeOfEnclosingComment(context, pos, range);
174     return (range != nullptr) && (!onlyMultiLine || range->kind_ == CommentKind::MULTI_LINE)
175                ? TextSpan(range->pos_, range->end_ - range->pos_)
176                : TextSpan(0, 0);
177 }
178 
GetSemanticDiagnostics(es2panda_Context * context)179 DiagnosticReferences GetSemanticDiagnostics(es2panda_Context *context)
180 {
181     DiagnosticReferences result {};
182     auto ctx = reinterpret_cast<public_lib::Context *>(context);
183     const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SEMANTIC);
184     for (const auto &diagnostic : diagnostics) {
185         result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic));
186     }
187     return result;
188 }
189 
GetSyntacticDiagnostics(es2panda_Context * context)190 DiagnosticReferences GetSyntacticDiagnostics(es2panda_Context *context)
191 {
192     DiagnosticReferences result {};
193     auto ctx = reinterpret_cast<public_lib::Context *>(context);
194     const auto &diagnostics = ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::SYNTAX);
195     const auto &diagnosticsPluginError =
196         ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_ERROR);
197     const auto &diagnosticsPluginWarning =
198         ctx->diagnosticEngine->GetDiagnosticStorage(util::DiagnosticType::PLUGIN_WARNING);
199     for (const auto &diagnostic : diagnostics) {
200         result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic));
201     }
202     for (const auto &diagnostic : diagnosticsPluginError) {
203         result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic));
204     }
205     for (const auto &diagnostic : diagnosticsPluginWarning) {
206         result.diagnostic.push_back(CreateDiagnosticForError(context, *diagnostic));
207     }
208     return result;
209 }
210 
GetCompilerOptionsDiagnostics(char const * fileName,CancellationToken cancellationToken)211 DiagnosticReferences GetCompilerOptionsDiagnostics(char const *fileName, CancellationToken cancellationToken)
212 {
213     Initializer initializer = Initializer();
214     auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED);
215 
216     DiagnosticReferences result {};
217     if (cancellationToken.IsCancellationRequested()) {
218         return result;
219     }
220     GetOptionDiagnostics(context, result);
221 
222     auto options = reinterpret_cast<public_lib::Context *>(context)->config->options;
223     auto compilationList = FindProjectSources(options->ArkTSConfig());
224     initializer.DestroyContext(context);
225 
226     for (auto const &file : compilationList) {
227         if (cancellationToken.IsCancellationRequested()) {
228             return result;
229         }
230         auto fileContext = initializer.CreateContext(file.first.c_str(), ES2PANDA_STATE_CHECKED);
231         GetGlobalDiagnostics(fileContext, result);
232         initializer.DestroyContext(fileContext);
233     }
234 
235     return result;
236 }
237 
GetTypeHierarchies(es2panda_Context * searchContext,es2panda_Context * context,const size_t pos)238 TypeHierarchiesInfo GetTypeHierarchies(es2panda_Context *searchContext, es2panda_Context *context, const size_t pos)
239 {
240     auto declaration = GetTargetDeclarationNodeByPosition(context, pos);
241     return GetTypeHierarchiesImpl(searchContext, pos, declaration);
242 }
243 
GetDocumentHighlights(es2panda_Context * context,size_t position)244 DocumentHighlightsReferences GetDocumentHighlights(es2panda_Context *context, size_t position)
245 {
246     DocumentHighlightsReferences result = {};
247     result.documentHighlights_.push_back(GetDocumentHighlightsImpl(context, position));
248     return result;
249 }
250 
FindSafeDeleteLocation(es2panda_Context * ctx,const std::tuple<std::string,std::string> * declInfo)251 std::vector<SafeDeleteLocation> FindSafeDeleteLocation(es2panda_Context *ctx,
252                                                        const std::tuple<std::string, std::string> *declInfo)
253 {
254     std::vector<SafeDeleteLocation> result;
255     if (declInfo == nullptr) {
256         return result;
257     }
258     result = FindSafeDeleteLocationImpl(ctx, *declInfo);
259     return result;
260 }
261 
FindReferencesWrapper(ark::es2panda::lsp::CancellationToken * tkn,const std::vector<ark::es2panda::SourceFile> & srcFiles,const ark::es2panda::SourceFile & srcFile,size_t position)262 std::vector<ark::es2panda::lsp::ReferencedNode> FindReferencesWrapper(
263     ark::es2panda::lsp::CancellationToken *tkn, const std::vector<ark::es2panda::SourceFile> &srcFiles,
264     const ark::es2panda::SourceFile &srcFile, size_t position)
265 {
266     auto tmp = FindReferences(tkn, srcFiles, srcFile, position);
267     std::vector<ark::es2panda::lsp::ReferencedNode> res(tmp.size());
268     for (const auto &entry : tmp) {
269         res.emplace_back(entry);
270     }
271     return res;
272 }
273 
GetBraceMatchingAtPositionWrapper(char const * fileName,size_t position)274 std::vector<TextSpan> GetBraceMatchingAtPositionWrapper(char const *fileName, size_t position)
275 {
276     Initializer initializer = Initializer();
277     auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED);
278     auto result = GetBraceMatchingAtPosition(context, position);
279     initializer.DestroyContext(context);
280     return result;
281 }
282 
FindRenameLocationsWrapper(const std::vector<ark::es2panda::SourceFile> & srcFiles,const ark::es2panda::SourceFile & srcFile,size_t position)283 std::vector<ark::es2panda::lsp::RenameLocation> FindRenameLocationsWrapper(
284     const std::vector<ark::es2panda::SourceFile> &srcFiles, const ark::es2panda::SourceFile &srcFile, size_t position)
285 {
286     auto tmp = FindRenameLocations(srcFiles, srcFile, position);
287     std::vector<ark::es2panda::lsp::RenameLocation> res(tmp.size());
288     for (const auto &entry : tmp) {
289         res.emplace_back(entry);
290     }
291     return res;
292 }
293 
FindRenameLocationsWithCancellationWrapper(ark::es2panda::lsp::CancellationToken * tkn,const std::vector<ark::es2panda::SourceFile> & srcFiles,const ark::es2panda::SourceFile & srcFile,size_t position)294 std::vector<ark::es2panda::lsp::RenameLocation> FindRenameLocationsWithCancellationWrapper(
295     ark::es2panda::lsp::CancellationToken *tkn, const std::vector<ark::es2panda::SourceFile> &srcFiles,
296     const ark::es2panda::SourceFile &srcFile, size_t position)
297 {
298     auto tmp = FindRenameLocations(tkn, srcFiles, srcFile, position);
299     std::vector<ark::es2panda::lsp::RenameLocation> res(tmp.size());
300     for (const auto &entry : tmp) {
301         res.emplace_back(entry);
302     }
303     return res;
304 }
305 
GetClassPropertyInfoWrapper(es2panda_Context * context,size_t position,bool shouldCollectInherited)306 std::vector<FieldsInfo> GetClassPropertyInfoWrapper(es2panda_Context *context, size_t position,
307                                                     bool shouldCollectInherited)
308 {
309     return GetClassPropertyInfo(context, position, shouldCollectInherited);
310 }
311 
GetSuggestionDiagnostics(es2panda_Context * context)312 DiagnosticReferences GetSuggestionDiagnostics(es2panda_Context *context)
313 {
314     DiagnosticReferences res {};
315     auto ctx = reinterpret_cast<public_lib::Context *>(context);
316     auto ast = ctx->parserProgram->Ast();
317     auto vec = GetSuggestionDiagnosticsImpl(ast);
318     res.diagnostic.reserve(vec.size());
319     for (const auto &diag : vec) {
320         res.diagnostic.push_back(diag.diagnostic);
321     }
322     return res;
323 }
324 
GetCompletionsAtPosition(es2panda_Context * context,size_t position)325 ark::es2panda::lsp::CompletionInfo GetCompletionsAtPosition(es2panda_Context *context, size_t position)
326 {
327     auto result = CompletionInfo(GetCompletionsAtPositionImpl(context, position));
328     return result;
329 }
330 
GetClassHierarchyInfo(es2panda_Context * context,size_t position)331 ClassHierarchy GetClassHierarchyInfo(es2panda_Context *context, size_t position)
332 {
333     auto result = GetClassHierarchyInfoImpl(context, position);
334     return result;
335 }
336 
GetImplementationLocationAtPositionWrapper(es2panda_Context * context,int position)337 std::vector<Location> GetImplementationLocationAtPositionWrapper(es2panda_Context *context, int position)
338 {
339     return GetImplementationLocationAtPosition(context, position);
340 }
341 
GetClassConstructorInfo(es2panda_Context * context,size_t position,const std::vector<std::string> & properties)342 RefactorEditInfo GetClassConstructorInfo(es2panda_Context *context, size_t position,
343                                          const std::vector<std::string> &properties)
344 {
345     auto result = RefactorEditInfo(GetRefactorActionsToGenerateConstructor(context, position, properties));
346     return result;
347 }
348 
ToLineColumnOffsetWrapper(es2panda_Context * context,size_t position)349 LineAndCharacter ToLineColumnOffsetWrapper(es2panda_Context *context, size_t position)
350 {
351     auto result = ToLineColumnOffset(context, position);
352     return result;
353 }
354 
355 // Returns type of refactoring and action that can be performed based
356 // on the input kind information and cursor position
GetApplicableRefactors(es2panda_Context * context,const char * kind,size_t position)357 std::vector<ApplicableRefactorInfo> GetApplicableRefactors(es2panda_Context *context, const char *kind, size_t position)
358 {
359     RefactorContext refactorContext;
360     refactorContext.context = context;
361     refactorContext.kind = kind;
362     refactorContext.span.pos = position;
363     auto result = GetApplicableRefactorsImpl(&refactorContext);
364     return result;
365 }
366 
GetTodoComments(char const * fileName,std::vector<ark::es2panda::lsp::TodoCommentDescriptor> & descriptors,CancellationToken * cancellationToken)367 std::vector<ark::es2panda::lsp::TodoComment> GetTodoComments(
368     char const *fileName, std::vector<ark::es2panda::lsp::TodoCommentDescriptor> &descriptors,
369     CancellationToken *cancellationToken)
370 {
371     Initializer initializer = Initializer();
372     auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED);
373     auto result = GetTodoCommentsImpl(context, descriptors, cancellationToken);
374     initializer.DestroyContext(context);
375     return result;
376 }
377 
ProvideInlayHints(es2panda_Context * context,const TextSpan * span)378 InlayHintList ProvideInlayHints(es2panda_Context *context, const TextSpan *span)
379 {
380     const size_t defaultTime = 20;
381     auto cancellationToken = CancellationToken(defaultTime, nullptr);
382     UserPreferences preferences = UserPreferences::GetDefaultUserPreferences();
383     preferences.SetIncludeInlayParameterNameHints(UserPreferences::IncludeInlayParameterNameHints::ALL);
384     return ProvideInlayHintsImpl(context, span, cancellationToken, preferences);
385 }
386 
GetSignatureHelpItems(es2panda_Context * context,size_t position)387 SignatureHelpItems GetSignatureHelpItems(es2panda_Context *context, size_t position)
388 {
389     const size_t defaultTime = 20;
390     auto invokedReason = ark::es2panda::lsp::SignatureHelpInvokedReason();
391     auto cancellationToken = ark::es2panda::lsp::CancellationToken(defaultTime, nullptr);
392     return ark::es2panda::lsp::GetSignatureHelpItems(context, position, invokedReason, cancellationToken);
393 }
GetCodeFixesAtPosition(es2panda_Context * context,size_t startPosition,size_t endPosition,std::vector<int> & errorCodes,CodeFixOptions & codeFixOptions)394 std::vector<CodeFixActionInfo> GetCodeFixesAtPosition(es2panda_Context *context, size_t startPosition,
395                                                       size_t endPosition, std::vector<int> &errorCodes,
396                                                       CodeFixOptions &codeFixOptions)
397 {
398     auto result =
399         ark::es2panda::lsp::GetCodeFixesAtPositionImpl(context, startPosition, endPosition, errorCodes, codeFixOptions);
400     return result;
401 }
402 
GetCombinedCodeFix(const char * fileName,const std::string & fixId,CodeFixOptions & codeFixOptions)403 CombinedCodeActionsInfo GetCombinedCodeFix(const char *fileName, const std::string &fixId,
404                                            CodeFixOptions &codeFixOptions)
405 {
406     Initializer initializer = Initializer();
407     auto context = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED);
408     auto result = ark::es2panda::lsp::GetCombinedCodeFixImpl(context, fixId, codeFixOptions);
409     initializer.DestroyContext(context);
410     return result;
411 }
412 
GetNameOrDottedNameSpan(es2panda_Context * context,int startPos)413 TextSpan *GetNameOrDottedNameSpan(es2panda_Context *context, int startPos)
414 {
415     auto result = ark::es2panda::lsp::GetNameOrDottedNameSpanImpl(context, startPos);
416     return result;
417 }
418 
419 LSPAPI g_lspImpl = {GetDefinitionAtPosition,
420                     GetApplicableRefactors,
421                     GetImplementationAtPosition,
422                     IsPackageModule,
423                     GetAliasScriptElementKind,
424                     GetFileReferences,
425                     GetDeclInfo,
426                     GetClassHierarchies,
427                     GetSafeDeleteInfo,
428                     GetReferencesAtPosition,
429                     GetPrecedingToken,
430                     GetCurrentTokenValue,
431                     OrganizeImportsImpl,
432                     GetQuickInfoAtPosition,
433                     GetCompletionEntryDetails,
434                     GetSpanOfEnclosingComment,
435                     GetSemanticDiagnostics,
436                     GetSyntacticDiagnostics,
437                     GetCompilerOptionsDiagnostics,
438                     GetTypeHierarchies,
439                     GetDocumentHighlights,
440                     FindRenameLocationsWrapper,
441                     FindRenameLocationsWithCancellationWrapper,
442                     FindSafeDeleteLocation,
443                     FindReferencesWrapper,
444                     GetClassPropertyInfoWrapper,
445                     GetSuggestionDiagnostics,
446                     GetCompletionsAtPosition,
447                     GetClassHierarchyInfo,
448                     GetBraceMatchingAtPositionWrapper,
449                     GetClassConstructorInfo,
450                     GetImplementationLocationAtPositionWrapper,
451                     ToLineColumnOffsetWrapper,
452                     GetTodoComments,
453                     ProvideInlayHints,
454                     GetSignatureHelpItems,
455                     GetCodeFixesAtPosition,
456                     GetCombinedCodeFix,
457                     GetNameOrDottedNameSpan};
458 }  // namespace ark::es2panda::lsp
459 
GetImpl()460 CAPI_EXPORT LSPAPI const *GetImpl()
461 {
462     return &ark::es2panda::lsp::g_lspImpl;
463 }
464 }
465