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 "string_completions.h"
17 #include "completions.h"
18 #include <optional>
19 #include <set>
20 #include <string>
21 #include <vector>
22 #include "ir/astNode.h"
23
24 namespace ark::es2panda::lsp {
GetDeclarationFromParent(ir::AstNode * node)25 ir::AstNode *GetDeclarationFromParent(ir::AstNode *node)
26 {
27 // NOTE: After GL22929
28 (void)node;
29
30 return nullptr;
31 }
32
ControlTypeAndAddToEntry(std::string name,ir::AstNode * referencePart,std::vector<lsp::CompletionEntry> & entries,std::set<std::string> & keys)33 void ControlTypeAndAddToEntry(std::string name, ir::AstNode *referencePart, std::vector<lsp::CompletionEntry> &entries,
34 std::set<std::string> &keys)
35 {
36 if (referencePart == nullptr) {
37 return;
38 }
39 auto type = std::string(referencePart->AsETSTypeReferencePart()->Name()->AsIdentifier()->Name());
40
41 std::string insertText = name += std::string(": ") += type;
42 auto entry = lsp::CompletionEntry(name, CompletionEntryKind::TEXT, "", insertText);
43 keys.insert(name);
44 entries.push_back(entry);
45 }
46
GetCompletionsFromBody(ArenaVector<ir::AstNode * > const & body,std::vector<lsp::CompletionEntry> & entries)47 void GetCompletionsFromBody(ArenaVector<ir::AstNode *> const &body, std::vector<lsp::CompletionEntry> &entries)
48 {
49 std::set<std::string> keys = {};
50 for (auto property : body) {
51 if (property->IsMethodDefinition()) {
52 auto methodDefinition = property->AsMethodDefinition();
53 auto name = std::string(methodDefinition->Key()->AsIdentifier()->Name());
54 if (name == "constructor" || keys.count(name) == 1 || name.empty()) {
55 continue;
56 }
57
58 ir::AstNode *referencePart = methodDefinition->Value()->FindChild(
59 [](ir::AstNode *child) { return child->IsETSTypeReferencePart(); });
60
61 ControlTypeAndAddToEntry(name, referencePart, entries, keys);
62 } else if (property->IsClassProperty()) {
63 auto classProperty = property->AsClassProperty();
64 auto name = std::string(classProperty->Key()->AsIdentifier()->Name());
65 if (name.empty() || keys.count(name) == 1) {
66 continue;
67 }
68
69 ir::AstNode *referencePart =
70 classProperty->FindChild([](ir::AstNode *child) { return child->IsETSTypeReferencePart(); });
71
72 ControlTypeAndAddToEntry(name, referencePart, entries, keys);
73 }
74 }
75 }
76
GetCompletionInfo(ir::AstNode * node)77 ark::es2panda::lsp::CompletionInfo GetCompletionInfo(ir::AstNode *node)
78 {
79 std::vector<lsp::CompletionEntry> entries;
80 switch (node->Type()) {
81 case ir::AstNodeType::TS_INTERFACE_BODY: {
82 GetCompletionsFromBody(node->AsTSInterfaceBody()->Body(), entries);
83 break;
84 }
85 case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
86 GetCompletionsFromBody(node->AsTSInterfaceDeclaration()->Body()->Body(), entries);
87 break;
88 }
89 case ir::AstNodeType::CLASS_DECLARATION: {
90 GetCompletionsFromBody(node->AsClassDeclaration()->Definition()->Body(), entries);
91 break;
92 }
93 default:
94 break;
95 }
96
97 return ark::es2panda::lsp::CompletionInfo(entries);
98 }
99
100 // NOTE: The API that calls this function already know the location of the completion request, should just
101 // pass the Node of the completion request position instead of send the location and we get the node from context
GetStringLiteralCompletions(ir::AstNode * cursor,ir::AstNode * declarationNode)102 std::optional<ark::es2panda::lsp::CompletionInfo> GetStringLiteralCompletions(ir::AstNode *cursor,
103 ir::AstNode *declarationNode)
104 {
105 if (cursor == nullptr || !cursor->IsStringLiteral() || declarationNode == nullptr) {
106 return std::nullopt;
107 }
108
109 // Note: Should add more cases, like function declaration, Property Assignment, Element Access etc.
110 switch (declarationNode->Type()) {
111 case ir::AstNodeType::TS_INTERFACE_DECLARATION:
112 case ir::AstNodeType::TS_INTERFACE_BODY: {
113 return GetCompletionInfo(declarationNode);
114 }
115 case ir::AstNodeType::CLASS_DECLARATION: {
116 return GetCompletionInfo(declarationNode);
117 }
118 case ir::AstNodeType::FUNCTION_DECLARATION:
119 // Not Supported at the moment
120 return std::nullopt;
121 case ir::AstNodeType::TS_UNION_TYPE:
122 case ir::AstNodeType::ETS_UNION_TYPE:
123 // Not supported at the moment
124 return std::nullopt;
125 default:
126 return std::nullopt;
127 }
128 return std::nullopt;
129 }
130
131 } // namespace ark::es2panda::lsp
132