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