13af6ab5fSopenharmony_ci/* 23af6ab5fSopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ciimport * as ts from 'typescript'; 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_cifunction isInstanceofContext(tsIdentStart: ts.Node): boolean { 193af6ab5fSopenharmony_ci return ( 203af6ab5fSopenharmony_ci ts.isBinaryExpression(tsIdentStart.parent) && 213af6ab5fSopenharmony_ci tsIdentStart.parent.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword 223af6ab5fSopenharmony_ci ); 233af6ab5fSopenharmony_ci} 243af6ab5fSopenharmony_ci 253af6ab5fSopenharmony_cifunction isNewExpressionContext(tsIdentStart: ts.Node): boolean { 263af6ab5fSopenharmony_ci return ts.isNewExpression(tsIdentStart.parent) && tsIdentStart === tsIdentStart.parent.expression; 273af6ab5fSopenharmony_ci} 283af6ab5fSopenharmony_ci 293af6ab5fSopenharmony_ci/* 303af6ab5fSopenharmony_ci * If identifier is the right-most name of Property Access chain or Qualified name, 313af6ab5fSopenharmony_ci * or it's a separate identifier expression, then identifier is being referenced as an value. 323af6ab5fSopenharmony_ci */ 333af6ab5fSopenharmony_cifunction isQualifiedNameContext(tsIdentStart: ts.Node, tsIdentifier: ts.Identifier): boolean { 343af6ab5fSopenharmony_ci // rightmost in AST is rightmost in qualified name chain 353af6ab5fSopenharmony_ci return ts.isQualifiedName(tsIdentStart) && tsIdentifier !== tsIdentStart.right; 363af6ab5fSopenharmony_ci} 373af6ab5fSopenharmony_ci 383af6ab5fSopenharmony_cifunction isPropertyAccessContext(tsIdentStart: ts.Node, tsIdentifier: ts.Identifier): boolean { 393af6ab5fSopenharmony_ci // rightmost in AST is rightmost in qualified name chain 403af6ab5fSopenharmony_ci return ts.isPropertyAccessExpression(tsIdentStart) && tsIdentifier !== tsIdentStart.name; 413af6ab5fSopenharmony_ci} 423af6ab5fSopenharmony_ci 433af6ab5fSopenharmony_cifunction getQualifiedStart(ident: ts.Node): ts.Node { 443af6ab5fSopenharmony_ci let qualifiedStart: ts.Node = ident; 453af6ab5fSopenharmony_ci while (ts.isPropertyAccessExpression(qualifiedStart.parent) || ts.isQualifiedName(qualifiedStart.parent)) { 463af6ab5fSopenharmony_ci qualifiedStart = qualifiedStart.parent; 473af6ab5fSopenharmony_ci } 483af6ab5fSopenharmony_ci return qualifiedStart; 493af6ab5fSopenharmony_ci} 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_cifunction isEnumPropAccess(ident: ts.Identifier, tsSym: ts.Symbol, context: ts.Node): boolean { 523af6ab5fSopenharmony_ci return ( 533af6ab5fSopenharmony_ci ts.isElementAccessExpression(context) && 543af6ab5fSopenharmony_ci !!(tsSym.flags & ts.SymbolFlags.Enum) && 553af6ab5fSopenharmony_ci (context.expression === ident || 563af6ab5fSopenharmony_ci ts.isPropertyAccessExpression(context.expression) && context.expression.name === ident) 573af6ab5fSopenharmony_ci ); 583af6ab5fSopenharmony_ci} 593af6ab5fSopenharmony_ci 603af6ab5fSopenharmony_cifunction isValidParent(parent: ts.Node): boolean { 613af6ab5fSopenharmony_ci // treat TypeQuery as valid because it's already forbidden (FaultID.TypeQuery) 623af6ab5fSopenharmony_ci return ( 633af6ab5fSopenharmony_ci ts.isTypeNode(parent) && !ts.isTypeOfExpression(parent) || 643af6ab5fSopenharmony_ci ts.isExpressionWithTypeArguments(parent) || 653af6ab5fSopenharmony_ci ts.isExportAssignment(parent) || 663af6ab5fSopenharmony_ci ts.isExportSpecifier(parent) || 673af6ab5fSopenharmony_ci ts.isMetaProperty(parent) || 683af6ab5fSopenharmony_ci ts.isImportClause(parent) || 693af6ab5fSopenharmony_ci ts.isClassLike(parent) || 703af6ab5fSopenharmony_ci ts.isInterfaceDeclaration(parent) || 713af6ab5fSopenharmony_ci ts.isModuleDeclaration(parent) || 723af6ab5fSopenharmony_ci ts.isEnumDeclaration(parent) || 733af6ab5fSopenharmony_ci ts.isNamespaceImport(parent) || 743af6ab5fSopenharmony_ci ts.isImportSpecifier(parent) || 753af6ab5fSopenharmony_ci ts.isImportEqualsDeclaration(parent) 763af6ab5fSopenharmony_ci ); 773af6ab5fSopenharmony_ci} 783af6ab5fSopenharmony_ci 793af6ab5fSopenharmony_ciexport function identiferUseInValueContext(ident: ts.Identifier, tsSym: ts.Symbol): boolean { 803af6ab5fSopenharmony_ci const qualifiedStart = getQualifiedStart(ident); 813af6ab5fSopenharmony_ci const parent = qualifiedStart.parent; 823af6ab5fSopenharmony_ci const isValidUse = 833af6ab5fSopenharmony_ci isValidParent(parent) || 843af6ab5fSopenharmony_ci isEnumPropAccess(ident, tsSym, parent) || 853af6ab5fSopenharmony_ci isQualifiedNameContext(qualifiedStart, ident) || 863af6ab5fSopenharmony_ci isPropertyAccessContext(qualifiedStart, ident) || 873af6ab5fSopenharmony_ci isNewExpressionContext(qualifiedStart) || 883af6ab5fSopenharmony_ci isInstanceofContext(qualifiedStart); 893af6ab5fSopenharmony_ci return !isValidUse; 903af6ab5fSopenharmony_ci} 91