• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 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
16import type {Expression, Node, ObjectBindingPattern} from 'typescript';
17import {
18  isBindingElement,
19  isCallExpression,
20  isComputedPropertyName,
21  isConstructorDeclaration,
22  isElementAccessExpression,
23  isEnumMember,
24  isGetAccessor,
25  isIdentifier,
26  isMethodDeclaration,
27  isMethodSignature,
28  isParameter,
29  isPropertyAccessExpression,
30  isPropertyAssignment,
31  isPropertyDeclaration,
32  isPropertySignature,
33  isQualifiedName,
34  isSetAccessor,
35  isVariableDeclaration
36} from 'typescript';
37
38export class NodeUtils {
39  public static isPropertyDeclarationNode(node: Node): boolean {
40    let parent: Node | undefined = node.parent;
41    if (!parent) {
42      return false;
43    }
44
45    /** eg: { 'name'' : 'akira' }, pass */
46    if (isPropertyAssignment(parent)) {
47      return parent.name === node;
48    }
49
50    if (isComputedPropertyName(parent) && parent.expression === node) {
51      return true;
52    }
53
54    /** object binding pattern */
55    if (isBindingElement(parent) && parent.propertyName === node) {
56      return true;
57    }
58
59    /** eg: interface/type inf { 'name' : string}, pass */
60    if (isPropertySignature(parent) && parent.name === node) {
61      return true;
62    }
63
64    /** eg: interface/type T1 { func(arg: string): number;} */
65    if (isMethodSignature(parent) && parent.name === node) {
66      return true;
67    }
68
69    /** eg: enum { xxx = 1}; */
70    if (isEnumMember(parent) && parent.name === node) {
71      return true;
72    }
73
74    /** class { private name= 1}; */
75    if (isPropertyDeclaration(parent) && parent.name === node) {
76      return true;
77    }
78
79    /** class {'getName': function() {}} let _ = { getName() [}} */
80    if (isMethodDeclaration(parent) && parent.name === node) {
81      return true;
82    }
83
84    if (isSetAccessor(parent) && parent.name === node) {
85      return true;
86    }
87
88    return isGetAccessor(parent) && parent.name === node;
89  }
90
91  public static isPropertyOrElementAccessNode(node: Node): boolean {
92    return this.isPropertyAccessNode(node) || this.isElementAccessNode(node) || false;
93  }
94
95  public static isPropertyAccessNode(node: Node): boolean {
96    let parent: Node | undefined = node.parent;
97    if (!parent) {
98      return false;
99    }
100
101    /** eg: a.b = 1 */
102    if (isPropertyAccessExpression(parent) && parent.name === node) {
103      return true;
104    }
105    return isQualifiedName(parent) && parent.right === node;
106  }
107
108  public static isElementAccessNode(node: Node): boolean {
109    let parent: Node | undefined = node.parent;
110    if (!parent) {
111      return false;
112    }
113
114    return isElementAccessExpression(parent) && parent.argumentExpression === node;
115  }
116
117  public static isClassPropertyInConstructorParams(node: Node): boolean {
118    if (!isIdentifier(node)) {
119      return false;
120    }
121
122    if (!node.parent || !isParameter(node.parent)) {
123      return false;
124    }
125
126    return node.parent.parent && isConstructorDeclaration(node.parent.parent);
127  }
128
129  public static isClassPropertyInConstructorBody(node: Node, constructorParams: Set<string>): boolean {
130    if (!isIdentifier(node)) {
131      return false;
132    }
133
134    const id: string = node.escapedText.toString();
135    let curNode: Node = node.parent;
136    while (curNode) {
137      if (isConstructorDeclaration(curNode) && constructorParams.has(id)) {
138        return true;
139      }
140
141      curNode = curNode.parent;
142    }
143
144    return false;
145  }
146
147  public static isPropertyNode(node: Node): boolean {
148    if (this.isPropertyOrElementAccessNode(node)) {
149      return true;
150    }
151
152    return this.isPropertyDeclarationNode(node);
153  }
154
155  public static isObjectBindingPatternAssignment(node: ObjectBindingPattern): boolean {
156    if (!node || !node.parent || !isVariableDeclaration(node.parent)) {
157      return false;
158    }
159
160    const initializer: Expression = node.parent.initializer;
161    return initializer && isCallExpression(initializer);
162  }
163}
164