• 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 "get_adjusted_location.h"
17 #include "internal_api.h"
18 #include <cassert>
19 #include <string>
20 #include <vector>
21 #include "public/es2panda_lib.h"
22 #include "public/public.h"
23 #include "ir/astNodeFlags.h"
24 #include "utils/arena_containers.h"
25 #include "util/options.h"
26 
27 using ark::es2panda::ir::AstNode;
28 using ark::es2panda::ir::AstNodeType;
29 using ark::es2panda::ir::ModifierFlags;
30 
31 namespace ark::es2panda::lsp {
32 
GetChildren(AstNode * node,ArenaAllocator * allocator)33 ArenaVector<AstNode *> GetChildren(AstNode *node, ArenaAllocator *allocator)
34 {
35     ArenaVector<AstNode *> children(allocator->Adapter());
36 
37     if (node == nullptr) {
38         return children;
39     }
40 
41     node->IterateRecursively([&children](const AstNode *current) {
42         if (current != nullptr) {
43             children.push_back(const_cast<AstNode *>(current));
44         }
45     });
46 
47     return children;
48 }
49 
GetTouchingPropertyName(es2panda_Context * context,size_t pos)50 AstNode *GetTouchingPropertyName(es2panda_Context *context, size_t pos)
51 {
52     AstNode *token = GetTouchingToken(context, pos, false);
53     if (token == nullptr) {
54         return nullptr;
55     }
56 
57     if (token->IsCallExpression() && token->AsCallExpression()->Callee()->IsIdentifier()) {
58         return token->AsCallExpression()->Callee()->AsIdentifier();
59     }
60 
61     if (token->IsProperty() || token->IsIdentifier()) {
62         return token;
63     }
64 
65     if (token->IsClassDeclaration() || token->IsFunctionDeclaration() || token->IsTSConstructorType()) {
66         return token;
67     }
68 
69     return nullptr;
70 }
71 
IsDeclarationOrModifier(AstNode * node,AstNode * parent,bool forRename)72 bool IsDeclarationOrModifier(AstNode *node, AstNode *parent, bool forRename)
73 {
74     return (
75         // Modifier check
76         (IsModifier(node) && forRename && CanHaveModifiers(*parent) &&
77          (parent->Modifiers() & node->Modifiers()) != 0U) ||
78         // Class implementation check
79         (node->IsTSClassImplements() && (parent->IsClassDeclaration() || node->IsClassExpression())) ||
80         // Function declaration check
81         (node->IsFunctionDeclaration() && (parent->IsFunctionDeclaration() || node->IsFunctionExpression())) ||
82         // Interface declaration check
83         (node->IsTSInterfaceDeclaration() && parent->IsTSInterfaceDeclaration()) ||
84         // Enum declaration check
85         (node->IsTSEnumDeclaration() && parent->IsTSEnumDeclaration()) ||
86         // Type alias declaration check
87         (node->IsTSTypeAliasDeclaration() && parent->IsTSTypeAliasDeclaration()) ||
88         // Module and import namespace check
89         ((node->IsImportNamespaceSpecifier() || node->IsTSModuleDeclaration()) && parent->IsTSModuleDeclaration()) ||
90         // Import equals declaration check
91         (node->IsTSImportEqualsDeclaration() && parent->IsTSImportEqualsDeclaration()));
92 }
93 
HandleTSAsExpression(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren)94 std::optional<AstNode *> HandleTSAsExpression(AstNode *node, AstNode *parent,
95                                               const ArenaVector<AstNode *> &parentChildren)
96 {
97     if (!node->IsTSAsExpression()) {
98         return std::nullopt;
99     }
100     // Import/Export specifier check
101     if (parent->IsImportSpecifier() || parent->IsExportSpecifier() || parent->IsImportNamespaceSpecifier()) {
102         return std::make_optional(FindFirstIdentifier(parent, false, parentChildren));
103     }
104     // Export all declaration check
105     if (parent->IsExportAllDeclaration()) {
106         if (auto *exportClause = FindNodeOfType(parent, AstNodeType::EXPORT_SPECIFIER, parentChildren)) {
107             if (exportClause->AsExportSpecifier()->Local()->IsIdentifier() &&
108                 exportClause->AsExportSpecifier()->Local()->AsIdentifier()->Name() == "*") {
109                 return std::make_optional(FindFirstIdentifier(exportClause, false, parentChildren));
110             }
111         }
112     }
113     return std::nullopt;
114 }
115 
HandleTSImportType(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren,bool forRename,ArenaAllocator * allocator)116 std::optional<AstNode *> HandleTSImportType(AstNode *node, AstNode *parent,
117                                             const ArenaVector<AstNode *> &parentChildren, bool forRename,
118                                             ArenaAllocator *allocator)
119 {
120     if (!node->IsTSImportType()) {
121         return std::nullopt;
122     }
123     if (auto location = GetAdjustedLocationForDeclaration(parent->Parent(), forRename, parentChildren, allocator)) {
124         return location;
125     }
126 
127     if (parent->IsExportAllDeclaration()) {
128         if (auto location = GetAdjustedLocationForExportDeclaration(parent, forRename, parentChildren)) {
129             return location;
130         }
131     }
132     return std::nullopt;
133 }
134 
HandleImportDeclaration(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren,bool forRename)135 std::optional<AstNode *> HandleImportDeclaration(AstNode *node, AstNode *parent,
136                                                  const ArenaVector<AstNode *> &parentChildren, bool forRename)
137 {
138     if (!node->IsImportDeclaration() || !parent->IsImportDeclaration()) {
139         return std::nullopt;
140     }
141     return GetAdjustedLocationForImportDeclaration(parent, forRename, parentChildren);
142 }
143 
HandleExportAllDeclaration(AstNode * node,AstNode * parent,bool forRename,const ArenaVector<AstNode * > & parentChildren)144 inline std::optional<AstNode *> HandleExportAllDeclaration(AstNode *node, AstNode *parent, bool forRename,
145                                                            const ArenaVector<AstNode *> &parentChildren)
146 {
147     if (!node->IsExportAllDeclaration() || !parent->IsExportAllDeclaration()) {
148         return std::nullopt;
149     }
150     return GetAdjustedLocationForExportDeclaration(parent, forRename, parentChildren);
151 }
152 
HandleTSClassImplements(AstNode * node,AstNode * parent)153 inline std::optional<AstNode *> HandleTSClassImplements(AstNode *node, AstNode *parent)
154 {
155     if (!node->IsTSClassImplements() || !parent->IsTSClassImplements()) {
156         return std::nullopt;
157     }
158     return GetAdjustedLocationForHeritageClause(parent);
159 }
160 
HandleTSInferType(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren)161 inline std::optional<AstNode *> HandleTSInferType(AstNode *node, AstNode *parent,
162                                                   const ArenaVector<AstNode *> &parentChildren)
163 {
164     if (!node->IsTSInferType() || !parent->IsTSInferType()) {
165         return std::nullopt;
166     }
167     if (auto *typeParam = FindTypeParameter(parent, parentChildren)) {
168         return std::make_optional(FindFirstIdentifier(typeParam, false, parentChildren));
169     }
170     return std::nullopt;
171 }
172 
HandleTSTypeParameterDeclaration(AstNode * parent,const ArenaVector<AstNode * > & parentChildren)173 inline std::optional<AstNode *> HandleTSTypeParameterDeclaration(AstNode *parent,
174                                                                  const ArenaVector<AstNode *> &parentChildren)
175 {
176     if (!parent->IsTSTypeParameterDeclaration() || !parent->Parent()->IsTSTypeParameterDeclaration()) {
177         return std::nullopt;
178     }
179     return std::make_optional(FindFirstIdentifier(parent, false, parentChildren));
180 }
181 
HandleTSTypeOperator(AstNode * parent,const ArenaVector<AstNode * > & parentChildren)182 std::optional<AstNode *> HandleTSTypeOperator(AstNode *parent, const ArenaVector<AstNode *> &parentChildren)
183 {
184     if (!parent->IsTSTypeOperator()) {
185         return std::nullopt;
186     }
187     if (auto *typeRef = FindTypeReference(parent, parentChildren)) {
188         return std::make_optional(FindFirstIdentifier(typeRef, false, parentChildren));
189     }
190     if (auto *arrayType = FindArrayType(parent, parentChildren)) {
191         if (auto *elementType = FindTypeReference(arrayType, parentChildren)) {
192             return std::make_optional(FindFirstIdentifier(elementType, false, parentChildren));
193         }
194     }
195     return std::nullopt;
196 }
197 
HandleBasicExpressions(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren)198 std::optional<AstNode *> HandleBasicExpressions(AstNode *node, AstNode *parent,
199                                                 const ArenaVector<AstNode *> &parentChildren)
200 {
201     if ((node->IsNewExpression() && parent->IsNewExpression()) ||
202         (node->IsTSVoidKeyword() && parent->IsTSVoidKeyword()) ||
203         (node->IsTypeofExpression() && parent->IsTypeofExpression()) ||
204         (node->IsAwaitExpression() && parent->IsAwaitExpression()) ||
205         (node->IsYieldExpression() && parent->IsYieldExpression())) {
206         if (auto *expr = FindFirstExpression(parent, parentChildren)) {
207             return std::make_optional(SkipOuterExpressions(expr));
208         }
209     }
210     return std::nullopt;
211 }
212 
HandleBinaryExpressions(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren)213 std::optional<AstNode *> HandleBinaryExpressions(AstNode *node, AstNode *parent,
214                                                  const ArenaVector<AstNode *> &parentChildren)
215 {
216     if (!parent->IsBinaryExpression()) {
217         return std::nullopt;
218     }
219     if (node->IsTSTypeOperator() ||
220         (node->IsForInStatement() && parent->FindChild([node](AstNode *child) { return child == node; }) != nullptr)) {
221         auto *firstExpr = FindFirstExpression(parent, parentChildren);
222         if (auto *rightExpr = FindFirstExpressionAfter(parent, firstExpr, parentChildren)) {
223             return std::make_optional(SkipOuterExpressions(rightExpr));
224         }
225     }
226     return std::nullopt;
227 }
228 
HandleForStatements(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren)229 std::optional<AstNode *> HandleForStatements(AstNode *node, AstNode *parent,
230                                              const ArenaVector<AstNode *> &parentChildren)
231 {
232     if ((node->IsForInStatement() && parent->IsForInStatement()) ||
233         (node->IsForOfStatement() && parent->IsForOfStatement())) {
234         if (auto *expr = FindFirstExpression(parent, parentChildren)) {
235             return std::make_optional(SkipOuterExpressions(expr));
236         }
237     }
238     return std::nullopt;
239 }
240 
HandleNonRenameExpressions(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren,bool forRename)241 std::optional<AstNode *> HandleNonRenameExpressions(AstNode *node, AstNode *parent,
242                                                     const ArenaVector<AstNode *> &parentChildren, bool forRename)
243 {
244     if (forRename) {
245         return std::nullopt;
246     }
247     // Try each handler in sequence
248     if (auto result = HandleBasicExpressions(node, parent, parentChildren)) {
249         return result;
250     }
251 
252     if (auto result = HandleBinaryExpressions(node, parent, parentChildren)) {
253         return result;
254     }
255     // Handle type assertions
256     if (node->IsTSAsExpression() && parent->IsTSAsExpression() && parent->IsTSTypeReference()) {
257         return std::make_optional(FindFirstIdentifier(parent, false, parentChildren));
258     }
259     if (auto result = HandleForStatements(node, parent, parentChildren)) {
260         return result;
261     }
262     return std::nullopt;
263 }
264 
HandleDefaultExport(AstNode * node,ArenaAllocator * allocator)265 std::optional<AstNode *> HandleDefaultExport(AstNode *node, ArenaAllocator *allocator)
266 {
267     if ((node->Modifiers() & ModifierFlags::DEFAULT_EXPORT) == 0U) {
268         return std::nullopt;
269     }
270     const std::array<AstNodeType, 21> declarationTypes = {AstNodeType::VARIABLE_DECLARATION,
271                                                           AstNodeType::PROPERTY,
272                                                           AstNodeType::FUNCTION_DECLARATION,
273                                                           AstNodeType::CLASS_DECLARATION,
274                                                           AstNodeType::TS_INTERFACE_DECLARATION,
275                                                           AstNodeType::TS_ENUM_DECLARATION,
276                                                           AstNodeType::TS_TYPE_ALIAS_DECLARATION,
277                                                           AstNodeType::TS_TYPE_PARAMETER_DECLARATION,
278                                                           AstNodeType::TS_MODULE_DECLARATION,
279                                                           AstNodeType::TS_CONSTRUCTOR_TYPE,
280                                                           AstNodeType::TS_TYPE_ASSERTION,
281                                                           AstNodeType::TS_AS_EXPRESSION,
282                                                           AstNodeType::TS_NON_NULL_EXPRESSION,
283                                                           AstNodeType::BINARY_EXPRESSION,
284                                                           AstNodeType::FOR_IN_STATEMENT,
285                                                           AstNodeType::FOR_OF_STATEMENT,
286                                                           AstNodeType::NEW_EXPRESSION,
287                                                           AstNodeType::TS_VOID_KEYWORD,
288                                                           AstNodeType::TYPEOF_EXPRESSION,
289                                                           AstNodeType::AWAIT_EXPRESSION,
290                                                           AstNodeType::YIELD_EXPRESSION};
291 
292     auto children = GetChildren(node, allocator);
293     for (const auto type : declarationTypes) {
294         if (auto *declaration = FindNodeOfType(node, type, children)) {
295             return std::make_optional(declaration);
296         }
297     }
298     return std::nullopt;
299 }
300 
HandleVariableDeclaration(AstNode * parent,const ArenaVector<AstNode * > & parentChildren)301 inline std::optional<AstNode *> HandleVariableDeclaration(AstNode *parent, const ArenaVector<AstNode *> &parentChildren)
302 {
303     if (parent->IsVariableDeclaration()) {
304         if (auto *identifier = FindFirstIdentifier(parent, false, parentChildren)) {
305             return std::make_optional(identifier);
306         }
307     }
308     return std::nullopt;
309 }
310 
HandleExternalModuleReference(AstNode * parent,const ArenaVector<AstNode * > & parentChildren)311 inline std::optional<AstNode *> HandleExternalModuleReference(AstNode *parent,
312                                                               const ArenaVector<AstNode *> &parentChildren)
313 {
314     if (parent->IsTSExternalModuleReference()) {
315         if (auto *expr = FindFirstExpression(parent, parentChildren)) {
316             return std::make_optional(expr);
317         }
318     }
319     return std::nullopt;
320 }
321 
HandleModuleSpecifier(AstNode * parent,const ArenaVector<AstNode * > & parentChildren)322 inline std::optional<AstNode *> HandleModuleSpecifier(AstNode *parent, const ArenaVector<AstNode *> &parentChildren)
323 {
324     if ((parent->IsImportDeclaration() || parent->IsExportAllDeclaration())) {
325         if (auto *moduleSpecifier = FindNodeOfType(parent, AstNodeType::STRING_LITERAL, parentChildren)) {
326             return std::make_optional(moduleSpecifier);
327         }
328     }
329     return std::nullopt;
330 }
331 
HandleExpressionAndTypes(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren,bool forRename,ArenaAllocator * allocator)332 std::optional<AstNode *> HandleExpressionAndTypes(AstNode *node, AstNode *parent,
333                                                   const ArenaVector<AstNode *> &parentChildren, bool forRename,
334                                                   ArenaAllocator *allocator)
335 {
336     // Expression handlers
337     if (auto result = HandleTSAsExpression(node, parent, parentChildren)) {
338         return result;
339     }
340     if (auto result = HandleTSImportType(node, parent, parentChildren, forRename, allocator)) {
341         return result;
342     }
343 
344     // Type system handlers
345     if (auto result = HandleTSClassImplements(node, parent)) {
346         return result;
347     }
348     if (auto result = HandleTSInferType(node, parent, parentChildren)) {
349         return result;
350     }
351     if (auto result = HandleTSTypeParameterDeclaration(parent, parentChildren)) {
352         return result;
353     }
354     if (auto result = HandleTSTypeOperator(parent, parentChildren)) {
355         return result;
356     }
357     return std::nullopt;
358 }
359 
HandleModulesAndExports(AstNode * node,AstNode * parent,const ArenaVector<AstNode * > & parentChildren,bool forRename,ArenaAllocator * allocator)360 std::optional<AstNode *> HandleModulesAndExports(AstNode *node, AstNode *parent,
361                                                  const ArenaVector<AstNode *> &parentChildren, bool forRename,
362                                                  ArenaAllocator *allocator)
363 {
364     // Import/Export handlers
365     if (auto result = HandleImportDeclaration(node, parent, parentChildren, forRename)) {
366         return result;
367     }
368     if (auto result = HandleExportAllDeclaration(node, parent, forRename, parentChildren)) {
369         return result;
370     }
371     if (auto result = HandleExternalModuleReference(parent, parentChildren)) {
372         return result;
373     }
374     if (auto result = HandleModuleSpecifier(parent, parentChildren)) {
375         return result;
376     }
377     if (auto result = HandleDefaultExport(node, allocator)) {
378         return result;
379     }
380 
381     return std::nullopt;
382 }
383 
GetAdjustedLocation(AstNode * node,bool forRename,ArenaAllocator * allocator)384 std::optional<AstNode *> GetAdjustedLocation(AstNode *node, bool forRename, ArenaAllocator *allocator)
385 {
386     node = GetOriginalNode(node);
387     auto *parent = node->Parent();
388     if (parent == nullptr) {
389         return std::make_optional(node);
390     }
391 
392     ArenaVector<AstNode *> parentChildren = GetChildren(parent, allocator);
393 
394     // Declaration handlers
395     if (IsDeclarationOrModifier(node, parent, forRename)) {
396         if (auto location = GetAdjustedLocationForDeclaration(parent, forRename, parentChildren, allocator)) {
397             return location;
398         }
399     }
400     // Expression and Type handlers
401     if (auto result = HandleExpressionAndTypes(node, parent, parentChildren, forRename, allocator)) {
402         return result;
403     }
404     // Module and Export handlers
405     if (auto result = HandleModulesAndExports(node, parent, parentChildren, forRename, allocator)) {
406         return result;
407     }
408     // Variable handlers
409     if (auto result = HandleVariableDeclaration(parent, parentChildren)) {
410         return result;
411     }
412     if (auto result = HandleNonRenameExpressions(node, parent, parentChildren, forRename)) {
413         return result;
414     }
415     return std::make_optional(node);
416 }
417 
GetAdjustedLocationForDeclaration(AstNode * node,bool forRename,const ArenaVector<AstNode * > & children,ArenaAllocator * allocator)418 std::optional<AstNode *> GetAdjustedLocationForDeclaration(AstNode *node, bool forRename,
419                                                            const ArenaVector<AstNode *> &children,
420                                                            ArenaAllocator *allocator)
421 {
422     if (!forRename) {
423         switch (node->Type()) {
424             case AstNodeType::CLASS_DECLARATION:
425             case AstNodeType::CLASS_EXPRESSION:
426             case AstNodeType::STRUCT_DECLARATION:
427                 return GetAdjustedLocationForClass(node, allocator);
428             case AstNodeType::FUNCTION_DECLARATION:
429             case AstNodeType::FUNCTION_EXPRESSION:
430                 return GetAdjustedLocationForFunction(node, allocator);
431             case AstNodeType::TS_CONSTRUCTOR_TYPE:
432                 return std::make_optional(node);
433             default:
434                 break;
435         }
436     }
437     if (node->IsExportNamedDeclaration()) {
438         return std::make_optional(FindFirstIdentifier(node, false, children));
439     }
440     return std::nullopt;
441 }
442 
GetAdjustedLocationForImportDeclaration(AstNode * node,bool forRename,const ArenaVector<AstNode * > & children)443 std::optional<AstNode *> GetAdjustedLocationForImportDeclaration(AstNode *node, bool forRename,
444                                                                  const ArenaVector<AstNode *> &children)
445 {
446     if (!node->IsImportDeclaration()) {
447         return std::nullopt;
448     }
449     if (forRename) {
450         auto *importNode = node->FindChild(
451             [](AstNode *child) { return child->IsImportSpecifier() || child->IsImportNamespaceSpecifier(); });
452         if (importNode != nullptr) {
453             return std::make_optional(FindFirstIdentifier(importNode, false, children));
454         }
455         return std::nullopt;
456     }
457     auto *importNode = node->FindChild(
458         [](AstNode *child) { return child->IsImportSpecifier() || child->IsImportNamespaceSpecifier(); });
459     if (importNode != nullptr) {
460         if (auto *identifier = FindFirstIdentifier(importNode, false, children)) {
461             return std::make_optional(identifier);
462         }
463         return std::make_optional(importNode);
464     }
465     return std::nullopt;
466 }
467 
GetAdjustedLocationForExportDeclaration(AstNode * node,bool forRename,const ArenaVector<AstNode * > & children)468 std::optional<AstNode *> GetAdjustedLocationForExportDeclaration(AstNode *node, bool forRename,
469                                                                  const ArenaVector<AstNode *> &children)
470 {
471     if (!node->IsExportAllDeclaration()) {
472         return std::nullopt;
473     }
474     if (forRename) {
475         return std::make_optional(FindFirstIdentifier(node, false, children));
476     }
477     auto *exportSpecifier = FindNodeOfType(node, AstNodeType::EXPORT_SPECIFIER, children);
478     if (exportSpecifier != nullptr) {
479         if (auto *identifier = FindFirstIdentifier(exportSpecifier, false, children)) {
480             return std::make_optional(identifier);
481         }
482         return std::make_optional(exportSpecifier);
483     }
484     if ((node->Modifiers() & ModifierFlags::DEFAULT_EXPORT) != 0U) {
485         const std::array<AstNodeType, 21> declarationTypes = {AstNodeType::VARIABLE_DECLARATION,
486                                                               AstNodeType::PROPERTY,
487                                                               AstNodeType::FUNCTION_DECLARATION,
488                                                               AstNodeType::CLASS_DECLARATION,
489                                                               AstNodeType::TS_INTERFACE_DECLARATION,
490                                                               AstNodeType::TS_ENUM_DECLARATION,
491                                                               AstNodeType::TS_TYPE_ALIAS_DECLARATION,
492                                                               AstNodeType::TS_TYPE_PARAMETER_DECLARATION,
493                                                               AstNodeType::TS_MODULE_DECLARATION,
494                                                               AstNodeType::TS_CONSTRUCTOR_TYPE,
495                                                               AstNodeType::TS_TYPE_ASSERTION,
496                                                               AstNodeType::TS_AS_EXPRESSION,
497                                                               AstNodeType::TS_NON_NULL_EXPRESSION,
498                                                               AstNodeType::BINARY_EXPRESSION,
499                                                               AstNodeType::FOR_IN_STATEMENT,
500                                                               AstNodeType::FOR_OF_STATEMENT,
501                                                               AstNodeType::NEW_EXPRESSION,
502                                                               AstNodeType::TS_VOID_KEYWORD,
503                                                               AstNodeType::TYPEOF_EXPRESSION,
504                                                               AstNodeType::AWAIT_EXPRESSION,
505                                                               AstNodeType::YIELD_EXPRESSION};
506 
507         for (const auto type : declarationTypes) {
508             if (auto *declaration = FindNodeOfType(node, type, children)) {
509                 return std::make_optional(declaration);
510             }
511         }
512     }
513     return std::nullopt;
514 }
515 
GetAdjustedLocationForClass(AstNode * node,ArenaAllocator * allocator)516 std::optional<AstNode *> GetAdjustedLocationForClass(AstNode *node, ArenaAllocator *allocator)
517 {
518     if (node == nullptr || (!node->IsClassDeclaration() && !node->IsClassExpression())) {
519         return std::nullopt;
520     }
521     auto children = GetChildren(node, allocator);
522     return std::make_optional(FindFirstIdentifier(node, false, children));
523 }
524 
GetAdjustedLocationForFunction(AstNode * node,ArenaAllocator * allocator)525 std::optional<AstNode *> GetAdjustedLocationForFunction(AstNode *node, ArenaAllocator *allocator)
526 {
527     if (node->IsIdentifier()) {
528         return std::make_optional(node);
529     }
530     if (node->IsFunctionDeclaration()) {
531         auto children = GetChildren(node, allocator);
532         return std::make_optional(FindFirstIdentifier(node, false, children));
533     }
534     if (auto *parent = node->Parent()) {
535         if (parent->IsFunctionDeclaration()) {
536             auto children = GetChildren(parent, allocator);
537             return std::make_optional(FindFirstIdentifier(parent, false, children));
538         }
539     }
540     return std::nullopt;
541 }
542 
IsModifier(const AstNode * node)543 bool IsModifier(const AstNode *node)
544 {
545     if (node == nullptr) {
546         return false;
547     }
548     switch (node->Modifiers()) {
549         case ModifierFlags::ABSTRACT:
550         case ModifierFlags::ACCESS:
551         case ModifierFlags::ASYNC:
552         case ModifierFlags::CONST:
553         case ModifierFlags::DECLARE:
554         case ModifierFlags::DEFAULT_EXPORT:
555         case ModifierFlags::IN:
556         case ModifierFlags::EXPORT:
557         case ModifierFlags::PUBLIC:
558         case ModifierFlags::PRIVATE:
559         case ModifierFlags::PROTECTED:
560         case ModifierFlags::READONLY:
561         case ModifierFlags::STATIC:
562         case ModifierFlags::OUT:
563         case ModifierFlags::OVERRIDE:
564             return true;
565         default:
566             return false;
567     }
568 }
569 
IsOuterExpression(const AstNode * node)570 bool IsOuterExpression(const AstNode *node)
571 {
572     if (node == nullptr) {
573         return false;
574     }
575     switch (node->Type()) {
576         case AstNodeType::TS_TYPE_ASSERTION:
577         case AstNodeType::TS_AS_EXPRESSION:
578         case AstNodeType::TS_NON_NULL_EXPRESSION:
579             return true;
580         default:
581             return false;
582     }
583 }
584 
SkipOuterExpressions(AstNode * node)585 AstNode *SkipOuterExpressions(AstNode *node)
586 {
587     if (node == nullptr) {
588         return node;
589     }
590     if (node->IsExpression() && IsOuterExpression(node)) {
591         return node;
592     }
593     return node;
594 }
595 
GetAdjustedLocationForHeritageClause(AstNode * node)596 std::optional<AstNode *> GetAdjustedLocationForHeritageClause(AstNode *node)
597 {
598     if (node == nullptr || node->Type() != AstNodeType::TS_INTERFACE_HERITAGE) {
599         return std::nullopt;
600     }
601     auto *expression = node->FindChild(
602         [](AstNode *child) { return child->IsExpression() || child->IsIdentifier() || child->IsTSTypeReference(); });
603     return expression != nullptr ? std::make_optional(expression) : std::nullopt;
604 }
605 
CanHaveModifiers(const AstNode & node)606 bool CanHaveModifiers(const AstNode &node)
607 {
608     switch (node.Type()) {
609         case AstNodeType::CLASS_DECLARATION:
610         case AstNodeType::FUNCTION_DECLARATION:
611         case AstNodeType::METHOD_DEFINITION:
612         case AstNodeType::PROPERTY:
613         case AstNodeType::TS_CONSTRUCTOR_TYPE:
614         case AstNodeType::TS_INTERFACE_DECLARATION:
615         case AstNodeType::TS_TYPE_ALIAS_DECLARATION:
616         case AstNodeType::TS_ENUM_DECLARATION:
617         case AstNodeType::TS_MODULE_DECLARATION:
618         case AstNodeType::VARIABLE_DECLARATION:
619             return true;
620         default:
621             return false;
622     }
623 }
624 
FindFirstIdentifier(AstNode * node,bool skipModifiers,const ArenaVector<AstNode * > & children)625 AstNode *FindFirstIdentifier(AstNode *node, bool skipModifiers, const ArenaVector<AstNode *> &children)
626 {
627     if (node->IsIdentifier() && (!skipModifiers || !IsModifier(node))) {
628         return node;
629     }
630     for (auto *child : children) {
631         if (child->IsIdentifier() && (!skipModifiers || !IsModifier(child))) {
632             return child;
633         }
634     }
635     return nullptr;
636 }
637 
FindFirstExpression(AstNode * node,const ArenaVector<AstNode * > & children)638 AstNode *FindFirstExpression(AstNode *node, const ArenaVector<AstNode *> &children)
639 {
640     if (node->IsExpression()) {
641         return node;
642     }
643     for (auto *child : children) {
644         if (child->IsExpression()) {
645             return child;
646         }
647     }
648     return nullptr;
649 }
650 
FindFirstExpressionAfter(AstNode * node,AstNode * after,const ArenaVector<AstNode * > & children)651 AstNode *FindFirstExpressionAfter(AstNode *node, AstNode *after, const ArenaVector<AstNode *> &children)
652 {
653     if (node->IsExpression() && node != after) {
654         return node;
655     }
656     bool foundAfter = false;
657     for (auto *child : children) {
658         if (child == after) {
659             foundAfter = true;
660             continue;
661         }
662         if (foundAfter && child->IsExpression()) {
663             return child;
664         }
665     }
666     return nullptr;
667 }
668 
FindNodeOfType(AstNode * node,AstNodeType type,const ArenaVector<AstNode * > & children)669 AstNode *FindNodeOfType(AstNode *node, AstNodeType type, const ArenaVector<AstNode *> &children)
670 {
671     if (node->Type() == type) {
672         return node;
673     }
674     for (auto *child : children) {
675         if (child->Type() == type) {
676             return child;
677         }
678     }
679     return nullptr;
680 }
681 
FindTypeReference(AstNode * node,const ArenaVector<AstNode * > & children)682 AstNode *FindTypeReference(AstNode *node, const ArenaVector<AstNode *> &children)
683 {
684     if (node != nullptr && node->IsTSTypeReference()) {
685         return node;
686     }
687     for (auto *child : children) {
688         if (child->IsTSTypeReference()) {
689             return child;
690         }
691     }
692     return nullptr;
693 }
694 
FindTypeParameter(AstNode * node,const ArenaVector<AstNode * > & children)695 AstNode *FindTypeParameter(AstNode *node, const ArenaVector<AstNode *> &children)
696 {
697     if (node->IsTSTypeParameterDeclaration()) {
698         return node;
699     }
700 
701     for (auto *child : children) {
702         if (child->IsTSTypeParameterDeclaration()) {
703             return child;
704         }
705         if (child->IsIdentifier() && child->AsIdentifier()->Name() == "T") {
706             return child;
707         }
708     }
709 
710     return nullptr;
711 }
712 
FindArrayType(AstNode * node,const ArenaVector<AstNode * > & children)713 AstNode *FindArrayType(AstNode *node, const ArenaVector<AstNode *> &children)
714 {
715     if (node->IsTSArrayType()) {
716         return node;
717     }
718     for (auto *child : children) {
719         if (child->IsTSArrayType()) {
720             return child;
721         }
722     }
723     return nullptr;
724 }
725 
726 }  // namespace ark::es2panda::lsp