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 "signature_help_items.h"
17 #include <optional>
18 #include <string>
19 #include <vector>
20 #include "utils/arena_containers.h"
21
22 namespace ark::es2panda::lsp {
23
CreateSignatureHelpItems(std::vector<checker::Signature * > & signatures,checker::Signature * signature,std::optional<ArgumentListInfo> argumentListInfo)24 SignatureHelpItems CreateSignatureHelpItems(std::vector<checker::Signature *> &signatures,
25 checker::Signature *signature,
26 std::optional<ArgumentListInfo> argumentListInfo)
27 {
28 SignatureHelpItems items;
29
30 size_t selectedItemIndex = -1;
31 size_t itemsSeen = 0;
32 const size_t one = 1;
33
34 for (size_t i = itemsSeen; i < signatures.size(); i++) {
35 auto ¤tSignature = signatures[i];
36 if (currentSignature->ToString() == signature->ToString()) {
37 selectedItemIndex = itemsSeen;
38 break;
39 }
40 itemsSeen++;
41 }
42
43 ES2PANDA_ASSERT(selectedItemIndex != static_cast<size_t>(-1));
44
45 for (const auto &helpItem : GetSignatureHelpItem(signatures)) {
46 items.SetItems(helpItem);
47 }
48
49 items.SetApplicableSpan(argumentListInfo->GetApplicableSpan().start, argumentListInfo->GetApplicableSpan().length);
50
51 items.SetSelectedItemIndex(selectedItemIndex);
52
53 size_t argumentIndex = argumentListInfo->GetArgumentIndex();
54 const auto selectedSignature = signatures[selectedItemIndex];
55
56 if (selectedSignature->HasRestParameter() && selectedSignature->ArgCount() > one) {
57 argumentIndex = selectedSignature->ArgCount();
58 } else {
59 argumentIndex = std::min(argumentIndex, selectedSignature->ArgCount() - one);
60 }
61
62 items.SetArgumentIndex(argumentIndex);
63 items.SetArgumentCount(argumentListInfo->GetArgumentCount());
64
65 return items;
66 }
67
GetSignatureHelpItem(const std::vector<checker::Signature * > & signatures)68 std::vector<SignatureHelpItem> GetSignatureHelpItem(const std::vector<checker::Signature *> &signatures)
69 {
70 std::vector<SignatureHelpItem> items;
71 if (signatures.empty()) {
72 return items;
73 }
74 for (auto *signature : signatures) {
75 const auto item = CreateSignatureHelpItem(*signature);
76 items.push_back(item);
77 }
78
79 return items;
80 }
81
CreateSignatureHelpItem(checker::Signature & signature)82 SignatureHelpItem CreateSignatureHelpItem(checker::Signature &signature)
83 {
84 const checker::SignatureInfo *signatureInfo = signature.GetSignatureInfo();
85 SignatureHelpItem item;
86 if (!signatureInfo->typeParams.empty()) {
87 item.SetPrefixDisplayParts(CreatePunctuation("<"));
88 for (auto it = signatureInfo->typeParams.begin(); it != signatureInfo->typeParams.end(); ++it) {
89 std::string typeName = (*it)->ToString();
90 item.SetPrefixDisplayParts(CreateTypeName(typeName));
91 if (std::next(it) != signatureInfo->typeParams.end()) {
92 item.SetPrefixDisplayParts(CreatePunctuation(","));
93 item.SetSeparatorDisplayParts(CreatePunctuation(","));
94 }
95 }
96 item.SetPrefixDisplayParts(CreatePunctuation(">"));
97 }
98 item.SetPrefixDisplayParts(CreatePunctuation("("));
99
100 SetSignatureHelpParameter(signatureInfo, item);
101
102 item.SetSuffixDisplayParts(CreatePunctuation(")"));
103
104 if (signature.HasFunction() ||
105 (signature.OwnerVar() != nullptr && signature.OwnerVar()->HasFlag(varbinder::VariableFlags::METHOD))) {
106 item.SetSuffixDisplayParts(CreatePunctuation(":"));
107 } else {
108 item.SetSuffixDisplayParts(CreatePunctuation("=>"));
109 }
110
111 std::string returnType = signature.ReturnType()->ToString();
112 item.SetSuffixDisplayParts(CreateTypeName(returnType));
113
114 if (signature.HasSignatureFlag(checker::SignatureFlags::THROWS)) {
115 item.SetSuffixDisplayParts(CreateKeyword("throws"));
116 } else if (signature.HasSignatureFlag(checker::SignatureFlags::RETHROWS)) {
117 item.SetSuffixDisplayParts(CreateKeyword("rethrows"));
118 }
119
120 return item;
121 }
122
SetSignatureHelpParameter(const checker::SignatureInfo * signatureInfo,SignatureHelpItem & signatureHelpItem)123 void SetSignatureHelpParameter(const checker::SignatureInfo *signatureInfo, SignatureHelpItem &signatureHelpItem)
124 {
125 for (auto it = signatureInfo->params.begin(); it != signatureInfo->params.end(); it++) {
126 SignatureHelpParameter param;
127
128 std::string paramName =
129 (!(*it)->Name().StartsWith(GENSYM_CORE) ? std::string((*it)->Name().Utf8()) : std::string(DUMMY_ID));
130 param.SetName(paramName);
131 param.SetDisplayParts(SignatureCreateParameterName(paramName));
132
133 if ((*it)->HasFlag(varbinder::VariableFlags::OPTIONAL)) {
134 param.SetDisplayParts(CreatePunctuation("?"));
135 }
136
137 param.SetDisplayParts(CreatePunctuation(":"));
138
139 std::string paramType = (*it)->TsType()->ToString();
140 param.SetDisplayParts(CreateTypeName(paramType));
141
142 if (std::next(it) != signatureInfo->params.end()) {
143 param.SetDisplayParts(CreatePunctuation(","));
144 }
145
146 signatureHelpItem.SetParameters(param);
147 }
148
149 if (signatureInfo->restVar == nullptr) {
150 return;
151 }
152
153 SignatureHelpParameter param;
154
155 if (!signatureInfo->params.empty()) {
156 param.SetDisplayParts(CreatePunctuation(","));
157 }
158 param.SetDisplayParts(CreatePunctuation("..."));
159
160 std::string paramName =
161 (!signatureInfo->restVar->Name().StartsWith(GENSYM_CORE) ? std::string(signatureInfo->restVar->Name().Utf8())
162 : std::string(DUMMY_ID));
163 param.SetDisplayParts(SignatureCreateParameterName(paramName));
164
165 param.SetDisplayParts(CreatePunctuation(":"));
166
167 std::string paramType = signatureInfo->restVar->TsType()->ToString();
168 param.SetDisplayParts(CreateTypeName(paramType));
169
170 signatureHelpItem.SetParameters(param);
171 }
172
173 } // namespace ark::es2panda::lsp