• 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 "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 &currentSignature = 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