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 "completions_details.h"
17 #include "internal_api.h"
18 #include "compiler/lowering/util.h"
19 #include "ir/astNode.h"
20 #include "public/public.h"
21 #include <algorithm>
22 #include <cstddef>
23 #include <string>
24 #include "generated/tokenType.h"
25 #include <cstdio>
26 #include "public/es2panda_lib.h"
27 #include "lexer/token/letters.h"
28 #include "api.h"
29 #include "quick_info.h"
30 #include "suggestion_diagnostics.h"
31
32 namespace ark::es2panda::lsp::details {
33
GetDisplayPartAndKind(ir::AstNode * node,std::vector<SymbolDisplayPart> & displayParts,std::string & kind,std::string & kindModifiers)34 void GetDisplayPartAndKind(ir::AstNode *node, std::vector<SymbolDisplayPart> &displayParts, std::string &kind,
35 std::string &kindModifiers)
36 {
37 if (IsClass(node)) {
38 displayParts = ark::es2panda::lsp::CreateDisplayForClass(node);
39 kind = "class";
40 } else if (node->Type() == ir::AstNodeType::ETS_PARAMETER_EXPRESSION) {
41 displayParts = ark::es2panda::lsp::CreateDisplayForETSParameterExpression(node);
42 kind = "parameter";
43 } else if (node->Type() == ir::AstNodeType::CLASS_PROPERTY) {
44 // After enum refactoring, enum declaration is transformed to a class declaration
45 if (compiler::ClassDefinitionIsEnumTransformed(node->Parent())) {
46 auto enumDecl = node->Parent()->AsClassDefinition()->OrigEnumDecl()->AsTSEnumDeclaration();
47 auto enumMember = GetEnumMemberByName(enumDecl, node->AsClassProperty()->Key()->AsIdentifier()->Name());
48 displayParts = ark::es2panda::lsp::CreateDisplayForEnumMember(enumMember);
49 kind = "enum member";
50 } else {
51 displayParts = ark::es2panda::lsp::CreateDisplayForClassProperty(node, kindModifiers);
52 kind = "property";
53 }
54 } else if (node->Type() == ir::AstNodeType::TS_INTERFACE_DECLARATION) {
55 displayParts = ark::es2panda::lsp::CreateDisplayForInterface(node);
56 kind = "interface";
57 } else if (node->Type() == ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION) {
58 displayParts = ark::es2panda::lsp::CreateDisplayForTypeAlias(node);
59 kind = "type alias";
60 } else if (node->Type() == ir::AstNodeType::TS_ENUM_DECLARATION) {
61 displayParts = ark::es2panda::lsp::CreateDisplayForEnum(node);
62 kind = "enum";
63 } else if (node->Type() == ir::AstNodeType::IMPORT_DECLARATION) {
64 displayParts = CreateDisplayForImportDeclaration(node);
65 kind = "import";
66 } else if (node->Type() == ir::AstNodeType::TS_TYPE_PARAMETER) {
67 displayParts = ark::es2panda::lsp::CreateDisplayForTypeParameter(node);
68 kind = "type parameter";
69 } else if (node->Type() == ir::AstNodeType::METHOD_DEFINITION) {
70 displayParts = ark::es2panda::lsp::CreateDisplayForMethodDefinition(node, kindModifiers);
71 kind = "function";
72 if (node->Parent() != nullptr && node->Parent()->Type() == ir::AstNodeType::TS_INTERFACE_BODY) {
73 kind = "property";
74 }
75 }
76 }
77
GetCompletionEntryDetails(ir::AstNode * node,const std::string & entryName,const std::string & fileName)78 CompletionEntryDetails GetCompletionEntryDetails(ir::AstNode *node, const std::string &entryName,
79 const std::string &fileName)
80 {
81 if (node == nullptr) {
82 return CompletionEntryDetails();
83 }
84 auto kindModifiers = GetKindModifiers(node);
85 std::vector<SymbolDisplayPart> displayParts;
86
87 std::string kind;
88 std::vector<SymbolDisplayPart> document;
89 std::vector<SymbolDisplayPart> source;
90 std::vector<SymbolDisplayPart> sourceDisplay;
91
92 GetDisplayPartAndKind(node, displayParts, kind, kindModifiers);
93
94 return CompletionEntryDetails(entryName, kind, kindModifiers, displayParts, document, source, sourceDisplay,
95 fileName);
96 }
97
GetCompletionEntryDetailsImpl(es2panda_Context * context,size_t position,const char * fileName,const char * entryName)98 CompletionEntryDetails GetCompletionEntryDetailsImpl(es2panda_Context *context, size_t position, const char *fileName,
99 const char *entryName)
100 {
101 if (context == nullptr) {
102 return CompletionEntryDetails();
103 }
104 auto touchingToken = GetTouchingToken(context, position, false);
105 if (touchingToken == nullptr || touchingToken->IsProgram()) {
106 return CompletionEntryDetails();
107 }
108 auto ctx = reinterpret_cast<public_lib::Context *>(context);
109 auto ast = ctx->parserProgram->Ast();
110 auto leIdentifier =
111 ast->FindChild([entryName](ir::AstNode *node) { return HasPropertyAccessExpressionWithName(node, entryName); });
112 if (leIdentifier == nullptr || !leIdentifier->IsIdentifier()) {
113 return CompletionEntryDetails();
114 }
115 auto targetNode = compiler::DeclarationFromIdentifier(leIdentifier->AsIdentifier());
116 if (targetNode == nullptr) {
117 return CompletionEntryDetails();
118 }
119 return GetCompletionEntryDetails(targetNode, entryName, fileName);
120 }
121
122 } // namespace ark::es2panda::lsp::details