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 path from 'node:path'; 173af6ab5fSopenharmony_ciimport * as ts from 'typescript'; 183af6ab5fSopenharmony_ciimport type { IsEtsFileCallback } from '../IsEtsFileCallback'; 193af6ab5fSopenharmony_ciimport { FaultID } from '../Problems'; 203af6ab5fSopenharmony_ciimport { ARKTS_IGNORE_DIRS, ARKTS_IGNORE_FILES } from './consts/ArktsIgnorePaths'; 213af6ab5fSopenharmony_ciimport { ES_OBJECT } from './consts/ESObject'; 223af6ab5fSopenharmony_ciimport { EXTENDED_BASE_TYPES } from './consts/ExtendedBaseTypes'; 233af6ab5fSopenharmony_ciimport { SENDABLE_DECORATOR } from './consts/SendableAPI'; 243af6ab5fSopenharmony_ciimport { USE_SHARED } from './consts/SharedModuleAPI'; 253af6ab5fSopenharmony_ciimport { STANDARD_LIBRARIES } from './consts/StandardLibraries'; 263af6ab5fSopenharmony_ciimport { 273af6ab5fSopenharmony_ci ARKTS_COLLECTIONS_D_ETS, 283af6ab5fSopenharmony_ci ARKTS_LANG_D_ETS, 293af6ab5fSopenharmony_ci COLLECTIONS_NAMESPACE, 303af6ab5fSopenharmony_ci ISENDABLE_TYPE, 313af6ab5fSopenharmony_ci LANG_NAMESPACE 323af6ab5fSopenharmony_ci} from './consts/SupportedDetsIndexableTypes'; 333af6ab5fSopenharmony_ciimport { TYPED_ARRAYS } from './consts/TypedArrays'; 343af6ab5fSopenharmony_ciimport { forEachNodeInSubtree } from './functions/ForEachNodeInSubtree'; 353af6ab5fSopenharmony_ciimport { getScriptKind } from './functions/GetScriptKind'; 363af6ab5fSopenharmony_ciimport { isStdLibrarySymbol, isStdLibraryType } from './functions/IsStdLibrary'; 373af6ab5fSopenharmony_ciimport { isStructDeclaration, isStructDeclarationKind } from './functions/IsStruct'; 383af6ab5fSopenharmony_ciimport type { NameGenerator } from './functions/NameGenerator'; 393af6ab5fSopenharmony_ciimport { srcFilePathContainsDirectory } from './functions/PathHelper'; 403af6ab5fSopenharmony_ciimport { isAssignmentOperator } from './functions/isAssignmentOperator'; 413af6ab5fSopenharmony_ciimport { isIntrinsicObjectType } from './functions/isIntrinsicObjectType'; 423af6ab5fSopenharmony_ci 433af6ab5fSopenharmony_ciexport const SYMBOL = 'Symbol'; 443af6ab5fSopenharmony_ciexport const SYMBOL_CONSTRUCTOR = 'SymbolConstructor'; 453af6ab5fSopenharmony_ciconst ITERATOR = 'iterator'; 463af6ab5fSopenharmony_ci 473af6ab5fSopenharmony_ciexport type CheckType = (this: TsUtils, t: ts.Type) => boolean; 483af6ab5fSopenharmony_ciexport class TsUtils { 493af6ab5fSopenharmony_ci constructor( 503af6ab5fSopenharmony_ci private readonly tsTypeChecker: ts.TypeChecker, 513af6ab5fSopenharmony_ci private readonly testMode: boolean, 523af6ab5fSopenharmony_ci private readonly advancedClassChecks: boolean, 533af6ab5fSopenharmony_ci private readonly useSdkLogic: boolean, 543af6ab5fSopenharmony_ci private readonly arkts2: boolean 553af6ab5fSopenharmony_ci ) {} 563af6ab5fSopenharmony_ci 573af6ab5fSopenharmony_ci entityNameToString(name: ts.EntityName): string { 583af6ab5fSopenharmony_ci if (ts.isIdentifier(name)) { 593af6ab5fSopenharmony_ci return name.escapedText.toString(); 603af6ab5fSopenharmony_ci } 613af6ab5fSopenharmony_ci return this.entityNameToString(name.left) + this.entityNameToString(name.right); 623af6ab5fSopenharmony_ci } 633af6ab5fSopenharmony_ci 643af6ab5fSopenharmony_ci isNumberLikeType(tsType: ts.Type): boolean { 653af6ab5fSopenharmony_ci if (!this.useSdkLogic && tsType.isUnion()) { 663af6ab5fSopenharmony_ci for (const tsCompType of tsType.types) { 673af6ab5fSopenharmony_ci if ((tsCompType.flags & ts.TypeFlags.NumberLike) === 0) { 683af6ab5fSopenharmony_ci return false; 693af6ab5fSopenharmony_ci } 703af6ab5fSopenharmony_ci } 713af6ab5fSopenharmony_ci return true; 723af6ab5fSopenharmony_ci } 733af6ab5fSopenharmony_ci return (tsType.getFlags() & ts.TypeFlags.NumberLike) !== 0; 743af6ab5fSopenharmony_ci } 753af6ab5fSopenharmony_ci 763af6ab5fSopenharmony_ci static isBooleanLikeType(tsType: ts.Type): boolean { 773af6ab5fSopenharmony_ci return (tsType.getFlags() & ts.TypeFlags.BooleanLike) !== 0; 783af6ab5fSopenharmony_ci } 793af6ab5fSopenharmony_ci 803af6ab5fSopenharmony_ci static isDestructuringAssignmentLHS(tsExpr: ts.ArrayLiteralExpression | ts.ObjectLiteralExpression): boolean { 813af6ab5fSopenharmony_ci 823af6ab5fSopenharmony_ci /* 833af6ab5fSopenharmony_ci * Check whether given expression is the LHS part of the destructuring 843af6ab5fSopenharmony_ci * assignment (or is a nested element of destructuring pattern). 853af6ab5fSopenharmony_ci */ 863af6ab5fSopenharmony_ci let tsParent = tsExpr.parent; 873af6ab5fSopenharmony_ci let tsCurrentExpr: ts.Node = tsExpr; 883af6ab5fSopenharmony_ci while (tsParent) { 893af6ab5fSopenharmony_ci if ( 903af6ab5fSopenharmony_ci ts.isBinaryExpression(tsParent) && 913af6ab5fSopenharmony_ci isAssignmentOperator(tsParent.operatorToken) && 923af6ab5fSopenharmony_ci tsParent.left === tsCurrentExpr 933af6ab5fSopenharmony_ci ) { 943af6ab5fSopenharmony_ci return true; 953af6ab5fSopenharmony_ci } 963af6ab5fSopenharmony_ci 973af6ab5fSopenharmony_ci if ( 983af6ab5fSopenharmony_ci (ts.isForStatement(tsParent) || ts.isForInStatement(tsParent) || ts.isForOfStatement(tsParent)) && 993af6ab5fSopenharmony_ci tsParent.initializer && 1003af6ab5fSopenharmony_ci tsParent.initializer === tsCurrentExpr 1013af6ab5fSopenharmony_ci ) { 1023af6ab5fSopenharmony_ci return true; 1033af6ab5fSopenharmony_ci } 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_ci tsCurrentExpr = tsParent; 1063af6ab5fSopenharmony_ci tsParent = tsParent.parent; 1073af6ab5fSopenharmony_ci } 1083af6ab5fSopenharmony_ci 1093af6ab5fSopenharmony_ci return false; 1103af6ab5fSopenharmony_ci } 1113af6ab5fSopenharmony_ci 1123af6ab5fSopenharmony_ci static isEnumType(tsType: ts.Type): boolean { 1133af6ab5fSopenharmony_ci // when type equals `typeof <Enum>`, only symbol contains information about it's type. 1143af6ab5fSopenharmony_ci const isEnumSymbol = tsType.symbol && this.isEnum(tsType.symbol); 1153af6ab5fSopenharmony_ci // otherwise, we should analyze flags of the type itself 1163af6ab5fSopenharmony_ci const isEnumType = !!(tsType.flags & ts.TypeFlags.Enum) || !!(tsType.flags & ts.TypeFlags.EnumLiteral); 1173af6ab5fSopenharmony_ci return isEnumSymbol || isEnumType; 1183af6ab5fSopenharmony_ci } 1193af6ab5fSopenharmony_ci 1203af6ab5fSopenharmony_ci static isEnum(tsSymbol: ts.Symbol): boolean { 1213af6ab5fSopenharmony_ci return !!(tsSymbol.flags & ts.SymbolFlags.Enum); 1223af6ab5fSopenharmony_ci } 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ci static hasModifier(tsModifiers: readonly ts.Modifier[] | undefined, tsModifierKind: number): boolean { 1253af6ab5fSopenharmony_ci if (!tsModifiers) { 1263af6ab5fSopenharmony_ci return false; 1273af6ab5fSopenharmony_ci } 1283af6ab5fSopenharmony_ci 1293af6ab5fSopenharmony_ci for (const tsModifier of tsModifiers) { 1303af6ab5fSopenharmony_ci if (tsModifier.kind === tsModifierKind) { 1313af6ab5fSopenharmony_ci return true; 1323af6ab5fSopenharmony_ci } 1333af6ab5fSopenharmony_ci } 1343af6ab5fSopenharmony_ci 1353af6ab5fSopenharmony_ci return false; 1363af6ab5fSopenharmony_ci } 1373af6ab5fSopenharmony_ci 1383af6ab5fSopenharmony_ci static unwrapParenthesized(tsExpr: ts.Expression): ts.Expression { 1393af6ab5fSopenharmony_ci let unwrappedExpr = tsExpr; 1403af6ab5fSopenharmony_ci while (ts.isParenthesizedExpression(unwrappedExpr)) { 1413af6ab5fSopenharmony_ci unwrappedExpr = unwrappedExpr.expression; 1423af6ab5fSopenharmony_ci } 1433af6ab5fSopenharmony_ci 1443af6ab5fSopenharmony_ci return unwrappedExpr; 1453af6ab5fSopenharmony_ci } 1463af6ab5fSopenharmony_ci 1473af6ab5fSopenharmony_ci followIfAliased(sym: ts.Symbol): ts.Symbol { 1483af6ab5fSopenharmony_ci if ((sym.getFlags() & ts.SymbolFlags.Alias) !== 0) { 1493af6ab5fSopenharmony_ci return this.tsTypeChecker.getAliasedSymbol(sym); 1503af6ab5fSopenharmony_ci } 1513af6ab5fSopenharmony_ci return sym; 1523af6ab5fSopenharmony_ci } 1533af6ab5fSopenharmony_ci 1543af6ab5fSopenharmony_ci private readonly trueSymbolAtLocationCache = new Map<ts.Node, ts.Symbol | null>(); 1553af6ab5fSopenharmony_ci 1563af6ab5fSopenharmony_ci trueSymbolAtLocation(node: ts.Node): ts.Symbol | undefined { 1573af6ab5fSopenharmony_ci const cache = this.trueSymbolAtLocationCache; 1583af6ab5fSopenharmony_ci const val = cache.get(node); 1593af6ab5fSopenharmony_ci if (val !== undefined) { 1603af6ab5fSopenharmony_ci return val !== null ? val : undefined; 1613af6ab5fSopenharmony_ci } 1623af6ab5fSopenharmony_ci let sym = this.tsTypeChecker.getSymbolAtLocation(node); 1633af6ab5fSopenharmony_ci if (sym === undefined) { 1643af6ab5fSopenharmony_ci cache.set(node, null); 1653af6ab5fSopenharmony_ci return undefined; 1663af6ab5fSopenharmony_ci } 1673af6ab5fSopenharmony_ci sym = this.followIfAliased(sym); 1683af6ab5fSopenharmony_ci cache.set(node, sym); 1693af6ab5fSopenharmony_ci return sym; 1703af6ab5fSopenharmony_ci } 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_ci private static isTypeDeclSyntaxKind(kind: ts.SyntaxKind): boolean { 1733af6ab5fSopenharmony_ci return ( 1743af6ab5fSopenharmony_ci isStructDeclarationKind(kind) || 1753af6ab5fSopenharmony_ci kind === ts.SyntaxKind.EnumDeclaration || 1763af6ab5fSopenharmony_ci kind === ts.SyntaxKind.ClassDeclaration || 1773af6ab5fSopenharmony_ci kind === ts.SyntaxKind.InterfaceDeclaration || 1783af6ab5fSopenharmony_ci kind === ts.SyntaxKind.TypeAliasDeclaration 1793af6ab5fSopenharmony_ci ); 1803af6ab5fSopenharmony_ci } 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci static symbolHasDuplicateName(symbol: ts.Symbol, tsDeclKind: ts.SyntaxKind): boolean { 1833af6ab5fSopenharmony_ci 1843af6ab5fSopenharmony_ci /* 1853af6ab5fSopenharmony_ci * Type Checker merges all declarations with the same name in one scope into one symbol. 1863af6ab5fSopenharmony_ci * Thus, check whether the symbol of certain declaration has any declaration with 1873af6ab5fSopenharmony_ci * different syntax kind. 1883af6ab5fSopenharmony_ci */ 1893af6ab5fSopenharmony_ci const symbolDecls = symbol?.getDeclarations(); 1903af6ab5fSopenharmony_ci if (symbolDecls) { 1913af6ab5fSopenharmony_ci for (const symDecl of symbolDecls) { 1923af6ab5fSopenharmony_ci const declKind = symDecl.kind; 1933af6ab5fSopenharmony_ci // we relax arkts-unique-names for namespace collision with class/interface/enum/type/struct 1943af6ab5fSopenharmony_ci const isNamespaceTypeCollision = 1953af6ab5fSopenharmony_ci TsUtils.isTypeDeclSyntaxKind(declKind) && tsDeclKind === ts.SyntaxKind.ModuleDeclaration || 1963af6ab5fSopenharmony_ci TsUtils.isTypeDeclSyntaxKind(tsDeclKind) && declKind === ts.SyntaxKind.ModuleDeclaration; 1973af6ab5fSopenharmony_ci 1983af6ab5fSopenharmony_ci /* 1993af6ab5fSopenharmony_ci * Don't count declarations with 'Identifier' syntax kind as those 2003af6ab5fSopenharmony_ci * usually depict declaring an object's property through assignment. 2013af6ab5fSopenharmony_ci */ 2023af6ab5fSopenharmony_ci if (declKind !== ts.SyntaxKind.Identifier && declKind !== tsDeclKind && !isNamespaceTypeCollision) { 2033af6ab5fSopenharmony_ci return true; 2043af6ab5fSopenharmony_ci } 2053af6ab5fSopenharmony_ci } 2063af6ab5fSopenharmony_ci } 2073af6ab5fSopenharmony_ci 2083af6ab5fSopenharmony_ci return false; 2093af6ab5fSopenharmony_ci } 2103af6ab5fSopenharmony_ci 2113af6ab5fSopenharmony_ci static isPrimitiveType(type: ts.Type): boolean { 2123af6ab5fSopenharmony_ci const f = type.getFlags(); 2133af6ab5fSopenharmony_ci return ( 2143af6ab5fSopenharmony_ci (f & ts.TypeFlags.Boolean) !== 0 || 2153af6ab5fSopenharmony_ci (f & ts.TypeFlags.BooleanLiteral) !== 0 || 2163af6ab5fSopenharmony_ci (f & ts.TypeFlags.Number) !== 0 || 2173af6ab5fSopenharmony_ci (f & ts.TypeFlags.NumberLiteral) !== 0 2183af6ab5fSopenharmony_ci 2193af6ab5fSopenharmony_ci /* 2203af6ab5fSopenharmony_ci * In ArkTS 'string' is not a primitive type. So for the common subset 'string' 2213af6ab5fSopenharmony_ci * should be considered as a reference type. That is why next line is commented out. 2223af6ab5fSopenharmony_ci * (f & ts.TypeFlags.String) != 0 || (f & ts.TypeFlags.StringLiteral) != 0 2233af6ab5fSopenharmony_ci */ 2243af6ab5fSopenharmony_ci ); 2253af6ab5fSopenharmony_ci } 2263af6ab5fSopenharmony_ci 2273af6ab5fSopenharmony_ci static isPrimitiveLiteralType(type: ts.Type): boolean { 2283af6ab5fSopenharmony_ci return !!( 2293af6ab5fSopenharmony_ci type.flags & 2303af6ab5fSopenharmony_ci (ts.TypeFlags.BooleanLiteral | 2313af6ab5fSopenharmony_ci ts.TypeFlags.NumberLiteral | 2323af6ab5fSopenharmony_ci ts.TypeFlags.StringLiteral | 2333af6ab5fSopenharmony_ci ts.TypeFlags.BigIntLiteral) 2343af6ab5fSopenharmony_ci ); 2353af6ab5fSopenharmony_ci } 2363af6ab5fSopenharmony_ci 2373af6ab5fSopenharmony_ci static isPurePrimitiveLiteralType(type: ts.Type): boolean { 2383af6ab5fSopenharmony_ci return TsUtils.isPrimitiveLiteralType(type) && !(type.flags & ts.TypeFlags.EnumLiteral); 2393af6ab5fSopenharmony_ci } 2403af6ab5fSopenharmony_ci 2413af6ab5fSopenharmony_ci static isTypeSymbol(symbol: ts.Symbol | undefined): boolean { 2423af6ab5fSopenharmony_ci return ( 2433af6ab5fSopenharmony_ci !!symbol && 2443af6ab5fSopenharmony_ci !!symbol.flags && 2453af6ab5fSopenharmony_ci ((symbol.flags & ts.SymbolFlags.Class) !== 0 || (symbol.flags & ts.SymbolFlags.Interface) !== 0) 2463af6ab5fSopenharmony_ci ); 2473af6ab5fSopenharmony_ci } 2483af6ab5fSopenharmony_ci 2493af6ab5fSopenharmony_ci // Check whether type is generic 'Array<T>' type defined in TypeScript standard library. 2503af6ab5fSopenharmony_ci isGenericArrayType(tsType: ts.Type): tsType is ts.TypeReference { 2513af6ab5fSopenharmony_ci return ( 2523af6ab5fSopenharmony_ci !(this.arkts2 && !isStdLibraryType(tsType)) && 2533af6ab5fSopenharmony_ci TsUtils.isTypeReference(tsType) && 2543af6ab5fSopenharmony_ci tsType.typeArguments?.length === 1 && 2553af6ab5fSopenharmony_ci tsType.target.typeParameters?.length === 1 && 2563af6ab5fSopenharmony_ci tsType.getSymbol()?.getName() === 'Array' 2573af6ab5fSopenharmony_ci ); 2583af6ab5fSopenharmony_ci } 2593af6ab5fSopenharmony_ci 2603af6ab5fSopenharmony_ci isReadonlyArrayType(tsType: ts.Type): boolean { 2613af6ab5fSopenharmony_ci return ( 2623af6ab5fSopenharmony_ci !(this.arkts2 && !isStdLibraryType(tsType)) && 2633af6ab5fSopenharmony_ci TsUtils.isTypeReference(tsType) && 2643af6ab5fSopenharmony_ci tsType.typeArguments?.length === 1 && 2653af6ab5fSopenharmony_ci tsType.target.typeParameters?.length === 1 && 2663af6ab5fSopenharmony_ci tsType.getSymbol()?.getName() === 'ReadonlyArray' 2673af6ab5fSopenharmony_ci ); 2683af6ab5fSopenharmony_ci } 2693af6ab5fSopenharmony_ci 2703af6ab5fSopenharmony_ci static isConcatArrayType(tsType: ts.Type): boolean { 2713af6ab5fSopenharmony_ci return ( 2723af6ab5fSopenharmony_ci isStdLibraryType(tsType) && 2733af6ab5fSopenharmony_ci TsUtils.isTypeReference(tsType) && 2743af6ab5fSopenharmony_ci tsType.typeArguments?.length === 1 && 2753af6ab5fSopenharmony_ci tsType.target.typeParameters?.length === 1 && 2763af6ab5fSopenharmony_ci tsType.getSymbol()?.getName() === 'ConcatArray' 2773af6ab5fSopenharmony_ci ); 2783af6ab5fSopenharmony_ci } 2793af6ab5fSopenharmony_ci 2803af6ab5fSopenharmony_ci static isArrayLikeType(tsType: ts.Type): boolean { 2813af6ab5fSopenharmony_ci return ( 2823af6ab5fSopenharmony_ci isStdLibraryType(tsType) && 2833af6ab5fSopenharmony_ci TsUtils.isTypeReference(tsType) && 2843af6ab5fSopenharmony_ci tsType.typeArguments?.length === 1 && 2853af6ab5fSopenharmony_ci tsType.target.typeParameters?.length === 1 && 2863af6ab5fSopenharmony_ci tsType.getSymbol()?.getName() === 'ArrayLike' 2873af6ab5fSopenharmony_ci ); 2883af6ab5fSopenharmony_ci } 2893af6ab5fSopenharmony_ci 2903af6ab5fSopenharmony_ci isTypedArray(tsType: ts.Type): boolean { 2913af6ab5fSopenharmony_ci const symbol = tsType.symbol; 2923af6ab5fSopenharmony_ci if (!symbol) { 2933af6ab5fSopenharmony_ci return false; 2943af6ab5fSopenharmony_ci } 2953af6ab5fSopenharmony_ci const name = this.tsTypeChecker.getFullyQualifiedName(symbol); 2963af6ab5fSopenharmony_ci if (this.isGlobalSymbol(symbol) && TYPED_ARRAYS.includes(name)) { 2973af6ab5fSopenharmony_ci return true; 2983af6ab5fSopenharmony_ci } 2993af6ab5fSopenharmony_ci const decl = TsUtils.getDeclaration(symbol); 3003af6ab5fSopenharmony_ci return ( 3013af6ab5fSopenharmony_ci !!decl && TsUtils.isArkTSCollectionsClassOrInterfaceDeclaration(decl) && TYPED_ARRAYS.includes(symbol.getName()) 3023af6ab5fSopenharmony_ci ); 3033af6ab5fSopenharmony_ci } 3043af6ab5fSopenharmony_ci 3053af6ab5fSopenharmony_ci isArray(tsType: ts.Type): boolean { 3063af6ab5fSopenharmony_ci return this.isGenericArrayType(tsType) || this.isReadonlyArrayType(tsType) || this.isTypedArray(tsType); 3073af6ab5fSopenharmony_ci } 3083af6ab5fSopenharmony_ci 3093af6ab5fSopenharmony_ci isIndexableArray(tsType: ts.Type): boolean { 3103af6ab5fSopenharmony_ci return ( 3113af6ab5fSopenharmony_ci this.isGenericArrayType(tsType) || 3123af6ab5fSopenharmony_ci this.isReadonlyArrayType(tsType) || 3133af6ab5fSopenharmony_ci TsUtils.isConcatArrayType(tsType) || 3143af6ab5fSopenharmony_ci TsUtils.isArrayLikeType(tsType) || 3153af6ab5fSopenharmony_ci this.isTypedArray(tsType) 3163af6ab5fSopenharmony_ci ); 3173af6ab5fSopenharmony_ci } 3183af6ab5fSopenharmony_ci 3193af6ab5fSopenharmony_ci static isTuple(tsType: ts.Type): boolean { 3203af6ab5fSopenharmony_ci return TsUtils.isTypeReference(tsType) && !!(tsType.objectFlags & ts.ObjectFlags.Tuple); 3213af6ab5fSopenharmony_ci } 3223af6ab5fSopenharmony_ci 3233af6ab5fSopenharmony_ci // does something similar to relatedByInheritanceOrIdentical function 3243af6ab5fSopenharmony_ci isOrDerivedFrom(tsType: ts.Type, checkType: CheckType, checkedBaseTypes?: Set<ts.Type>): boolean { 3253af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 3263af6ab5fSopenharmony_ci tsType = TsUtils.reduceReference(tsType); 3273af6ab5fSopenharmony_ci 3283af6ab5fSopenharmony_ci if (checkType.call(this, tsType)) { 3293af6ab5fSopenharmony_ci return true; 3303af6ab5fSopenharmony_ci } 3313af6ab5fSopenharmony_ci 3323af6ab5fSopenharmony_ci if (!tsType.symbol?.declarations) { 3333af6ab5fSopenharmony_ci return false; 3343af6ab5fSopenharmony_ci } 3353af6ab5fSopenharmony_ci 3363af6ab5fSopenharmony_ci // Avoid type recursion in heritage by caching checked types. 3373af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 3383af6ab5fSopenharmony_ci (checkedBaseTypes ||= new Set<ts.Type>()).add(tsType); 3393af6ab5fSopenharmony_ci 3403af6ab5fSopenharmony_ci for (const tsTypeDecl of tsType.symbol.declarations) { 3413af6ab5fSopenharmony_ci const isClassOrInterfaceDecl = ts.isClassDeclaration(tsTypeDecl) || ts.isInterfaceDeclaration(tsTypeDecl); 3423af6ab5fSopenharmony_ci const isDerived = isClassOrInterfaceDecl && !!tsTypeDecl.heritageClauses; 3433af6ab5fSopenharmony_ci if (!isDerived) { 3443af6ab5fSopenharmony_ci continue; 3453af6ab5fSopenharmony_ci } 3463af6ab5fSopenharmony_ci for (const heritageClause of tsTypeDecl.heritageClauses) { 3473af6ab5fSopenharmony_ci if (this.processParentTypesCheck(heritageClause.types, checkType, checkedBaseTypes)) { 3483af6ab5fSopenharmony_ci return true; 3493af6ab5fSopenharmony_ci } 3503af6ab5fSopenharmony_ci } 3513af6ab5fSopenharmony_ci } 3523af6ab5fSopenharmony_ci 3533af6ab5fSopenharmony_ci return false; 3543af6ab5fSopenharmony_ci } 3553af6ab5fSopenharmony_ci 3563af6ab5fSopenharmony_ci static isTypeReference(tsType: ts.Type): tsType is ts.TypeReference { 3573af6ab5fSopenharmony_ci return ( 3583af6ab5fSopenharmony_ci (tsType.getFlags() & ts.TypeFlags.Object) !== 0 && 3593af6ab5fSopenharmony_ci ((tsType as ts.ObjectType).objectFlags & ts.ObjectFlags.Reference) !== 0 3603af6ab5fSopenharmony_ci ); 3613af6ab5fSopenharmony_ci } 3623af6ab5fSopenharmony_ci 3633af6ab5fSopenharmony_ci static isPrototypeSymbol(symbol: ts.Symbol | undefined): boolean { 3643af6ab5fSopenharmony_ci return !!symbol && !!symbol.flags && (symbol.flags & ts.SymbolFlags.Prototype) !== 0; 3653af6ab5fSopenharmony_ci } 3663af6ab5fSopenharmony_ci 3673af6ab5fSopenharmony_ci static isFunctionSymbol(symbol: ts.Symbol | undefined): boolean { 3683af6ab5fSopenharmony_ci return !!symbol && !!symbol.flags && (symbol.flags & ts.SymbolFlags.Function) !== 0; 3693af6ab5fSopenharmony_ci } 3703af6ab5fSopenharmony_ci 3713af6ab5fSopenharmony_ci static isInterfaceType(tsType: ts.Type | undefined): boolean { 3723af6ab5fSopenharmony_ci return ( 3733af6ab5fSopenharmony_ci !!tsType && !!tsType.symbol && !!tsType.symbol.flags && (tsType.symbol.flags & ts.SymbolFlags.Interface) !== 0 3743af6ab5fSopenharmony_ci ); 3753af6ab5fSopenharmony_ci } 3763af6ab5fSopenharmony_ci 3773af6ab5fSopenharmony_ci static isAnyType(tsType: ts.Type): tsType is ts.TypeReference { 3783af6ab5fSopenharmony_ci return (tsType.getFlags() & ts.TypeFlags.Any) !== 0; 3793af6ab5fSopenharmony_ci } 3803af6ab5fSopenharmony_ci 3813af6ab5fSopenharmony_ci static isUnknownType(tsType: ts.Type): boolean { 3823af6ab5fSopenharmony_ci return (tsType.getFlags() & ts.TypeFlags.Unknown) !== 0; 3833af6ab5fSopenharmony_ci } 3843af6ab5fSopenharmony_ci 3853af6ab5fSopenharmony_ci static isUnsupportedType(tsType: ts.Type): boolean { 3863af6ab5fSopenharmony_ci return ( 3873af6ab5fSopenharmony_ci !!tsType.flags && 3883af6ab5fSopenharmony_ci ((tsType.flags & ts.TypeFlags.Any) !== 0 || 3893af6ab5fSopenharmony_ci (tsType.flags & ts.TypeFlags.Unknown) !== 0 || 3903af6ab5fSopenharmony_ci (tsType.flags & ts.TypeFlags.Intersection) !== 0) 3913af6ab5fSopenharmony_ci ); 3923af6ab5fSopenharmony_ci } 3933af6ab5fSopenharmony_ci 3943af6ab5fSopenharmony_ci isUnsupportedTypeArkts2(tsType: ts.Type): boolean { 3953af6ab5fSopenharmony_ci const typenode = this.tsTypeChecker.typeToTypeNode(tsType, undefined, ts.NodeBuilderFlags.None); 3963af6ab5fSopenharmony_ci return !!typenode && !this.isSupportedType(typenode); 3973af6ab5fSopenharmony_ci } 3983af6ab5fSopenharmony_ci 3993af6ab5fSopenharmony_ci static isNullableUnionType(type: ts.Type): boolean { 4003af6ab5fSopenharmony_ci if (type.isUnion()) { 4013af6ab5fSopenharmony_ci for (const t of type.types) { 4023af6ab5fSopenharmony_ci if (!!(t.flags & ts.TypeFlags.Undefined) || !!(t.flags & ts.TypeFlags.Null)) { 4033af6ab5fSopenharmony_ci return true; 4043af6ab5fSopenharmony_ci } 4053af6ab5fSopenharmony_ci } 4063af6ab5fSopenharmony_ci } 4073af6ab5fSopenharmony_ci return false; 4083af6ab5fSopenharmony_ci } 4093af6ab5fSopenharmony_ci 4103af6ab5fSopenharmony_ci static isMethodAssignment(tsSymbol: ts.Symbol | undefined): boolean { 4113af6ab5fSopenharmony_ci return ( 4123af6ab5fSopenharmony_ci !!tsSymbol && (tsSymbol.flags & ts.SymbolFlags.Method) !== 0 && (tsSymbol.flags & ts.SymbolFlags.Assignment) !== 0 4133af6ab5fSopenharmony_ci ); 4143af6ab5fSopenharmony_ci } 4153af6ab5fSopenharmony_ci 4163af6ab5fSopenharmony_ci static getDeclaration(tsSymbol: ts.Symbol | undefined): ts.Declaration | undefined { 4173af6ab5fSopenharmony_ci if (tsSymbol?.declarations && tsSymbol.declarations.length > 0) { 4183af6ab5fSopenharmony_ci return tsSymbol.declarations[0]; 4193af6ab5fSopenharmony_ci } 4203af6ab5fSopenharmony_ci return undefined; 4213af6ab5fSopenharmony_ci } 4223af6ab5fSopenharmony_ci 4233af6ab5fSopenharmony_ci private static isVarDeclaration(tsDecl: ts.Node): boolean { 4243af6ab5fSopenharmony_ci return ts.isVariableDeclaration(tsDecl) && ts.isVariableDeclarationList(tsDecl.parent); 4253af6ab5fSopenharmony_ci } 4263af6ab5fSopenharmony_ci 4273af6ab5fSopenharmony_ci isValidEnumMemberInit(tsExpr: ts.Expression): boolean { 4283af6ab5fSopenharmony_ci if (this.isNumberConstantValue(tsExpr.parent as ts.EnumMember)) { 4293af6ab5fSopenharmony_ci return true; 4303af6ab5fSopenharmony_ci } 4313af6ab5fSopenharmony_ci if (this.isStringConstantValue(tsExpr.parent as ts.EnumMember)) { 4323af6ab5fSopenharmony_ci return true; 4333af6ab5fSopenharmony_ci } 4343af6ab5fSopenharmony_ci return this.isCompileTimeExpression(tsExpr); 4353af6ab5fSopenharmony_ci } 4363af6ab5fSopenharmony_ci 4373af6ab5fSopenharmony_ci private isCompileTimeExpressionHandlePropertyAccess(tsExpr: ts.Expression): boolean { 4383af6ab5fSopenharmony_ci if (!ts.isPropertyAccessExpression(tsExpr)) { 4393af6ab5fSopenharmony_ci return false; 4403af6ab5fSopenharmony_ci } 4413af6ab5fSopenharmony_ci 4423af6ab5fSopenharmony_ci /* 4433af6ab5fSopenharmony_ci * if enum member is in current enum declaration try to get value 4443af6ab5fSopenharmony_ci * if it comes from another enum consider as constant 4453af6ab5fSopenharmony_ci */ 4463af6ab5fSopenharmony_ci const propertyAccess = tsExpr; 4473af6ab5fSopenharmony_ci if (this.isNumberConstantValue(propertyAccess)) { 4483af6ab5fSopenharmony_ci return true; 4493af6ab5fSopenharmony_ci } 4503af6ab5fSopenharmony_ci const leftHandSymbol = this.trueSymbolAtLocation(propertyAccess.expression); 4513af6ab5fSopenharmony_ci if (!leftHandSymbol) { 4523af6ab5fSopenharmony_ci return false; 4533af6ab5fSopenharmony_ci } 4543af6ab5fSopenharmony_ci const decls = leftHandSymbol.getDeclarations(); 4553af6ab5fSopenharmony_ci if (!decls || decls.length !== 1) { 4563af6ab5fSopenharmony_ci return false; 4573af6ab5fSopenharmony_ci } 4583af6ab5fSopenharmony_ci return ts.isEnumDeclaration(decls[0]); 4593af6ab5fSopenharmony_ci } 4603af6ab5fSopenharmony_ci 4613af6ab5fSopenharmony_ci isCompileTimeExpression(tsExpr: ts.Expression): boolean { 4623af6ab5fSopenharmony_ci if ( 4633af6ab5fSopenharmony_ci ts.isParenthesizedExpression(tsExpr) || 4643af6ab5fSopenharmony_ci ts.isAsExpression(tsExpr) && tsExpr.type.kind === ts.SyntaxKind.NumberKeyword 4653af6ab5fSopenharmony_ci ) { 4663af6ab5fSopenharmony_ci return this.isCompileTimeExpression(tsExpr.expression); 4673af6ab5fSopenharmony_ci } 4683af6ab5fSopenharmony_ci 4693af6ab5fSopenharmony_ci switch (tsExpr.kind) { 4703af6ab5fSopenharmony_ci case ts.SyntaxKind.PrefixUnaryExpression: 4713af6ab5fSopenharmony_ci return this.isPrefixUnaryExprValidEnumMemberInit(tsExpr as ts.PrefixUnaryExpression); 4723af6ab5fSopenharmony_ci case ts.SyntaxKind.ParenthesizedExpression: 4733af6ab5fSopenharmony_ci case ts.SyntaxKind.BinaryExpression: 4743af6ab5fSopenharmony_ci return this.isBinaryExprValidEnumMemberInit(tsExpr as ts.BinaryExpression); 4753af6ab5fSopenharmony_ci case ts.SyntaxKind.ConditionalExpression: 4763af6ab5fSopenharmony_ci return this.isConditionalExprValidEnumMemberInit(tsExpr as ts.ConditionalExpression); 4773af6ab5fSopenharmony_ci case ts.SyntaxKind.Identifier: 4783af6ab5fSopenharmony_ci return this.isIdentifierValidEnumMemberInit(tsExpr as ts.Identifier); 4793af6ab5fSopenharmony_ci case ts.SyntaxKind.NumericLiteral: 4803af6ab5fSopenharmony_ci return true; 4813af6ab5fSopenharmony_ci case ts.SyntaxKind.StringLiteral: 4823af6ab5fSopenharmony_ci return true; 4833af6ab5fSopenharmony_ci case ts.SyntaxKind.PropertyAccessExpression: 4843af6ab5fSopenharmony_ci return this.isCompileTimeExpressionHandlePropertyAccess(tsExpr); 4853af6ab5fSopenharmony_ci default: 4863af6ab5fSopenharmony_ci return false; 4873af6ab5fSopenharmony_ci } 4883af6ab5fSopenharmony_ci } 4893af6ab5fSopenharmony_ci 4903af6ab5fSopenharmony_ci private isPrefixUnaryExprValidEnumMemberInit(tsExpr: ts.PrefixUnaryExpression): boolean { 4913af6ab5fSopenharmony_ci return TsUtils.isUnaryOpAllowedForEnumMemberInit(tsExpr.operator) && this.isCompileTimeExpression(tsExpr.operand); 4923af6ab5fSopenharmony_ci } 4933af6ab5fSopenharmony_ci 4943af6ab5fSopenharmony_ci private isBinaryExprValidEnumMemberInit(tsExpr: ts.BinaryExpression): boolean { 4953af6ab5fSopenharmony_ci return ( 4963af6ab5fSopenharmony_ci TsUtils.isBinaryOpAllowedForEnumMemberInit(tsExpr.operatorToken) && 4973af6ab5fSopenharmony_ci this.isCompileTimeExpression(tsExpr.left) && 4983af6ab5fSopenharmony_ci this.isCompileTimeExpression(tsExpr.right) 4993af6ab5fSopenharmony_ci ); 5003af6ab5fSopenharmony_ci } 5013af6ab5fSopenharmony_ci 5023af6ab5fSopenharmony_ci private isConditionalExprValidEnumMemberInit(tsExpr: ts.ConditionalExpression): boolean { 5033af6ab5fSopenharmony_ci return this.isCompileTimeExpression(tsExpr.whenTrue) && this.isCompileTimeExpression(tsExpr.whenFalse); 5043af6ab5fSopenharmony_ci } 5053af6ab5fSopenharmony_ci 5063af6ab5fSopenharmony_ci private isIdentifierValidEnumMemberInit(tsExpr: ts.Identifier): boolean { 5073af6ab5fSopenharmony_ci const tsSymbol = this.trueSymbolAtLocation(tsExpr); 5083af6ab5fSopenharmony_ci const tsDecl = TsUtils.getDeclaration(tsSymbol); 5093af6ab5fSopenharmony_ci return ( 5103af6ab5fSopenharmony_ci !!tsDecl && 5113af6ab5fSopenharmony_ci (TsUtils.isVarDeclaration(tsDecl) && TsUtils.isConst(tsDecl.parent) || tsDecl.kind === ts.SyntaxKind.EnumMember) 5123af6ab5fSopenharmony_ci ); 5133af6ab5fSopenharmony_ci } 5143af6ab5fSopenharmony_ci 5153af6ab5fSopenharmony_ci private static isUnaryOpAllowedForEnumMemberInit(tsPrefixUnaryOp: ts.PrefixUnaryOperator): boolean { 5163af6ab5fSopenharmony_ci return ( 5173af6ab5fSopenharmony_ci tsPrefixUnaryOp === ts.SyntaxKind.PlusToken || 5183af6ab5fSopenharmony_ci tsPrefixUnaryOp === ts.SyntaxKind.MinusToken || 5193af6ab5fSopenharmony_ci tsPrefixUnaryOp === ts.SyntaxKind.TildeToken 5203af6ab5fSopenharmony_ci ); 5213af6ab5fSopenharmony_ci } 5223af6ab5fSopenharmony_ci 5233af6ab5fSopenharmony_ci private static isBinaryOpAllowedForEnumMemberInit(tsBinaryOp: ts.BinaryOperatorToken): boolean { 5243af6ab5fSopenharmony_ci return ( 5253af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.AsteriskToken || 5263af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.SlashToken || 5273af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.PercentToken || 5283af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.MinusToken || 5293af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.PlusToken || 5303af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.LessThanLessThanToken || 5313af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.GreaterThanGreaterThanToken || 5323af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.BarBarToken || 5333af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.GreaterThanGreaterThanGreaterThanToken || 5343af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.AmpersandToken || 5353af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.CaretToken || 5363af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.BarToken || 5373af6ab5fSopenharmony_ci tsBinaryOp.kind === ts.SyntaxKind.AmpersandAmpersandToken 5383af6ab5fSopenharmony_ci ); 5393af6ab5fSopenharmony_ci } 5403af6ab5fSopenharmony_ci 5413af6ab5fSopenharmony_ci static isConst(tsNode: ts.Node): boolean { 5423af6ab5fSopenharmony_ci return !!(ts.getCombinedNodeFlags(tsNode) & ts.NodeFlags.Const); 5433af6ab5fSopenharmony_ci } 5443af6ab5fSopenharmony_ci 5453af6ab5fSopenharmony_ci isNumberConstantValue( 5463af6ab5fSopenharmony_ci tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.NumericLiteral 5473af6ab5fSopenharmony_ci ): boolean { 5483af6ab5fSopenharmony_ci const tsConstValue = 5493af6ab5fSopenharmony_ci tsExpr.kind === ts.SyntaxKind.NumericLiteral ? 5503af6ab5fSopenharmony_ci Number(tsExpr.getText()) : 5513af6ab5fSopenharmony_ci this.tsTypeChecker.getConstantValue(tsExpr); 5523af6ab5fSopenharmony_ci 5533af6ab5fSopenharmony_ci return tsConstValue !== undefined && typeof tsConstValue === 'number'; 5543af6ab5fSopenharmony_ci } 5553af6ab5fSopenharmony_ci 5563af6ab5fSopenharmony_ci isIntegerConstantValue( 5573af6ab5fSopenharmony_ci tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression | ts.NumericLiteral 5583af6ab5fSopenharmony_ci ): boolean { 5593af6ab5fSopenharmony_ci const tsConstValue = 5603af6ab5fSopenharmony_ci tsExpr.kind === ts.SyntaxKind.NumericLiteral ? 5613af6ab5fSopenharmony_ci Number(tsExpr.getText()) : 5623af6ab5fSopenharmony_ci this.tsTypeChecker.getConstantValue(tsExpr); 5633af6ab5fSopenharmony_ci return ( 5643af6ab5fSopenharmony_ci tsConstValue !== undefined && 5653af6ab5fSopenharmony_ci typeof tsConstValue === 'number' && 5663af6ab5fSopenharmony_ci tsConstValue.toFixed(0) === tsConstValue.toString() 5673af6ab5fSopenharmony_ci ); 5683af6ab5fSopenharmony_ci } 5693af6ab5fSopenharmony_ci 5703af6ab5fSopenharmony_ci isStringConstantValue(tsExpr: ts.EnumMember | ts.PropertyAccessExpression | ts.ElementAccessExpression): boolean { 5713af6ab5fSopenharmony_ci const tsConstValue = this.tsTypeChecker.getConstantValue(tsExpr); 5723af6ab5fSopenharmony_ci return tsConstValue !== undefined && typeof tsConstValue === 'string'; 5733af6ab5fSopenharmony_ci } 5743af6ab5fSopenharmony_ci 5753af6ab5fSopenharmony_ci // Returns true if typeA is a subtype of typeB 5763af6ab5fSopenharmony_ci relatedByInheritanceOrIdentical(typeA: ts.Type, typeB: ts.Type): boolean { 5773af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 5783af6ab5fSopenharmony_ci typeA = TsUtils.reduceReference(typeA); 5793af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 5803af6ab5fSopenharmony_ci typeB = TsUtils.reduceReference(typeB); 5813af6ab5fSopenharmony_ci 5823af6ab5fSopenharmony_ci if (typeA === typeB || this.isObject(typeB)) { 5833af6ab5fSopenharmony_ci return true; 5843af6ab5fSopenharmony_ci } 5853af6ab5fSopenharmony_ci if (!typeA.symbol?.declarations) { 5863af6ab5fSopenharmony_ci return false; 5873af6ab5fSopenharmony_ci } 5883af6ab5fSopenharmony_ci const isBISendable = TsUtils.isISendableInterface(typeB); 5893af6ab5fSopenharmony_ci for (const typeADecl of typeA.symbol.declarations) { 5903af6ab5fSopenharmony_ci if (isBISendable && ts.isClassDeclaration(typeADecl) && TsUtils.hasSendableDecorator(typeADecl)) { 5913af6ab5fSopenharmony_ci return true; 5923af6ab5fSopenharmony_ci } 5933af6ab5fSopenharmony_ci if (!ts.isClassDeclaration(typeADecl) && !ts.isInterfaceDeclaration(typeADecl)) { 5943af6ab5fSopenharmony_ci continue; 5953af6ab5fSopenharmony_ci } 5963af6ab5fSopenharmony_ci if (this.processExtendedParentTypes(typeA, typeB)) { 5973af6ab5fSopenharmony_ci return true; 5983af6ab5fSopenharmony_ci } 5993af6ab5fSopenharmony_ci if (!typeADecl.heritageClauses) { 6003af6ab5fSopenharmony_ci continue; 6013af6ab5fSopenharmony_ci } 6023af6ab5fSopenharmony_ci for (const heritageClause of typeADecl.heritageClauses) { 6033af6ab5fSopenharmony_ci const processInterfaces = typeA.isClass() ? heritageClause.token !== ts.SyntaxKind.ExtendsKeyword : true; 6043af6ab5fSopenharmony_ci if (this.processParentTypes(heritageClause.types, typeB, processInterfaces)) { 6053af6ab5fSopenharmony_ci return true; 6063af6ab5fSopenharmony_ci } 6073af6ab5fSopenharmony_ci } 6083af6ab5fSopenharmony_ci } 6093af6ab5fSopenharmony_ci return false; 6103af6ab5fSopenharmony_ci } 6113af6ab5fSopenharmony_ci 6123af6ab5fSopenharmony_ci static reduceReference(t: ts.Type): ts.Type { 6133af6ab5fSopenharmony_ci return TsUtils.isTypeReference(t) && t.target !== t ? t.target : t; 6143af6ab5fSopenharmony_ci } 6153af6ab5fSopenharmony_ci 6163af6ab5fSopenharmony_ci private needToDeduceStructuralIdentityHandleUnions( 6173af6ab5fSopenharmony_ci lhsType: ts.Type, 6183af6ab5fSopenharmony_ci rhsType: ts.Type, 6193af6ab5fSopenharmony_ci rhsExpr: ts.Expression, 6203af6ab5fSopenharmony_ci isStrict: boolean 6213af6ab5fSopenharmony_ci ): boolean { 6223af6ab5fSopenharmony_ci if (rhsType.isUnion()) { 6233af6ab5fSopenharmony_ci // Each Class/Interface of the RHS union type must be compatible with LHS type. 6243af6ab5fSopenharmony_ci for (const compType of rhsType.types) { 6253af6ab5fSopenharmony_ci if (this.needToDeduceStructuralIdentity(lhsType, compType, rhsExpr, isStrict)) { 6263af6ab5fSopenharmony_ci return true; 6273af6ab5fSopenharmony_ci } 6283af6ab5fSopenharmony_ci } 6293af6ab5fSopenharmony_ci return false; 6303af6ab5fSopenharmony_ci } 6313af6ab5fSopenharmony_ci if (lhsType.isUnion()) { 6323af6ab5fSopenharmony_ci // RHS type needs to be compatible with at least one type of the LHS union. 6333af6ab5fSopenharmony_ci for (const compType of lhsType.types) { 6343af6ab5fSopenharmony_ci if (!this.needToDeduceStructuralIdentity(compType, rhsType, rhsExpr, isStrict)) { 6353af6ab5fSopenharmony_ci return false; 6363af6ab5fSopenharmony_ci } 6373af6ab5fSopenharmony_ci } 6383af6ab5fSopenharmony_ci return true; 6393af6ab5fSopenharmony_ci } 6403af6ab5fSopenharmony_ci // should be unreachable 6413af6ab5fSopenharmony_ci return false; 6423af6ab5fSopenharmony_ci } 6433af6ab5fSopenharmony_ci 6443af6ab5fSopenharmony_ci // return true if two class types are not related by inheritance and structural identity check is needed 6453af6ab5fSopenharmony_ci needToDeduceStructuralIdentity( 6463af6ab5fSopenharmony_ci lhsType: ts.Type, 6473af6ab5fSopenharmony_ci rhsType: ts.Type, 6483af6ab5fSopenharmony_ci rhsExpr: ts.Expression, 6493af6ab5fSopenharmony_ci isStrict: boolean = false 6503af6ab5fSopenharmony_ci ): boolean { 6513af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 6523af6ab5fSopenharmony_ci lhsType = this.getNonNullableType(lhsType); 6533af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 6543af6ab5fSopenharmony_ci rhsType = this.getNonNullableType(rhsType); 6553af6ab5fSopenharmony_ci if (this.isLibraryType(lhsType)) { 6563af6ab5fSopenharmony_ci return false; 6573af6ab5fSopenharmony_ci } 6583af6ab5fSopenharmony_ci if (this.isDynamicObjectAssignedToStdType(lhsType, rhsExpr)) { 6593af6ab5fSopenharmony_ci return false; 6603af6ab5fSopenharmony_ci } 6613af6ab5fSopenharmony_ci // #14569: Check for Function type. 6623af6ab5fSopenharmony_ci if (this.areCompatibleFunctionals(lhsType, rhsType)) { 6633af6ab5fSopenharmony_ci return false; 6643af6ab5fSopenharmony_ci } 6653af6ab5fSopenharmony_ci if (rhsType.isUnion() || lhsType.isUnion()) { 6663af6ab5fSopenharmony_ci return this.needToDeduceStructuralIdentityHandleUnions(lhsType, rhsType, rhsExpr, isStrict); 6673af6ab5fSopenharmony_ci } 6683af6ab5fSopenharmony_ci if ( 6693af6ab5fSopenharmony_ci this.advancedClassChecks && 6703af6ab5fSopenharmony_ci TsUtils.isClassValueType(rhsType) && 6713af6ab5fSopenharmony_ci lhsType !== rhsType && 6723af6ab5fSopenharmony_ci !TsUtils.isObjectType(lhsType) 6733af6ab5fSopenharmony_ci ) { 6743af6ab5fSopenharmony_ci // missing exact rule 6753af6ab5fSopenharmony_ci return true; 6763af6ab5fSopenharmony_ci } 6773af6ab5fSopenharmony_ci // if isStrict, things like generics need to be checked 6783af6ab5fSopenharmony_ci if (isStrict) { 6793af6ab5fSopenharmony_ci if (TsUtils.isTypeReference(rhsType) && !!(rhsType.objectFlags & ts.ObjectFlags.ArrayLiteral)) { 6803af6ab5fSopenharmony_ci // The 'arkts-sendable-obj-init' rule already exists. Wait for the new 'strict type' to be modified. 6813af6ab5fSopenharmony_ci return false; 6823af6ab5fSopenharmony_ci } 6833af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 6843af6ab5fSopenharmony_ci lhsType = TsUtils.reduceReference(lhsType); 6853af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 6863af6ab5fSopenharmony_ci rhsType = TsUtils.reduceReference(rhsType); 6873af6ab5fSopenharmony_ci } 6883af6ab5fSopenharmony_ci return ( 6893af6ab5fSopenharmony_ci lhsType.isClassOrInterface() && 6903af6ab5fSopenharmony_ci rhsType.isClassOrInterface() && 6913af6ab5fSopenharmony_ci !this.relatedByInheritanceOrIdentical(rhsType, lhsType) 6923af6ab5fSopenharmony_ci ); 6933af6ab5fSopenharmony_ci } 6943af6ab5fSopenharmony_ci 6953af6ab5fSopenharmony_ci // Does the 'arkts-no-structural-typing' rule need to be strictly enforced to complete previously missed scenarios 6963af6ab5fSopenharmony_ci needStrictMatchType(lhsType: ts.Type, rhsType: ts.Type): boolean { 6973af6ab5fSopenharmony_ci if (this.arkts2) { 6983af6ab5fSopenharmony_ci return true; 6993af6ab5fSopenharmony_ci } 7003af6ab5fSopenharmony_ci if (this.isStrictSendableMatch(lhsType, rhsType)) { 7013af6ab5fSopenharmony_ci return true; 7023af6ab5fSopenharmony_ci } 7033af6ab5fSopenharmony_ci // add other requirements with strict type requirements here 7043af6ab5fSopenharmony_ci return false; 7053af6ab5fSopenharmony_ci } 7063af6ab5fSopenharmony_ci 7073af6ab5fSopenharmony_ci // For compatibility, left must all ClassOrInterface is sendable, right must has non-sendable ClassorInterface 7083af6ab5fSopenharmony_ci private isStrictSendableMatch(lhsType: ts.Type, rhsType: ts.Type): boolean { 7093af6ab5fSopenharmony_ci let isStrictLhs = false; 7103af6ab5fSopenharmony_ci if (lhsType.isUnion()) { 7113af6ab5fSopenharmony_ci for (let compType of lhsType.types) { 7123af6ab5fSopenharmony_ci compType = TsUtils.reduceReference(compType); 7133af6ab5fSopenharmony_ci if (!compType.isClassOrInterface()) { 7143af6ab5fSopenharmony_ci continue; 7153af6ab5fSopenharmony_ci } 7163af6ab5fSopenharmony_ci if (!this.isSendableClassOrInterface(compType)) { 7173af6ab5fSopenharmony_ci return false; 7183af6ab5fSopenharmony_ci } 7193af6ab5fSopenharmony_ci isStrictLhs = true; 7203af6ab5fSopenharmony_ci } 7213af6ab5fSopenharmony_ci } else { 7223af6ab5fSopenharmony_ci isStrictLhs = this.isSendableClassOrInterface(lhsType); 7233af6ab5fSopenharmony_ci } 7243af6ab5fSopenharmony_ci return isStrictLhs && this.typeContainsNonSendableClassOrInterface(rhsType); 7253af6ab5fSopenharmony_ci } 7263af6ab5fSopenharmony_ci 7273af6ab5fSopenharmony_ci private processExtendedParentTypes(typeA: ts.Type, typeB: ts.Type): boolean { 7283af6ab5fSopenharmony_ci 7293af6ab5fSopenharmony_ci /* 7303af6ab5fSopenharmony_ci * Most standard types in TS Stdlib do not use explicit inheritance and rely on 7313af6ab5fSopenharmony_ci * structural compatibility. In contrast, the type definitions in ArkTS stdlib 7323af6ab5fSopenharmony_ci * use inheritance with explicit base types. We check the inheritance hierarchy 7333af6ab5fSopenharmony_ci * for such types according to how they are defined in ArkTS Stdlib. 7343af6ab5fSopenharmony_ci */ 7353af6ab5fSopenharmony_ci 7363af6ab5fSopenharmony_ci if (!this.arkts2) { 7373af6ab5fSopenharmony_ci return false; 7383af6ab5fSopenharmony_ci } 7393af6ab5fSopenharmony_ci if (!isStdLibrarySymbol(typeA.symbol) && !isStdLibrarySymbol(typeB.symbol)) { 7403af6ab5fSopenharmony_ci return false; 7413af6ab5fSopenharmony_ci } 7423af6ab5fSopenharmony_ci return this.checkExtendedParentTypes(typeA.symbol.name, typeB.symbol.name); 7433af6ab5fSopenharmony_ci } 7443af6ab5fSopenharmony_ci 7453af6ab5fSopenharmony_ci private checkExtendedParentTypes(typeA: string, typeB: string): boolean { 7463af6ab5fSopenharmony_ci if (typeA === typeB) { 7473af6ab5fSopenharmony_ci return true; 7483af6ab5fSopenharmony_ci } 7493af6ab5fSopenharmony_ci const extBaseTypes = EXTENDED_BASE_TYPES.get(typeA); 7503af6ab5fSopenharmony_ci if (!extBaseTypes) { 7513af6ab5fSopenharmony_ci return false; 7523af6ab5fSopenharmony_ci } 7533af6ab5fSopenharmony_ci for (const extBaseType of extBaseTypes) { 7543af6ab5fSopenharmony_ci if (this.checkExtendedParentTypes(extBaseType, typeB)) { 7553af6ab5fSopenharmony_ci return true; 7563af6ab5fSopenharmony_ci } 7573af6ab5fSopenharmony_ci } 7583af6ab5fSopenharmony_ci return false; 7593af6ab5fSopenharmony_ci } 7603af6ab5fSopenharmony_ci 7613af6ab5fSopenharmony_ci private processParentTypes( 7623af6ab5fSopenharmony_ci parentTypes: ts.NodeArray<ts.Expression>, 7633af6ab5fSopenharmony_ci typeB: ts.Type, 7643af6ab5fSopenharmony_ci processInterfaces: boolean 7653af6ab5fSopenharmony_ci ): boolean { 7663af6ab5fSopenharmony_ci for (const baseTypeExpr of parentTypes) { 7673af6ab5fSopenharmony_ci const baseType = TsUtils.reduceReference(this.tsTypeChecker.getTypeAtLocation(baseTypeExpr)); 7683af6ab5fSopenharmony_ci if ( 7693af6ab5fSopenharmony_ci baseType && 7703af6ab5fSopenharmony_ci baseType.isClass() !== processInterfaces && 7713af6ab5fSopenharmony_ci this.relatedByInheritanceOrIdentical(baseType, typeB) 7723af6ab5fSopenharmony_ci ) { 7733af6ab5fSopenharmony_ci return true; 7743af6ab5fSopenharmony_ci } 7753af6ab5fSopenharmony_ci } 7763af6ab5fSopenharmony_ci return false; 7773af6ab5fSopenharmony_ci } 7783af6ab5fSopenharmony_ci 7793af6ab5fSopenharmony_ci private processParentTypesCheck( 7803af6ab5fSopenharmony_ci parentTypes: ts.NodeArray<ts.Expression>, 7813af6ab5fSopenharmony_ci checkType: CheckType, 7823af6ab5fSopenharmony_ci checkedBaseTypes: Set<ts.Type> 7833af6ab5fSopenharmony_ci ): boolean { 7843af6ab5fSopenharmony_ci for (const baseTypeExpr of parentTypes) { 7853af6ab5fSopenharmony_ci const baseType = TsUtils.reduceReference(this.tsTypeChecker.getTypeAtLocation(baseTypeExpr)); 7863af6ab5fSopenharmony_ci if (baseType && !checkedBaseTypes.has(baseType) && this.isOrDerivedFrom(baseType, checkType, checkedBaseTypes)) { 7873af6ab5fSopenharmony_ci return true; 7883af6ab5fSopenharmony_ci } 7893af6ab5fSopenharmony_ci } 7903af6ab5fSopenharmony_ci return false; 7913af6ab5fSopenharmony_ci } 7923af6ab5fSopenharmony_ci 7933af6ab5fSopenharmony_ci isObject(tsType: ts.Type): boolean { 7943af6ab5fSopenharmony_ci if (!tsType) { 7953af6ab5fSopenharmony_ci return false; 7963af6ab5fSopenharmony_ci } 7973af6ab5fSopenharmony_ci if (tsType.symbol && tsType.isClassOrInterface() && tsType.symbol.name === 'Object') { 7983af6ab5fSopenharmony_ci return true; 7993af6ab5fSopenharmony_ci } 8003af6ab5fSopenharmony_ci const node = this.tsTypeChecker.typeToTypeNode(tsType, undefined, undefined); 8013af6ab5fSopenharmony_ci return node !== undefined && node.kind === ts.SyntaxKind.ObjectKeyword; 8023af6ab5fSopenharmony_ci } 8033af6ab5fSopenharmony_ci 8043af6ab5fSopenharmony_ci isCallToFunctionWithOmittedReturnType(tsExpr: ts.Expression): boolean { 8053af6ab5fSopenharmony_ci if (ts.isCallExpression(tsExpr)) { 8063af6ab5fSopenharmony_ci const tsCallSignature = this.tsTypeChecker.getResolvedSignature(tsExpr); 8073af6ab5fSopenharmony_ci if (tsCallSignature) { 8083af6ab5fSopenharmony_ci const tsSignDecl = tsCallSignature.getDeclaration(); 8093af6ab5fSopenharmony_ci // `tsSignDecl` is undefined when `getResolvedSignature` returns `unknownSignature` 8103af6ab5fSopenharmony_ci if (!tsSignDecl?.type) { 8113af6ab5fSopenharmony_ci return true; 8123af6ab5fSopenharmony_ci } 8133af6ab5fSopenharmony_ci } 8143af6ab5fSopenharmony_ci } 8153af6ab5fSopenharmony_ci 8163af6ab5fSopenharmony_ci return false; 8173af6ab5fSopenharmony_ci } 8183af6ab5fSopenharmony_ci 8193af6ab5fSopenharmony_ci private static hasReadonlyFields(type: ts.Type): boolean { 8203af6ab5fSopenharmony_ci // No members -> no readonly fields 8213af6ab5fSopenharmony_ci if (type.symbol.members === undefined) { 8223af6ab5fSopenharmony_ci return false; 8233af6ab5fSopenharmony_ci } 8243af6ab5fSopenharmony_ci 8253af6ab5fSopenharmony_ci let result: boolean = false; 8263af6ab5fSopenharmony_ci 8273af6ab5fSopenharmony_ci type.symbol.members.forEach((value) => { 8283af6ab5fSopenharmony_ci if ( 8293af6ab5fSopenharmony_ci value.declarations !== undefined && 8303af6ab5fSopenharmony_ci value.declarations.length > 0 && 8313af6ab5fSopenharmony_ci ts.isPropertyDeclaration(value.declarations[0]) 8323af6ab5fSopenharmony_ci ) { 8333af6ab5fSopenharmony_ci const propmMods = ts.getModifiers(value.declarations[0]); 8343af6ab5fSopenharmony_ci if (TsUtils.hasModifier(propmMods, ts.SyntaxKind.ReadonlyKeyword)) { 8353af6ab5fSopenharmony_ci result = true; 8363af6ab5fSopenharmony_ci } 8373af6ab5fSopenharmony_ci } 8383af6ab5fSopenharmony_ci }); 8393af6ab5fSopenharmony_ci 8403af6ab5fSopenharmony_ci return result; 8413af6ab5fSopenharmony_ci } 8423af6ab5fSopenharmony_ci 8433af6ab5fSopenharmony_ci private static hasDefaultCtor(type: ts.Type): boolean { 8443af6ab5fSopenharmony_ci // No members -> no explicit constructors -> there is default ctor 8453af6ab5fSopenharmony_ci if (type.symbol.members === undefined) { 8463af6ab5fSopenharmony_ci return true; 8473af6ab5fSopenharmony_ci } 8483af6ab5fSopenharmony_ci 8493af6ab5fSopenharmony_ci // has any constructor 8503af6ab5fSopenharmony_ci let hasCtor: boolean = false; 8513af6ab5fSopenharmony_ci // has default constructor 8523af6ab5fSopenharmony_ci let hasDefaultCtor: boolean = false; 8533af6ab5fSopenharmony_ci 8543af6ab5fSopenharmony_ci type.symbol.members.forEach((value) => { 8553af6ab5fSopenharmony_ci if ((value.flags & ts.SymbolFlags.Constructor) === 0) { 8563af6ab5fSopenharmony_ci return; 8573af6ab5fSopenharmony_ci } 8583af6ab5fSopenharmony_ci hasCtor = true; 8593af6ab5fSopenharmony_ci 8603af6ab5fSopenharmony_ci if (value.declarations === undefined || value.declarations.length <= 0) { 8613af6ab5fSopenharmony_ci return; 8623af6ab5fSopenharmony_ci } 8633af6ab5fSopenharmony_ci 8643af6ab5fSopenharmony_ci const declCtor = value.declarations[0] as ts.ConstructorDeclaration; 8653af6ab5fSopenharmony_ci if (declCtor.parameters.length === 0) { 8663af6ab5fSopenharmony_ci hasDefaultCtor = true; 8673af6ab5fSopenharmony_ci } 8683af6ab5fSopenharmony_ci }); 8693af6ab5fSopenharmony_ci 8703af6ab5fSopenharmony_ci // Has no any explicit constructor -> has implicit default constructor. 8713af6ab5fSopenharmony_ci return !hasCtor || hasDefaultCtor; 8723af6ab5fSopenharmony_ci } 8733af6ab5fSopenharmony_ci 8743af6ab5fSopenharmony_ci private static isAbstractClass(type: ts.Type): boolean { 8753af6ab5fSopenharmony_ci if (type.isClass() && type.symbol.declarations && type.symbol.declarations.length > 0) { 8763af6ab5fSopenharmony_ci const declClass = type.symbol.declarations[0] as ts.ClassDeclaration; 8773af6ab5fSopenharmony_ci const classMods = ts.getModifiers(declClass); 8783af6ab5fSopenharmony_ci if (TsUtils.hasModifier(classMods, ts.SyntaxKind.AbstractKeyword)) { 8793af6ab5fSopenharmony_ci return true; 8803af6ab5fSopenharmony_ci } 8813af6ab5fSopenharmony_ci } 8823af6ab5fSopenharmony_ci 8833af6ab5fSopenharmony_ci return false; 8843af6ab5fSopenharmony_ci } 8853af6ab5fSopenharmony_ci 8863af6ab5fSopenharmony_ci static validateObjectLiteralType(type: ts.Type | undefined): boolean { 8873af6ab5fSopenharmony_ci if (!type) { 8883af6ab5fSopenharmony_ci return false; 8893af6ab5fSopenharmony_ci } 8903af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 8913af6ab5fSopenharmony_ci type = TsUtils.reduceReference(type); 8923af6ab5fSopenharmony_ci return ( 8933af6ab5fSopenharmony_ci type.isClassOrInterface() && 8943af6ab5fSopenharmony_ci TsUtils.hasDefaultCtor(type) && 8953af6ab5fSopenharmony_ci !TsUtils.hasReadonlyFields(type) && 8963af6ab5fSopenharmony_ci !TsUtils.isAbstractClass(type) 8973af6ab5fSopenharmony_ci ); 8983af6ab5fSopenharmony_ci } 8993af6ab5fSopenharmony_ci 9003af6ab5fSopenharmony_ci hasMethods(type: ts.Type): boolean { 9013af6ab5fSopenharmony_ci const properties = this.tsTypeChecker.getPropertiesOfType(type); 9023af6ab5fSopenharmony_ci if (properties?.length) { 9033af6ab5fSopenharmony_ci for (const prop of properties) { 9043af6ab5fSopenharmony_ci if (prop.getFlags() & ts.SymbolFlags.Method) { 9053af6ab5fSopenharmony_ci return true; 9063af6ab5fSopenharmony_ci } 9073af6ab5fSopenharmony_ci } 9083af6ab5fSopenharmony_ci } 9093af6ab5fSopenharmony_ci return false; 9103af6ab5fSopenharmony_ci } 9113af6ab5fSopenharmony_ci 9123af6ab5fSopenharmony_ci findProperty(type: ts.Type, name: string): ts.Symbol | undefined { 9133af6ab5fSopenharmony_ci const properties = this.tsTypeChecker.getPropertiesOfType(type); 9143af6ab5fSopenharmony_ci if (properties?.length) { 9153af6ab5fSopenharmony_ci for (const prop of properties) { 9163af6ab5fSopenharmony_ci if (prop.name === name) { 9173af6ab5fSopenharmony_ci return prop; 9183af6ab5fSopenharmony_ci } 9193af6ab5fSopenharmony_ci } 9203af6ab5fSopenharmony_ci } 9213af6ab5fSopenharmony_ci 9223af6ab5fSopenharmony_ci return undefined; 9233af6ab5fSopenharmony_ci } 9243af6ab5fSopenharmony_ci 9253af6ab5fSopenharmony_ci checkTypeSet(typeSet: ts.Type, predicate: CheckType): boolean { 9263af6ab5fSopenharmony_ci if (!typeSet.isUnionOrIntersection()) { 9273af6ab5fSopenharmony_ci return predicate.call(this, typeSet); 9283af6ab5fSopenharmony_ci } 9293af6ab5fSopenharmony_ci for (const elemType of typeSet.types) { 9303af6ab5fSopenharmony_ci if (this.checkTypeSet(elemType, predicate)) { 9313af6ab5fSopenharmony_ci return true; 9323af6ab5fSopenharmony_ci } 9333af6ab5fSopenharmony_ci } 9343af6ab5fSopenharmony_ci return false; 9353af6ab5fSopenharmony_ci } 9363af6ab5fSopenharmony_ci 9373af6ab5fSopenharmony_ci getNonNullableType(t: ts.Type): ts.Type { 9383af6ab5fSopenharmony_ci const isNullableUnionType = this.useSdkLogic ? t.isUnion() : TsUtils.isNullableUnionType(t); 9393af6ab5fSopenharmony_ci if (isNullableUnionType) { 9403af6ab5fSopenharmony_ci return t.getNonNullableType(); 9413af6ab5fSopenharmony_ci } 9423af6ab5fSopenharmony_ci return t; 9433af6ab5fSopenharmony_ci } 9443af6ab5fSopenharmony_ci 9453af6ab5fSopenharmony_ci private isObjectLiteralAssignableToUnion(lhsType: ts.UnionType, rhsExpr: ts.ObjectLiteralExpression): boolean { 9463af6ab5fSopenharmony_ci for (const compType of lhsType.types) { 9473af6ab5fSopenharmony_ci if (this.isObjectLiteralAssignable(compType, rhsExpr)) { 9483af6ab5fSopenharmony_ci return true; 9493af6ab5fSopenharmony_ci } 9503af6ab5fSopenharmony_ci } 9513af6ab5fSopenharmony_ci return false; 9523af6ab5fSopenharmony_ci } 9533af6ab5fSopenharmony_ci 9543af6ab5fSopenharmony_ci isObjectLiteralAssignable(lhsType: ts.Type | undefined, rhsExpr: ts.ObjectLiteralExpression): boolean { 9553af6ab5fSopenharmony_ci if (lhsType === undefined) { 9563af6ab5fSopenharmony_ci return false; 9573af6ab5fSopenharmony_ci } 9583af6ab5fSopenharmony_ci // Always check with the non-nullable variant of lhs type. 9593af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 9603af6ab5fSopenharmony_ci lhsType = this.getNonNullableType(lhsType); 9613af6ab5fSopenharmony_ci if (lhsType.isUnion() && this.isObjectLiteralAssignableToUnion(lhsType, rhsExpr)) { 9623af6ab5fSopenharmony_ci return true; 9633af6ab5fSopenharmony_ci } 9643af6ab5fSopenharmony_ci 9653af6ab5fSopenharmony_ci /* 9663af6ab5fSopenharmony_ci * Allow initializing with anything when the type 9673af6ab5fSopenharmony_ci * originates from the library. 9683af6ab5fSopenharmony_ci */ 9693af6ab5fSopenharmony_ci if (TsUtils.isAnyType(lhsType) || this.isLibraryType(lhsType)) { 9703af6ab5fSopenharmony_ci return true; 9713af6ab5fSopenharmony_ci } 9723af6ab5fSopenharmony_ci 9733af6ab5fSopenharmony_ci /* 9743af6ab5fSopenharmony_ci * issue 13412: 9753af6ab5fSopenharmony_ci * Allow initializing with a dynamic object when the LHS type 9763af6ab5fSopenharmony_ci * is primitive or defined in standard library. 9773af6ab5fSopenharmony_ci */ 9783af6ab5fSopenharmony_ci if (this.isDynamicObjectAssignedToStdType(lhsType, rhsExpr)) { 9793af6ab5fSopenharmony_ci return true; 9803af6ab5fSopenharmony_ci } 9813af6ab5fSopenharmony_ci // For Partial<T>, Required<T>, Readonly<T> types, validate their argument type. 9823af6ab5fSopenharmony_ci if (this.isStdPartialType(lhsType) || this.isStdRequiredType(lhsType) || this.isStdReadonlyType(lhsType)) { 9833af6ab5fSopenharmony_ci if (lhsType.aliasTypeArguments && lhsType.aliasTypeArguments.length === 1) { 9843af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 9853af6ab5fSopenharmony_ci lhsType = lhsType.aliasTypeArguments[0]; 9863af6ab5fSopenharmony_ci } else { 9873af6ab5fSopenharmony_ci return false; 9883af6ab5fSopenharmony_ci } 9893af6ab5fSopenharmony_ci } 9903af6ab5fSopenharmony_ci 9913af6ab5fSopenharmony_ci /* 9923af6ab5fSopenharmony_ci * Allow initializing Record objects with object initializer. 9933af6ab5fSopenharmony_ci * Record supports any type for a its value, but the key value 9943af6ab5fSopenharmony_ci * must be either a string or number literal. 9953af6ab5fSopenharmony_ci */ 9963af6ab5fSopenharmony_ci if (this.isStdRecordType(lhsType)) { 9973af6ab5fSopenharmony_ci return this.validateRecordObjectKeys(rhsExpr); 9983af6ab5fSopenharmony_ci } 9993af6ab5fSopenharmony_ci return ( 10003af6ab5fSopenharmony_ci TsUtils.validateObjectLiteralType(lhsType) && !this.hasMethods(lhsType) && this.validateFields(lhsType, rhsExpr) 10013af6ab5fSopenharmony_ci ); 10023af6ab5fSopenharmony_ci } 10033af6ab5fSopenharmony_ci 10043af6ab5fSopenharmony_ci private isDynamicObjectAssignedToStdType(lhsType: ts.Type, rhsExpr: ts.Expression): boolean { 10053af6ab5fSopenharmony_ci if (isStdLibraryType(lhsType) || TsUtils.isPrimitiveType(lhsType)) { 10063af6ab5fSopenharmony_ci // eslint-disable-next-line no-nested-ternary 10073af6ab5fSopenharmony_ci const rhsSym = ts.isCallExpression(rhsExpr) ? 10083af6ab5fSopenharmony_ci this.getSymbolOfCallExpression(rhsExpr) : 10093af6ab5fSopenharmony_ci this.useSdkLogic ? 10103af6ab5fSopenharmony_ci this.tsTypeChecker.getSymbolAtLocation(rhsExpr) : 10113af6ab5fSopenharmony_ci this.trueSymbolAtLocation(rhsExpr); 10123af6ab5fSopenharmony_ci if (rhsSym && this.isLibrarySymbol(rhsSym)) { 10133af6ab5fSopenharmony_ci return true; 10143af6ab5fSopenharmony_ci } 10153af6ab5fSopenharmony_ci } 10163af6ab5fSopenharmony_ci return false; 10173af6ab5fSopenharmony_ci } 10183af6ab5fSopenharmony_ci 10193af6ab5fSopenharmony_ci validateFields(objectType: ts.Type, objectLiteral: ts.ObjectLiteralExpression): boolean { 10203af6ab5fSopenharmony_ci for (const prop of objectLiteral.properties) { 10213af6ab5fSopenharmony_ci if (ts.isPropertyAssignment(prop)) { 10223af6ab5fSopenharmony_ci if (!this.validateField(objectType, prop)) { 10233af6ab5fSopenharmony_ci return false; 10243af6ab5fSopenharmony_ci } 10253af6ab5fSopenharmony_ci } 10263af6ab5fSopenharmony_ci } 10273af6ab5fSopenharmony_ci 10283af6ab5fSopenharmony_ci return true; 10293af6ab5fSopenharmony_ci } 10303af6ab5fSopenharmony_ci 10313af6ab5fSopenharmony_ci getPropertySymbol(type: ts.Type, prop: ts.PropertyAssignment): ts.Symbol | undefined { 10323af6ab5fSopenharmony_ci const propNameSymbol = this.tsTypeChecker.getSymbolAtLocation(prop.name); 10333af6ab5fSopenharmony_ci // eslint-disable-next-line no-nested-ternary 10343af6ab5fSopenharmony_ci const propName = propNameSymbol ? 10353af6ab5fSopenharmony_ci ts.symbolName(propNameSymbol) : 10363af6ab5fSopenharmony_ci ts.isMemberName(prop.name) ? 10373af6ab5fSopenharmony_ci ts.idText(prop.name) : 10383af6ab5fSopenharmony_ci prop.name.getText(); 10393af6ab5fSopenharmony_ci const propSym = this.findProperty(type, propName); 10403af6ab5fSopenharmony_ci return propSym; 10413af6ab5fSopenharmony_ci } 10423af6ab5fSopenharmony_ci 10433af6ab5fSopenharmony_ci private validateField(type: ts.Type, prop: ts.PropertyAssignment): boolean { 10443af6ab5fSopenharmony_ci // Issue 15497: Use unescaped property name to find correpsponding property. 10453af6ab5fSopenharmony_ci const propSym = this.getPropertySymbol(type, prop); 10463af6ab5fSopenharmony_ci if (!propSym?.declarations?.length) { 10473af6ab5fSopenharmony_ci return false; 10483af6ab5fSopenharmony_ci } 10493af6ab5fSopenharmony_ci 10503af6ab5fSopenharmony_ci const propType = this.tsTypeChecker.getTypeOfSymbolAtLocation(propSym, propSym.declarations[0]); 10513af6ab5fSopenharmony_ci const initExpr = TsUtils.unwrapParenthesized(prop.initializer); 10523af6ab5fSopenharmony_ci const rhsType = this.tsTypeChecker.getTypeAtLocation(initExpr); 10533af6ab5fSopenharmony_ci if (ts.isObjectLiteralExpression(initExpr)) { 10543af6ab5fSopenharmony_ci if (!this.isObjectLiteralAssignable(propType, initExpr)) { 10553af6ab5fSopenharmony_ci return false; 10563af6ab5fSopenharmony_ci } 10573af6ab5fSopenharmony_ci } else { 10583af6ab5fSopenharmony_ci // Only check for structural sub-typing. 10593af6ab5fSopenharmony_ci if ( 10603af6ab5fSopenharmony_ci this.needToDeduceStructuralIdentity(propType, rhsType, initExpr, this.needStrictMatchType(propType, rhsType)) 10613af6ab5fSopenharmony_ci ) { 10623af6ab5fSopenharmony_ci return false; 10633af6ab5fSopenharmony_ci } 10643af6ab5fSopenharmony_ci if (this.isWrongSendableFunctionAssignment(propType, rhsType)) { 10653af6ab5fSopenharmony_ci return false; 10663af6ab5fSopenharmony_ci } 10673af6ab5fSopenharmony_ci } 10683af6ab5fSopenharmony_ci 10693af6ab5fSopenharmony_ci return true; 10703af6ab5fSopenharmony_ci } 10713af6ab5fSopenharmony_ci 10723af6ab5fSopenharmony_ci validateRecordObjectKeys(objectLiteral: ts.ObjectLiteralExpression): boolean { 10733af6ab5fSopenharmony_ci for (const prop of objectLiteral.properties) { 10743af6ab5fSopenharmony_ci if (!prop.name || !this.isValidRecordObjectLiteralKey(prop.name)) { 10753af6ab5fSopenharmony_ci return false; 10763af6ab5fSopenharmony_ci } 10773af6ab5fSopenharmony_ci } 10783af6ab5fSopenharmony_ci return true; 10793af6ab5fSopenharmony_ci } 10803af6ab5fSopenharmony_ci 10813af6ab5fSopenharmony_ci isValidRecordObjectLiteralKey(propName: ts.PropertyName): boolean { 10823af6ab5fSopenharmony_ci if (ts.isComputedPropertyName(propName)) { 10833af6ab5fSopenharmony_ci return this.isValidComputedPropertyName(propName, true); 10843af6ab5fSopenharmony_ci } 10853af6ab5fSopenharmony_ci return ts.isStringLiteral(propName) || ts.isNumericLiteral(propName); 10863af6ab5fSopenharmony_ci } 10873af6ab5fSopenharmony_ci 10883af6ab5fSopenharmony_ci private static isSupportedTypeNodeKind(kind: ts.SyntaxKind): boolean { 10893af6ab5fSopenharmony_ci return ( 10903af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.AnyKeyword && 10913af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.UnknownKeyword && 10923af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.SymbolKeyword && 10933af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.IndexedAccessType && 10943af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.ConditionalType && 10953af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.MappedType && 10963af6ab5fSopenharmony_ci kind !== ts.SyntaxKind.InferType 10973af6ab5fSopenharmony_ci ); 10983af6ab5fSopenharmony_ci } 10993af6ab5fSopenharmony_ci 11003af6ab5fSopenharmony_ci private isSupportedTypeHandleUnionTypeNode(typeNode: ts.UnionTypeNode): boolean { 11013af6ab5fSopenharmony_ci for (const unionTypeElem of typeNode.types) { 11023af6ab5fSopenharmony_ci if (!this.isSupportedType(unionTypeElem)) { 11033af6ab5fSopenharmony_ci return false; 11043af6ab5fSopenharmony_ci } 11053af6ab5fSopenharmony_ci } 11063af6ab5fSopenharmony_ci return true; 11073af6ab5fSopenharmony_ci } 11083af6ab5fSopenharmony_ci 11093af6ab5fSopenharmony_ci private isSupportedTypeHandleTupleTypeNode(typeNode: ts.TupleTypeNode): boolean { 11103af6ab5fSopenharmony_ci for (const elem of typeNode.elements) { 11113af6ab5fSopenharmony_ci if (ts.isTypeNode(elem) && !this.isSupportedType(elem)) { 11123af6ab5fSopenharmony_ci return false; 11133af6ab5fSopenharmony_ci } 11143af6ab5fSopenharmony_ci if (ts.isNamedTupleMember(elem) && !this.isSupportedType(elem.type)) { 11153af6ab5fSopenharmony_ci return false; 11163af6ab5fSopenharmony_ci } 11173af6ab5fSopenharmony_ci } 11183af6ab5fSopenharmony_ci return true; 11193af6ab5fSopenharmony_ci } 11203af6ab5fSopenharmony_ci 11213af6ab5fSopenharmony_ci isSupportedType(typeNode: ts.TypeNode): boolean { 11223af6ab5fSopenharmony_ci if (ts.isParenthesizedTypeNode(typeNode)) { 11233af6ab5fSopenharmony_ci return this.isSupportedType(typeNode.type); 11243af6ab5fSopenharmony_ci } 11253af6ab5fSopenharmony_ci 11263af6ab5fSopenharmony_ci if (ts.isArrayTypeNode(typeNode)) { 11273af6ab5fSopenharmony_ci return this.isSupportedType(typeNode.elementType); 11283af6ab5fSopenharmony_ci } 11293af6ab5fSopenharmony_ci 11303af6ab5fSopenharmony_ci if (ts.isTypeReferenceNode(typeNode) && typeNode.typeArguments) { 11313af6ab5fSopenharmony_ci for (const typeArg of typeNode.typeArguments) { 11323af6ab5fSopenharmony_ci if (!this.isSupportedType(typeArg)) { 11333af6ab5fSopenharmony_ci return false; 11343af6ab5fSopenharmony_ci } 11353af6ab5fSopenharmony_ci } 11363af6ab5fSopenharmony_ci return true; 11373af6ab5fSopenharmony_ci } 11383af6ab5fSopenharmony_ci 11393af6ab5fSopenharmony_ci if (ts.isUnionTypeNode(typeNode)) { 11403af6ab5fSopenharmony_ci return this.isSupportedTypeHandleUnionTypeNode(typeNode); 11413af6ab5fSopenharmony_ci } 11423af6ab5fSopenharmony_ci 11433af6ab5fSopenharmony_ci if (ts.isTupleTypeNode(typeNode)) { 11443af6ab5fSopenharmony_ci return this.isSupportedTypeHandleTupleTypeNode(typeNode); 11453af6ab5fSopenharmony_ci } 11463af6ab5fSopenharmony_ci 11473af6ab5fSopenharmony_ci return ( 11483af6ab5fSopenharmony_ci !ts.isTypeLiteralNode(typeNode) && 11493af6ab5fSopenharmony_ci (this.advancedClassChecks || !ts.isTypeQueryNode(typeNode)) && 11503af6ab5fSopenharmony_ci !ts.isIntersectionTypeNode(typeNode) && 11513af6ab5fSopenharmony_ci TsUtils.isSupportedTypeNodeKind(typeNode.kind) 11523af6ab5fSopenharmony_ci ); 11533af6ab5fSopenharmony_ci } 11543af6ab5fSopenharmony_ci 11553af6ab5fSopenharmony_ci isStructObjectInitializer(objectLiteral: ts.ObjectLiteralExpression): boolean { 11563af6ab5fSopenharmony_ci if (ts.isCallLikeExpression(objectLiteral.parent)) { 11573af6ab5fSopenharmony_ci const signature = this.tsTypeChecker.getResolvedSignature(objectLiteral.parent); 11583af6ab5fSopenharmony_ci const signDecl = signature?.declaration; 11593af6ab5fSopenharmony_ci return !!signDecl && ts.isConstructorDeclaration(signDecl) && isStructDeclaration(signDecl.parent); 11603af6ab5fSopenharmony_ci } 11613af6ab5fSopenharmony_ci return false; 11623af6ab5fSopenharmony_ci } 11633af6ab5fSopenharmony_ci 11643af6ab5fSopenharmony_ci parentSymbolCache = new Map<ts.Symbol, string | undefined>(); 11653af6ab5fSopenharmony_ci 11663af6ab5fSopenharmony_ci getParentSymbolName(symbol: ts.Symbol): string | undefined { 11673af6ab5fSopenharmony_ci const cached = this.parentSymbolCache.get(symbol); 11683af6ab5fSopenharmony_ci if (cached) { 11693af6ab5fSopenharmony_ci return cached; 11703af6ab5fSopenharmony_ci } 11713af6ab5fSopenharmony_ci 11723af6ab5fSopenharmony_ci const name = this.tsTypeChecker.getFullyQualifiedName(symbol); 11733af6ab5fSopenharmony_ci const dotPosition = name.lastIndexOf('.'); 11743af6ab5fSopenharmony_ci const result = dotPosition === -1 ? undefined : name.substring(0, dotPosition); 11753af6ab5fSopenharmony_ci this.parentSymbolCache.set(symbol, result); 11763af6ab5fSopenharmony_ci return result; 11773af6ab5fSopenharmony_ci } 11783af6ab5fSopenharmony_ci 11793af6ab5fSopenharmony_ci isGlobalSymbol(symbol: ts.Symbol): boolean { 11803af6ab5fSopenharmony_ci const parentName = this.getParentSymbolName(symbol); 11813af6ab5fSopenharmony_ci return !parentName || parentName === 'global'; 11823af6ab5fSopenharmony_ci } 11833af6ab5fSopenharmony_ci 11843af6ab5fSopenharmony_ci isStdSymbol(symbol: ts.Symbol): boolean { 11853af6ab5fSopenharmony_ci const name = this.tsTypeChecker.getFullyQualifiedName(symbol); 11863af6ab5fSopenharmony_ci return name === SYMBOL || name === SYMBOL_CONSTRUCTOR; 11873af6ab5fSopenharmony_ci } 11883af6ab5fSopenharmony_ci 11893af6ab5fSopenharmony_ci isStdSymbolAPI(symbol: ts.Symbol): boolean { 11903af6ab5fSopenharmony_ci const parentName = this.getParentSymbolName(symbol); 11913af6ab5fSopenharmony_ci if (this.useSdkLogic) { 11923af6ab5fSopenharmony_ci const name = parentName ? parentName : symbol.escapedName; 11933af6ab5fSopenharmony_ci return name === SYMBOL || name === SYMBOL_CONSTRUCTOR; 11943af6ab5fSopenharmony_ci } 11953af6ab5fSopenharmony_ci return !!parentName && (parentName === SYMBOL || parentName === SYMBOL_CONSTRUCTOR); 11963af6ab5fSopenharmony_ci } 11973af6ab5fSopenharmony_ci 11983af6ab5fSopenharmony_ci isSymbolIterator(symbol: ts.Symbol): boolean { 11993af6ab5fSopenharmony_ci if (this.useSdkLogic) { 12003af6ab5fSopenharmony_ci const name = symbol.name; 12013af6ab5fSopenharmony_ci const parName = this.getParentSymbolName(symbol); 12023af6ab5fSopenharmony_ci return (parName === SYMBOL || parName === SYMBOL_CONSTRUCTOR) && name === ITERATOR; 12033af6ab5fSopenharmony_ci } 12043af6ab5fSopenharmony_ci return this.isStdSymbolAPI(symbol) && symbol.name === ITERATOR; 12053af6ab5fSopenharmony_ci } 12063af6ab5fSopenharmony_ci 12073af6ab5fSopenharmony_ci isSymbolIteratorExpression(expr: ts.Expression): boolean { 12083af6ab5fSopenharmony_ci const symbol = this.trueSymbolAtLocation(expr); 12093af6ab5fSopenharmony_ci return !!symbol && this.isSymbolIterator(symbol); 12103af6ab5fSopenharmony_ci } 12113af6ab5fSopenharmony_ci 12123af6ab5fSopenharmony_ci static isDefaultImport(importSpec: ts.ImportSpecifier): boolean { 12133af6ab5fSopenharmony_ci return importSpec?.propertyName?.text === 'default'; 12143af6ab5fSopenharmony_ci } 12153af6ab5fSopenharmony_ci 12163af6ab5fSopenharmony_ci static getStartPos(nodeOrComment: ts.Node | ts.CommentRange): number { 12173af6ab5fSopenharmony_ci return nodeOrComment.kind === ts.SyntaxKind.SingleLineCommentTrivia || 12183af6ab5fSopenharmony_ci nodeOrComment.kind === ts.SyntaxKind.MultiLineCommentTrivia ? 12193af6ab5fSopenharmony_ci (nodeOrComment as ts.CommentRange).pos : 12203af6ab5fSopenharmony_ci (nodeOrComment as ts.Node).getStart(); 12213af6ab5fSopenharmony_ci } 12223af6ab5fSopenharmony_ci 12233af6ab5fSopenharmony_ci static getEndPos(nodeOrComment: ts.Node | ts.CommentRange): number { 12243af6ab5fSopenharmony_ci return nodeOrComment.kind === ts.SyntaxKind.SingleLineCommentTrivia || 12253af6ab5fSopenharmony_ci nodeOrComment.kind === ts.SyntaxKind.MultiLineCommentTrivia ? 12263af6ab5fSopenharmony_ci (nodeOrComment as ts.CommentRange).end : 12273af6ab5fSopenharmony_ci (nodeOrComment as ts.Node).getEnd(); 12283af6ab5fSopenharmony_ci } 12293af6ab5fSopenharmony_ci 12303af6ab5fSopenharmony_ci static getHighlightRange(nodeOrComment: ts.Node | ts.CommentRange, faultId: number): [number, number] { 12313af6ab5fSopenharmony_ci return ( 12323af6ab5fSopenharmony_ci this.highlightRangeHandlers.get(faultId)?.call(this, nodeOrComment) ?? [ 12333af6ab5fSopenharmony_ci this.getStartPos(nodeOrComment), 12343af6ab5fSopenharmony_ci this.getEndPos(nodeOrComment) 12353af6ab5fSopenharmony_ci ] 12363af6ab5fSopenharmony_ci ); 12373af6ab5fSopenharmony_ci } 12383af6ab5fSopenharmony_ci 12393af6ab5fSopenharmony_ci static highlightRangeHandlers = new Map([ 12403af6ab5fSopenharmony_ci [FaultID.VarDeclaration, TsUtils.getVarDeclarationHighlightRange], 12413af6ab5fSopenharmony_ci [FaultID.CatchWithUnsupportedType, TsUtils.getCatchWithUnsupportedTypeHighlightRange], 12423af6ab5fSopenharmony_ci [FaultID.ForInStatement, TsUtils.getForInStatementHighlightRange], 12433af6ab5fSopenharmony_ci [FaultID.WithStatement, TsUtils.getWithStatementHighlightRange], 12443af6ab5fSopenharmony_ci [FaultID.DeleteOperator, TsUtils.getDeleteOperatorHighlightRange], 12453af6ab5fSopenharmony_ci [FaultID.TypeQuery, TsUtils.getTypeQueryHighlightRange], 12463af6ab5fSopenharmony_ci [FaultID.InstanceofUnsupported, TsUtils.getInstanceofUnsupportedHighlightRange], 12473af6ab5fSopenharmony_ci [FaultID.ConstAssertion, TsUtils.getConstAssertionHighlightRange], 12483af6ab5fSopenharmony_ci [FaultID.LimitedReturnTypeInference, TsUtils.getLimitedReturnTypeInferenceHighlightRange], 12493af6ab5fSopenharmony_ci [FaultID.LocalFunction, TsUtils.getLocalFunctionHighlightRange], 12503af6ab5fSopenharmony_ci [FaultID.FunctionBind, TsUtils.getFunctionApplyCallHighlightRange], 12513af6ab5fSopenharmony_ci [FaultID.FunctionBindError, TsUtils.getFunctionApplyCallHighlightRange], 12523af6ab5fSopenharmony_ci [FaultID.FunctionApplyCall, TsUtils.getFunctionApplyCallHighlightRange], 12533af6ab5fSopenharmony_ci [FaultID.DeclWithDuplicateName, TsUtils.getDeclWithDuplicateNameHighlightRange], 12543af6ab5fSopenharmony_ci [FaultID.ObjectLiteralNoContextType, TsUtils.getObjectLiteralNoContextTypeHighlightRange], 12553af6ab5fSopenharmony_ci [FaultID.ClassExpression, TsUtils.getClassExpressionHighlightRange], 12563af6ab5fSopenharmony_ci [FaultID.MultipleStaticBlocks, TsUtils.getMultipleStaticBlocksHighlightRange], 12573af6ab5fSopenharmony_ci [FaultID.ParameterProperties, TsUtils.getParameterPropertiesHighlightRange], 12583af6ab5fSopenharmony_ci [FaultID.SendableDefiniteAssignment, TsUtils.getSendableDefiniteAssignmentHighlightRange], 12593af6ab5fSopenharmony_ci [FaultID.ObjectTypeLiteral, TsUtils.getObjectTypeLiteralHighlightRange], 12603af6ab5fSopenharmony_ci [FaultID.StructuralIdentity, TsUtils.getStructuralIdentityHighlightRange] 12613af6ab5fSopenharmony_ci ]); 12623af6ab5fSopenharmony_ci 12633af6ab5fSopenharmony_ci static getKeywordHighlightRange(nodeOrComment: ts.Node | ts.CommentRange, keyword: string): [number, number] { 12643af6ab5fSopenharmony_ci const start = this.getStartPos(nodeOrComment); 12653af6ab5fSopenharmony_ci return [start, start + keyword.length]; 12663af6ab5fSopenharmony_ci } 12673af6ab5fSopenharmony_ci 12683af6ab5fSopenharmony_ci static getVarDeclarationHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 12693af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'var'); 12703af6ab5fSopenharmony_ci } 12713af6ab5fSopenharmony_ci 12723af6ab5fSopenharmony_ci static getCatchWithUnsupportedTypeHighlightRange( 12733af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 12743af6ab5fSopenharmony_ci ): [number, number] | undefined { 12753af6ab5fSopenharmony_ci const catchClauseNode = (nodeOrComment as ts.CatchClause).variableDeclaration; 12763af6ab5fSopenharmony_ci if (catchClauseNode !== undefined) { 12773af6ab5fSopenharmony_ci return [catchClauseNode.getStart(), catchClauseNode.getEnd()]; 12783af6ab5fSopenharmony_ci } 12793af6ab5fSopenharmony_ci 12803af6ab5fSopenharmony_ci return undefined; 12813af6ab5fSopenharmony_ci } 12823af6ab5fSopenharmony_ci 12833af6ab5fSopenharmony_ci static getForInStatementHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 12843af6ab5fSopenharmony_ci return [ 12853af6ab5fSopenharmony_ci this.getEndPos((nodeOrComment as ts.ForInStatement).initializer) + 1, 12863af6ab5fSopenharmony_ci this.getStartPos((nodeOrComment as ts.ForInStatement).expression) - 1 12873af6ab5fSopenharmony_ci ]; 12883af6ab5fSopenharmony_ci } 12893af6ab5fSopenharmony_ci 12903af6ab5fSopenharmony_ci static getWithStatementHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 12913af6ab5fSopenharmony_ci return [this.getStartPos(nodeOrComment), (nodeOrComment as ts.WithStatement).statement.getStart() - 1]; 12923af6ab5fSopenharmony_ci } 12933af6ab5fSopenharmony_ci 12943af6ab5fSopenharmony_ci static getDeleteOperatorHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 12953af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'delete'); 12963af6ab5fSopenharmony_ci } 12973af6ab5fSopenharmony_ci 12983af6ab5fSopenharmony_ci static getTypeQueryHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 12993af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'typeof'); 13003af6ab5fSopenharmony_ci } 13013af6ab5fSopenharmony_ci 13023af6ab5fSopenharmony_ci static getInstanceofUnsupportedHighlightRange( 13033af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 13043af6ab5fSopenharmony_ci ): [number, number] | undefined { 13053af6ab5fSopenharmony_ci return this.getKeywordHighlightRange((nodeOrComment as ts.BinaryExpression).operatorToken, 'instanceof'); 13063af6ab5fSopenharmony_ci } 13073af6ab5fSopenharmony_ci 13083af6ab5fSopenharmony_ci static getConstAssertionHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13093af6ab5fSopenharmony_ci if (nodeOrComment.kind === ts.SyntaxKind.AsExpression) { 13103af6ab5fSopenharmony_ci return [ 13113af6ab5fSopenharmony_ci (nodeOrComment as ts.AsExpression).expression.getEnd() + 1, 13123af6ab5fSopenharmony_ci (nodeOrComment as ts.AsExpression).type.getStart() - 1 13133af6ab5fSopenharmony_ci ]; 13143af6ab5fSopenharmony_ci } 13153af6ab5fSopenharmony_ci return [ 13163af6ab5fSopenharmony_ci (nodeOrComment as ts.TypeAssertion).expression.getEnd() + 1, 13173af6ab5fSopenharmony_ci (nodeOrComment as ts.TypeAssertion).type.getEnd() + 1 13183af6ab5fSopenharmony_ci ]; 13193af6ab5fSopenharmony_ci } 13203af6ab5fSopenharmony_ci 13213af6ab5fSopenharmony_ci static getLimitedReturnTypeInferenceHighlightRange( 13223af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 13233af6ab5fSopenharmony_ci ): [number, number] | undefined { 13243af6ab5fSopenharmony_ci let node: ts.Node | undefined; 13253af6ab5fSopenharmony_ci if (nodeOrComment.kind === ts.SyntaxKind.FunctionExpression) { 13263af6ab5fSopenharmony_ci // we got error about return type so it should be present 13273af6ab5fSopenharmony_ci node = (nodeOrComment as ts.FunctionExpression).type; 13283af6ab5fSopenharmony_ci } else if (nodeOrComment.kind === ts.SyntaxKind.FunctionDeclaration) { 13293af6ab5fSopenharmony_ci node = (nodeOrComment as ts.FunctionDeclaration).name; 13303af6ab5fSopenharmony_ci } else if (nodeOrComment.kind === ts.SyntaxKind.MethodDeclaration) { 13313af6ab5fSopenharmony_ci node = (nodeOrComment as ts.MethodDeclaration).name; 13323af6ab5fSopenharmony_ci } 13333af6ab5fSopenharmony_ci 13343af6ab5fSopenharmony_ci if (node !== undefined) { 13353af6ab5fSopenharmony_ci return [node.getStart(), node.getEnd()]; 13363af6ab5fSopenharmony_ci } 13373af6ab5fSopenharmony_ci 13383af6ab5fSopenharmony_ci return undefined; 13393af6ab5fSopenharmony_ci } 13403af6ab5fSopenharmony_ci 13413af6ab5fSopenharmony_ci static getLocalFunctionHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13423af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'function'); 13433af6ab5fSopenharmony_ci } 13443af6ab5fSopenharmony_ci 13453af6ab5fSopenharmony_ci static getFunctionApplyCallHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13463af6ab5fSopenharmony_ci const pointPos = (nodeOrComment as ts.Node).getText().lastIndexOf('.'); 13473af6ab5fSopenharmony_ci return [this.getStartPos(nodeOrComment) + pointPos + 1, this.getEndPos(nodeOrComment)]; 13483af6ab5fSopenharmony_ci } 13493af6ab5fSopenharmony_ci 13503af6ab5fSopenharmony_ci static getDeclWithDuplicateNameHighlightRange( 13513af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 13523af6ab5fSopenharmony_ci ): [number, number] | undefined { 13533af6ab5fSopenharmony_ci // in case of private identifier no range update is needed 13543af6ab5fSopenharmony_ci const nameNode: ts.Node | undefined = (nodeOrComment as ts.NamedDeclaration).name; 13553af6ab5fSopenharmony_ci if (nameNode !== undefined) { 13563af6ab5fSopenharmony_ci return [nameNode.getStart(), nameNode.getEnd()]; 13573af6ab5fSopenharmony_ci } 13583af6ab5fSopenharmony_ci 13593af6ab5fSopenharmony_ci return undefined; 13603af6ab5fSopenharmony_ci } 13613af6ab5fSopenharmony_ci 13623af6ab5fSopenharmony_ci static getObjectLiteralNoContextTypeHighlightRange( 13633af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 13643af6ab5fSopenharmony_ci ): [number, number] | undefined { 13653af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, '{'); 13663af6ab5fSopenharmony_ci } 13673af6ab5fSopenharmony_ci 13683af6ab5fSopenharmony_ci static getClassExpressionHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13693af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'class'); 13703af6ab5fSopenharmony_ci } 13713af6ab5fSopenharmony_ci 13723af6ab5fSopenharmony_ci static getMultipleStaticBlocksHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13733af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, 'static'); 13743af6ab5fSopenharmony_ci } 13753af6ab5fSopenharmony_ci 13763af6ab5fSopenharmony_ci static getParameterPropertiesHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13773af6ab5fSopenharmony_ci const param = nodeOrComment as ts.ParameterDeclaration; 13783af6ab5fSopenharmony_ci const modifier = TsUtils.getAccessModifier(ts.getModifiers(param)); 13793af6ab5fSopenharmony_ci if (modifier !== undefined) { 13803af6ab5fSopenharmony_ci return [modifier.getStart(), modifier.getEnd()]; 13813af6ab5fSopenharmony_ci } 13823af6ab5fSopenharmony_ci return undefined; 13833af6ab5fSopenharmony_ci } 13843af6ab5fSopenharmony_ci 13853af6ab5fSopenharmony_ci static getObjectTypeLiteralHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 13863af6ab5fSopenharmony_ci return this.getKeywordHighlightRange(nodeOrComment, '{'); 13873af6ab5fSopenharmony_ci } 13883af6ab5fSopenharmony_ci 13893af6ab5fSopenharmony_ci // highlight ranges for Sendable rules 13903af6ab5fSopenharmony_ci 13913af6ab5fSopenharmony_ci static getSendableDefiniteAssignmentHighlightRange( 13923af6ab5fSopenharmony_ci nodeOrComment: ts.Node | ts.CommentRange 13933af6ab5fSopenharmony_ci ): [number, number] | undefined { 13943af6ab5fSopenharmony_ci const name = (nodeOrComment as ts.PropertyDeclaration).name; 13953af6ab5fSopenharmony_ci const exclamationToken = (nodeOrComment as ts.PropertyDeclaration).exclamationToken; 13963af6ab5fSopenharmony_ci return [name.getStart(), exclamationToken ? exclamationToken.getEnd() : name.getEnd()]; 13973af6ab5fSopenharmony_ci } 13983af6ab5fSopenharmony_ci 13993af6ab5fSopenharmony_ci static getStructuralIdentityHighlightRange(nodeOrComment: ts.Node | ts.CommentRange): [number, number] | undefined { 14003af6ab5fSopenharmony_ci let node: ts.Node | undefined; 14013af6ab5fSopenharmony_ci if (nodeOrComment.kind === ts.SyntaxKind.ReturnStatement) { 14023af6ab5fSopenharmony_ci node = (nodeOrComment as ts.ReturnStatement).expression; 14033af6ab5fSopenharmony_ci } else if (nodeOrComment.kind === ts.SyntaxKind.PropertyDeclaration) { 14043af6ab5fSopenharmony_ci node = (nodeOrComment as ts.PropertyDeclaration).name; 14053af6ab5fSopenharmony_ci } 14063af6ab5fSopenharmony_ci 14073af6ab5fSopenharmony_ci if (node !== undefined) { 14083af6ab5fSopenharmony_ci return [node.getStart(), node.getEnd()]; 14093af6ab5fSopenharmony_ci } 14103af6ab5fSopenharmony_ci 14113af6ab5fSopenharmony_ci return undefined; 14123af6ab5fSopenharmony_ci } 14133af6ab5fSopenharmony_ci 14143af6ab5fSopenharmony_ci isStdRecordType(type: ts.Type): boolean { 14153af6ab5fSopenharmony_ci 14163af6ab5fSopenharmony_ci /* 14173af6ab5fSopenharmony_ci * In TypeScript, 'Record<K, T>' is defined as type alias to a mapped type. 14183af6ab5fSopenharmony_ci * Thus, it should have 'aliasSymbol' and 'target' properties. The 'target' 14193af6ab5fSopenharmony_ci * in this case will resolve to origin 'Record' symbol. 14203af6ab5fSopenharmony_ci */ 14213af6ab5fSopenharmony_ci if (type.aliasSymbol) { 14223af6ab5fSopenharmony_ci const target = (type as ts.TypeReference).target; 14233af6ab5fSopenharmony_ci if (target) { 14243af6ab5fSopenharmony_ci const sym = target.aliasSymbol; 14253af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Record' && this.isGlobalSymbol(sym); 14263af6ab5fSopenharmony_ci } 14273af6ab5fSopenharmony_ci } 14283af6ab5fSopenharmony_ci 14293af6ab5fSopenharmony_ci return false; 14303af6ab5fSopenharmony_ci } 14313af6ab5fSopenharmony_ci 14323af6ab5fSopenharmony_ci isStdErrorType(type: ts.Type): boolean { 14333af6ab5fSopenharmony_ci const symbol = type.symbol; 14343af6ab5fSopenharmony_ci if (!symbol) { 14353af6ab5fSopenharmony_ci return false; 14363af6ab5fSopenharmony_ci } 14373af6ab5fSopenharmony_ci const name = this.tsTypeChecker.getFullyQualifiedName(symbol); 14383af6ab5fSopenharmony_ci return name === 'Error' && this.isGlobalSymbol(symbol); 14393af6ab5fSopenharmony_ci } 14403af6ab5fSopenharmony_ci 14413af6ab5fSopenharmony_ci isStdPartialType(type: ts.Type): boolean { 14423af6ab5fSopenharmony_ci const sym = type.aliasSymbol; 14433af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Partial' && this.isGlobalSymbol(sym); 14443af6ab5fSopenharmony_ci } 14453af6ab5fSopenharmony_ci 14463af6ab5fSopenharmony_ci isStdRequiredType(type: ts.Type): boolean { 14473af6ab5fSopenharmony_ci const sym = type.aliasSymbol; 14483af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Required' && this.isGlobalSymbol(sym); 14493af6ab5fSopenharmony_ci } 14503af6ab5fSopenharmony_ci 14513af6ab5fSopenharmony_ci isStdReadonlyType(type: ts.Type): boolean { 14523af6ab5fSopenharmony_ci const sym = type.aliasSymbol; 14533af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Readonly' && this.isGlobalSymbol(sym); 14543af6ab5fSopenharmony_ci } 14553af6ab5fSopenharmony_ci 14563af6ab5fSopenharmony_ci isLibraryType(type: ts.Type): boolean { 14573af6ab5fSopenharmony_ci const nonNullableType = type.getNonNullableType(); 14583af6ab5fSopenharmony_ci if (nonNullableType.isUnion()) { 14593af6ab5fSopenharmony_ci for (const componentType of nonNullableType.types) { 14603af6ab5fSopenharmony_ci if (!this.isLibraryType(componentType)) { 14613af6ab5fSopenharmony_ci return false; 14623af6ab5fSopenharmony_ci } 14633af6ab5fSopenharmony_ci } 14643af6ab5fSopenharmony_ci return true; 14653af6ab5fSopenharmony_ci } 14663af6ab5fSopenharmony_ci return this.isLibrarySymbol(nonNullableType.aliasSymbol ?? nonNullableType.getSymbol()); 14673af6ab5fSopenharmony_ci } 14683af6ab5fSopenharmony_ci 14693af6ab5fSopenharmony_ci hasLibraryType(node: ts.Node): boolean { 14703af6ab5fSopenharmony_ci return this.isLibraryType(this.tsTypeChecker.getTypeAtLocation(node)); 14713af6ab5fSopenharmony_ci } 14723af6ab5fSopenharmony_ci 14733af6ab5fSopenharmony_ci isLibrarySymbol(sym: ts.Symbol | undefined): boolean { 14743af6ab5fSopenharmony_ci if (sym?.declarations && sym.declarations.length > 0) { 14753af6ab5fSopenharmony_ci const srcFile = sym.declarations[0].getSourceFile(); 14763af6ab5fSopenharmony_ci if (!srcFile) { 14773af6ab5fSopenharmony_ci return false; 14783af6ab5fSopenharmony_ci } 14793af6ab5fSopenharmony_ci const fileName = srcFile.fileName; 14803af6ab5fSopenharmony_ci 14813af6ab5fSopenharmony_ci /* 14823af6ab5fSopenharmony_ci * Symbols from both *.ts and *.d.ts files should obey interop rules. 14833af6ab5fSopenharmony_ci * We disable such behavior for *.ts files in the test mode due to lack of 'ets' 14843af6ab5fSopenharmony_ci * extension support. 14853af6ab5fSopenharmony_ci */ 14863af6ab5fSopenharmony_ci const ext = path.extname(fileName).toLowerCase(); 14873af6ab5fSopenharmony_ci const isThirdPartyCode = 14883af6ab5fSopenharmony_ci ARKTS_IGNORE_DIRS.some((ignore) => { 14893af6ab5fSopenharmony_ci return srcFilePathContainsDirectory(srcFile, ignore); 14903af6ab5fSopenharmony_ci }) || 14913af6ab5fSopenharmony_ci ARKTS_IGNORE_FILES.some((ignore) => { 14923af6ab5fSopenharmony_ci return path.basename(fileName) === ignore; 14933af6ab5fSopenharmony_ci }); 14943af6ab5fSopenharmony_ci const isEts = ext === '.ets'; 14953af6ab5fSopenharmony_ci const isTs = ext === '.ts' && !srcFile.isDeclarationFile; 14963af6ab5fSopenharmony_ci const isStatic = (isEts || isTs && this.testMode) && !isThirdPartyCode; 14973af6ab5fSopenharmony_ci const isStdLib = STANDARD_LIBRARIES.includes(path.basename(fileName).toLowerCase()); 14983af6ab5fSopenharmony_ci 14993af6ab5fSopenharmony_ci /* 15003af6ab5fSopenharmony_ci * We still need to confirm support for certain API from the 15013af6ab5fSopenharmony_ci * TypeScript standard library in ArkTS. Thus, for now do not 15023af6ab5fSopenharmony_ci * count standard library modules as dynamic. 15033af6ab5fSopenharmony_ci */ 15043af6ab5fSopenharmony_ci return !isStatic && !isStdLib; 15053af6ab5fSopenharmony_ci } 15063af6ab5fSopenharmony_ci return false; 15073af6ab5fSopenharmony_ci } 15083af6ab5fSopenharmony_ci 15093af6ab5fSopenharmony_ci isDynamicType(type: ts.Type | undefined): boolean | undefined { 15103af6ab5fSopenharmony_ci if (type === undefined) { 15113af6ab5fSopenharmony_ci return false; 15123af6ab5fSopenharmony_ci } 15133af6ab5fSopenharmony_ci 15143af6ab5fSopenharmony_ci /* 15153af6ab5fSopenharmony_ci * Return 'true' if it is an object of library type initialization, otherwise 15163af6ab5fSopenharmony_ci * return 'false' if it is not an object of standard library type one. 15173af6ab5fSopenharmony_ci * In the case of standard library type we need to determine context. 15183af6ab5fSopenharmony_ci */ 15193af6ab5fSopenharmony_ci 15203af6ab5fSopenharmony_ci /* 15213af6ab5fSopenharmony_ci * Check the non-nullable version of type to eliminate 'undefined' type 15223af6ab5fSopenharmony_ci * from the union type elements. 15233af6ab5fSopenharmony_ci */ 15243af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 15253af6ab5fSopenharmony_ci type = type.getNonNullableType(); 15263af6ab5fSopenharmony_ci 15273af6ab5fSopenharmony_ci if (type.isUnion()) { 15283af6ab5fSopenharmony_ci for (const compType of type.types) { 15293af6ab5fSopenharmony_ci const isDynamic = this.isDynamicType(compType); 15303af6ab5fSopenharmony_ci if (isDynamic || isDynamic === undefined) { 15313af6ab5fSopenharmony_ci return isDynamic; 15323af6ab5fSopenharmony_ci } 15333af6ab5fSopenharmony_ci } 15343af6ab5fSopenharmony_ci return false; 15353af6ab5fSopenharmony_ci } 15363af6ab5fSopenharmony_ci 15373af6ab5fSopenharmony_ci if (this.isLibraryType(type)) { 15383af6ab5fSopenharmony_ci return true; 15393af6ab5fSopenharmony_ci } 15403af6ab5fSopenharmony_ci 15413af6ab5fSopenharmony_ci if (!isStdLibraryType(type) && !isIntrinsicObjectType(type) && !TsUtils.isAnyType(type)) { 15423af6ab5fSopenharmony_ci return false; 15433af6ab5fSopenharmony_ci } 15443af6ab5fSopenharmony_ci 15453af6ab5fSopenharmony_ci return undefined; 15463af6ab5fSopenharmony_ci } 15473af6ab5fSopenharmony_ci 15483af6ab5fSopenharmony_ci static isObjectType(type: ts.Type): type is ts.ObjectType { 15493af6ab5fSopenharmony_ci return !!(type.flags & ts.TypeFlags.Object); 15503af6ab5fSopenharmony_ci } 15513af6ab5fSopenharmony_ci 15523af6ab5fSopenharmony_ci private static isAnonymous(type: ts.Type): boolean { 15533af6ab5fSopenharmony_ci if (TsUtils.isObjectType(type)) { 15543af6ab5fSopenharmony_ci return !!(type.objectFlags & ts.ObjectFlags.Anonymous); 15553af6ab5fSopenharmony_ci } 15563af6ab5fSopenharmony_ci return false; 15573af6ab5fSopenharmony_ci } 15583af6ab5fSopenharmony_ci 15593af6ab5fSopenharmony_ci private isDynamicLiteralInitializerHandleCallExpression(callExpr: ts.CallExpression): boolean { 15603af6ab5fSopenharmony_ci const type = this.tsTypeChecker.getTypeAtLocation(callExpr.expression); 15613af6ab5fSopenharmony_ci 15623af6ab5fSopenharmony_ci if (TsUtils.isAnyType(type)) { 15633af6ab5fSopenharmony_ci return true; 15643af6ab5fSopenharmony_ci } 15653af6ab5fSopenharmony_ci 15663af6ab5fSopenharmony_ci let sym: ts.Symbol | undefined = type.symbol; 15673af6ab5fSopenharmony_ci if (this.isLibrarySymbol(sym)) { 15683af6ab5fSopenharmony_ci return true; 15693af6ab5fSopenharmony_ci } 15703af6ab5fSopenharmony_ci 15713af6ab5fSopenharmony_ci /* 15723af6ab5fSopenharmony_ci * #13483: 15733af6ab5fSopenharmony_ci * x.foo({ ... }), where 'x' is exported from some library: 15743af6ab5fSopenharmony_ci */ 15753af6ab5fSopenharmony_ci if (ts.isPropertyAccessExpression(callExpr.expression)) { 15763af6ab5fSopenharmony_ci sym = this.trueSymbolAtLocation(callExpr.expression.expression); 15773af6ab5fSopenharmony_ci if (sym && this.isLibrarySymbol(sym)) { 15783af6ab5fSopenharmony_ci return true; 15793af6ab5fSopenharmony_ci } 15803af6ab5fSopenharmony_ci } 15813af6ab5fSopenharmony_ci 15823af6ab5fSopenharmony_ci return false; 15833af6ab5fSopenharmony_ci } 15843af6ab5fSopenharmony_ci 15853af6ab5fSopenharmony_ci isDynamicLiteralInitializer(expr: ts.Expression): boolean { 15863af6ab5fSopenharmony_ci if (!ts.isObjectLiteralExpression(expr) && !ts.isArrayLiteralExpression(expr)) { 15873af6ab5fSopenharmony_ci return false; 15883af6ab5fSopenharmony_ci } 15893af6ab5fSopenharmony_ci 15903af6ab5fSopenharmony_ci /* 15913af6ab5fSopenharmony_ci * Handle nested literals: 15923af6ab5fSopenharmony_ci * { f: { ... } } 15933af6ab5fSopenharmony_ci */ 15943af6ab5fSopenharmony_ci let curNode: ts.Node = expr; 15953af6ab5fSopenharmony_ci while (ts.isObjectLiteralExpression(curNode) || ts.isArrayLiteralExpression(curNode)) { 15963af6ab5fSopenharmony_ci const exprType = this.tsTypeChecker.getContextualType(curNode); 15973af6ab5fSopenharmony_ci if (exprType !== undefined && !TsUtils.isAnonymous(exprType)) { 15983af6ab5fSopenharmony_ci const res = this.isDynamicType(exprType); 15993af6ab5fSopenharmony_ci if (res !== undefined) { 16003af6ab5fSopenharmony_ci return res; 16013af6ab5fSopenharmony_ci } 16023af6ab5fSopenharmony_ci } 16033af6ab5fSopenharmony_ci 16043af6ab5fSopenharmony_ci curNode = curNode.parent; 16053af6ab5fSopenharmony_ci if (ts.isPropertyAssignment(curNode)) { 16063af6ab5fSopenharmony_ci curNode = curNode.parent; 16073af6ab5fSopenharmony_ci } 16083af6ab5fSopenharmony_ci } 16093af6ab5fSopenharmony_ci 16103af6ab5fSopenharmony_ci /* 16113af6ab5fSopenharmony_ci * Handle calls with literals: 16123af6ab5fSopenharmony_ci * foo({ ... }) 16133af6ab5fSopenharmony_ci */ 16143af6ab5fSopenharmony_ci if (ts.isCallExpression(curNode) && this.isDynamicLiteralInitializerHandleCallExpression(curNode)) { 16153af6ab5fSopenharmony_ci return true; 16163af6ab5fSopenharmony_ci } 16173af6ab5fSopenharmony_ci 16183af6ab5fSopenharmony_ci /* 16193af6ab5fSopenharmony_ci * Handle property assignments with literals: 16203af6ab5fSopenharmony_ci * obj.f = { ... } 16213af6ab5fSopenharmony_ci */ 16223af6ab5fSopenharmony_ci if (ts.isBinaryExpression(curNode)) { 16233af6ab5fSopenharmony_ci const binExpr = curNode; 16243af6ab5fSopenharmony_ci if (ts.isPropertyAccessExpression(binExpr.left)) { 16253af6ab5fSopenharmony_ci const propAccessExpr = binExpr.left; 16263af6ab5fSopenharmony_ci const type = this.tsTypeChecker.getTypeAtLocation(propAccessExpr.expression); 16273af6ab5fSopenharmony_ci return this.isLibrarySymbol(type.symbol); 16283af6ab5fSopenharmony_ci } 16293af6ab5fSopenharmony_ci } 16303af6ab5fSopenharmony_ci 16313af6ab5fSopenharmony_ci return false; 16323af6ab5fSopenharmony_ci } 16333af6ab5fSopenharmony_ci 16343af6ab5fSopenharmony_ci static isEsObjectType(typeNode: ts.TypeNode | undefined): boolean { 16353af6ab5fSopenharmony_ci return ( 16363af6ab5fSopenharmony_ci !!typeNode && 16373af6ab5fSopenharmony_ci ts.isTypeReferenceNode(typeNode) && 16383af6ab5fSopenharmony_ci ts.isIdentifier(typeNode.typeName) && 16393af6ab5fSopenharmony_ci typeNode.typeName.text === ES_OBJECT 16403af6ab5fSopenharmony_ci ); 16413af6ab5fSopenharmony_ci } 16423af6ab5fSopenharmony_ci 16433af6ab5fSopenharmony_ci static isInsideBlock(node: ts.Node): boolean { 16443af6ab5fSopenharmony_ci let par = node.parent; 16453af6ab5fSopenharmony_ci while (par) { 16463af6ab5fSopenharmony_ci if (ts.isBlock(par)) { 16473af6ab5fSopenharmony_ci return true; 16483af6ab5fSopenharmony_ci } 16493af6ab5fSopenharmony_ci par = par.parent; 16503af6ab5fSopenharmony_ci } 16513af6ab5fSopenharmony_ci return false; 16523af6ab5fSopenharmony_ci } 16533af6ab5fSopenharmony_ci 16543af6ab5fSopenharmony_ci static isEsObjectPossiblyAllowed(typeRef: ts.TypeReferenceNode): boolean { 16553af6ab5fSopenharmony_ci return ts.isVariableDeclaration(typeRef.parent); 16563af6ab5fSopenharmony_ci } 16573af6ab5fSopenharmony_ci 16583af6ab5fSopenharmony_ci isValueAssignableToESObject(node: ts.Node): boolean { 16593af6ab5fSopenharmony_ci if (ts.isArrayLiteralExpression(node) || ts.isObjectLiteralExpression(node)) { 16603af6ab5fSopenharmony_ci return false; 16613af6ab5fSopenharmony_ci } 16623af6ab5fSopenharmony_ci const valueType = this.tsTypeChecker.getTypeAtLocation(node); 16633af6ab5fSopenharmony_ci return TsUtils.isUnsupportedType(valueType) || TsUtils.isAnonymousType(valueType); 16643af6ab5fSopenharmony_ci } 16653af6ab5fSopenharmony_ci 16663af6ab5fSopenharmony_ci getVariableDeclarationTypeNode(node: ts.Node): ts.TypeNode | undefined { 16673af6ab5fSopenharmony_ci const sym = this.trueSymbolAtLocation(node); 16683af6ab5fSopenharmony_ci if (sym === undefined) { 16693af6ab5fSopenharmony_ci return undefined; 16703af6ab5fSopenharmony_ci } 16713af6ab5fSopenharmony_ci return TsUtils.getSymbolDeclarationTypeNode(sym); 16723af6ab5fSopenharmony_ci } 16733af6ab5fSopenharmony_ci 16743af6ab5fSopenharmony_ci static getSymbolDeclarationTypeNode(sym: ts.Symbol): ts.TypeNode | undefined { 16753af6ab5fSopenharmony_ci const decl = TsUtils.getDeclaration(sym); 16763af6ab5fSopenharmony_ci if (!!decl && ts.isVariableDeclaration(decl)) { 16773af6ab5fSopenharmony_ci return decl.type; 16783af6ab5fSopenharmony_ci } 16793af6ab5fSopenharmony_ci return undefined; 16803af6ab5fSopenharmony_ci } 16813af6ab5fSopenharmony_ci 16823af6ab5fSopenharmony_ci hasEsObjectType(node: ts.Node): boolean { 16833af6ab5fSopenharmony_ci const typeNode = this.getVariableDeclarationTypeNode(node); 16843af6ab5fSopenharmony_ci return typeNode !== undefined && TsUtils.isEsObjectType(typeNode); 16853af6ab5fSopenharmony_ci } 16863af6ab5fSopenharmony_ci 16873af6ab5fSopenharmony_ci static symbolHasEsObjectType(sym: ts.Symbol): boolean { 16883af6ab5fSopenharmony_ci const typeNode = TsUtils.getSymbolDeclarationTypeNode(sym); 16893af6ab5fSopenharmony_ci return typeNode !== undefined && TsUtils.isEsObjectType(typeNode); 16903af6ab5fSopenharmony_ci } 16913af6ab5fSopenharmony_ci 16923af6ab5fSopenharmony_ci static isEsObjectSymbol(sym: ts.Symbol): boolean { 16933af6ab5fSopenharmony_ci const decl = TsUtils.getDeclaration(sym); 16943af6ab5fSopenharmony_ci return ( 16953af6ab5fSopenharmony_ci !!decl && 16963af6ab5fSopenharmony_ci ts.isTypeAliasDeclaration(decl) && 16973af6ab5fSopenharmony_ci decl.name.escapedText === ES_OBJECT && 16983af6ab5fSopenharmony_ci decl.type.kind === ts.SyntaxKind.AnyKeyword 16993af6ab5fSopenharmony_ci ); 17003af6ab5fSopenharmony_ci } 17013af6ab5fSopenharmony_ci 17023af6ab5fSopenharmony_ci static isAnonymousType(type: ts.Type): boolean { 17033af6ab5fSopenharmony_ci if (type.isUnionOrIntersection()) { 17043af6ab5fSopenharmony_ci for (const compType of type.types) { 17053af6ab5fSopenharmony_ci if (TsUtils.isAnonymousType(compType)) { 17063af6ab5fSopenharmony_ci return true; 17073af6ab5fSopenharmony_ci } 17083af6ab5fSopenharmony_ci } 17093af6ab5fSopenharmony_ci return false; 17103af6ab5fSopenharmony_ci } 17113af6ab5fSopenharmony_ci 17123af6ab5fSopenharmony_ci return ( 17133af6ab5fSopenharmony_ci (type.flags & ts.TypeFlags.Object) !== 0 && ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Anonymous) !== 0 17143af6ab5fSopenharmony_ci ); 17153af6ab5fSopenharmony_ci } 17163af6ab5fSopenharmony_ci 17173af6ab5fSopenharmony_ci getSymbolOfCallExpression(callExpr: ts.CallExpression): ts.Symbol | undefined { 17183af6ab5fSopenharmony_ci const signature = this.tsTypeChecker.getResolvedSignature(callExpr); 17193af6ab5fSopenharmony_ci const signDecl = signature?.getDeclaration(); 17203af6ab5fSopenharmony_ci if (signDecl?.name) { 17213af6ab5fSopenharmony_ci return this.trueSymbolAtLocation(signDecl.name); 17223af6ab5fSopenharmony_ci } 17233af6ab5fSopenharmony_ci return undefined; 17243af6ab5fSopenharmony_ci } 17253af6ab5fSopenharmony_ci 17263af6ab5fSopenharmony_ci static isClassValueType(type: ts.Type): boolean { 17273af6ab5fSopenharmony_ci if ( 17283af6ab5fSopenharmony_ci (type.flags & ts.TypeFlags.Object) === 0 || 17293af6ab5fSopenharmony_ci ((type as ts.ObjectType).objectFlags & ts.ObjectFlags.Anonymous) === 0 17303af6ab5fSopenharmony_ci ) { 17313af6ab5fSopenharmony_ci return false; 17323af6ab5fSopenharmony_ci } 17333af6ab5fSopenharmony_ci return type.symbol && (type.symbol.flags & ts.SymbolFlags.Class) !== 0; 17343af6ab5fSopenharmony_ci } 17353af6ab5fSopenharmony_ci 17363af6ab5fSopenharmony_ci isClassObjectExpression(expr: ts.Expression): boolean { 17373af6ab5fSopenharmony_ci if (!TsUtils.isClassValueType(this.tsTypeChecker.getTypeAtLocation(expr))) { 17383af6ab5fSopenharmony_ci return false; 17393af6ab5fSopenharmony_ci } 17403af6ab5fSopenharmony_ci const symbol = this.trueSymbolAtLocation(expr); 17413af6ab5fSopenharmony_ci return !symbol || (symbol.flags & ts.SymbolFlags.Class) === 0; 17423af6ab5fSopenharmony_ci } 17433af6ab5fSopenharmony_ci 17443af6ab5fSopenharmony_ci isClassTypeExpression(expr: ts.Expression): boolean { 17453af6ab5fSopenharmony_ci const sym = this.trueSymbolAtLocation(expr); 17463af6ab5fSopenharmony_ci return sym !== undefined && (sym.flags & ts.SymbolFlags.Class) !== 0; 17473af6ab5fSopenharmony_ci } 17483af6ab5fSopenharmony_ci 17493af6ab5fSopenharmony_ci isFunctionCalledRecursively(funcExpr: ts.FunctionExpression): boolean { 17503af6ab5fSopenharmony_ci if (!funcExpr.name) { 17513af6ab5fSopenharmony_ci return false; 17523af6ab5fSopenharmony_ci } 17533af6ab5fSopenharmony_ci 17543af6ab5fSopenharmony_ci const sym = this.tsTypeChecker.getSymbolAtLocation(funcExpr.name); 17553af6ab5fSopenharmony_ci if (!sym) { 17563af6ab5fSopenharmony_ci return false; 17573af6ab5fSopenharmony_ci } 17583af6ab5fSopenharmony_ci 17593af6ab5fSopenharmony_ci let found = false; 17603af6ab5fSopenharmony_ci const callback = (node: ts.Node): void => { 17613af6ab5fSopenharmony_ci if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) { 17623af6ab5fSopenharmony_ci const callSym = this.tsTypeChecker.getSymbolAtLocation(node.expression); 17633af6ab5fSopenharmony_ci if (callSym && callSym === sym) { 17643af6ab5fSopenharmony_ci found = true; 17653af6ab5fSopenharmony_ci } 17663af6ab5fSopenharmony_ci } 17673af6ab5fSopenharmony_ci }; 17683af6ab5fSopenharmony_ci 17693af6ab5fSopenharmony_ci const stopCondition = (node: ts.Node): boolean => { 17703af6ab5fSopenharmony_ci void node; 17713af6ab5fSopenharmony_ci return found; 17723af6ab5fSopenharmony_ci }; 17733af6ab5fSopenharmony_ci 17743af6ab5fSopenharmony_ci forEachNodeInSubtree(funcExpr, callback, stopCondition); 17753af6ab5fSopenharmony_ci return found; 17763af6ab5fSopenharmony_ci } 17773af6ab5fSopenharmony_ci 17783af6ab5fSopenharmony_ci getTypeOrTypeConstraintAtLocation(expr: ts.Expression): ts.Type { 17793af6ab5fSopenharmony_ci const type = this.tsTypeChecker.getTypeAtLocation(expr); 17803af6ab5fSopenharmony_ci if (type.isTypeParameter()) { 17813af6ab5fSopenharmony_ci const constraint = type.getConstraint(); 17823af6ab5fSopenharmony_ci if (constraint) { 17833af6ab5fSopenharmony_ci return constraint; 17843af6ab5fSopenharmony_ci } 17853af6ab5fSopenharmony_ci } 17863af6ab5fSopenharmony_ci return type; 17873af6ab5fSopenharmony_ci } 17883af6ab5fSopenharmony_ci 17893af6ab5fSopenharmony_ci private areCompatibleFunctionals(lhsType: ts.Type, rhsType: ts.Type): boolean { 17903af6ab5fSopenharmony_ci return ( 17913af6ab5fSopenharmony_ci (this.isStdFunctionType(lhsType) || TsUtils.isFunctionalType(lhsType)) && 17923af6ab5fSopenharmony_ci (this.isStdFunctionType(rhsType) || TsUtils.isFunctionalType(rhsType)) 17933af6ab5fSopenharmony_ci ); 17943af6ab5fSopenharmony_ci } 17953af6ab5fSopenharmony_ci 17963af6ab5fSopenharmony_ci private static isFunctionalType(type: ts.Type): boolean { 17973af6ab5fSopenharmony_ci const callSigns = type.getCallSignatures(); 17983af6ab5fSopenharmony_ci return callSigns && callSigns.length > 0; 17993af6ab5fSopenharmony_ci } 18003af6ab5fSopenharmony_ci 18013af6ab5fSopenharmony_ci private isStdFunctionType(type: ts.Type): boolean { 18023af6ab5fSopenharmony_ci const sym = type.getSymbol(); 18033af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Function' && this.isGlobalSymbol(sym); 18043af6ab5fSopenharmony_ci } 18053af6ab5fSopenharmony_ci 18063af6ab5fSopenharmony_ci isStdBigIntType(type: ts.Type): boolean { 18073af6ab5fSopenharmony_ci const sym = type.symbol; 18083af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'BigInt' && this.isGlobalSymbol(sym); 18093af6ab5fSopenharmony_ci } 18103af6ab5fSopenharmony_ci 18113af6ab5fSopenharmony_ci isStdNumberType(type: ts.Type): boolean { 18123af6ab5fSopenharmony_ci const sym = type.symbol; 18133af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Number' && this.isGlobalSymbol(sym); 18143af6ab5fSopenharmony_ci } 18153af6ab5fSopenharmony_ci 18163af6ab5fSopenharmony_ci isStdBooleanType(type: ts.Type): boolean { 18173af6ab5fSopenharmony_ci const sym = type.symbol; 18183af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Boolean' && this.isGlobalSymbol(sym); 18193af6ab5fSopenharmony_ci } 18203af6ab5fSopenharmony_ci 18213af6ab5fSopenharmony_ci isEnumStringLiteral(expr: ts.Expression): boolean { 18223af6ab5fSopenharmony_ci const symbol = this.trueSymbolAtLocation(expr); 18233af6ab5fSopenharmony_ci const isEnumMember = !!symbol && !!(symbol.flags & ts.SymbolFlags.EnumMember); 18243af6ab5fSopenharmony_ci const type = this.tsTypeChecker.getTypeAtLocation(expr); 18253af6ab5fSopenharmony_ci const isStringEnumLiteral = TsUtils.isEnumType(type) && !!(type.flags & ts.TypeFlags.StringLiteral); 18263af6ab5fSopenharmony_ci return isEnumMember && isStringEnumLiteral; 18273af6ab5fSopenharmony_ci } 18283af6ab5fSopenharmony_ci 18293af6ab5fSopenharmony_ci isValidComputedPropertyName(computedProperty: ts.ComputedPropertyName, isRecordObjectInitializer = false): boolean { 18303af6ab5fSopenharmony_ci const expr = computedProperty.expression; 18313af6ab5fSopenharmony_ci if (!isRecordObjectInitializer) { 18323af6ab5fSopenharmony_ci if (this.isSymbolIteratorExpression(expr)) { 18333af6ab5fSopenharmony_ci return true; 18343af6ab5fSopenharmony_ci } 18353af6ab5fSopenharmony_ci } 18363af6ab5fSopenharmony_ci // We allow computed property names if expression is string literal or string Enum member 18373af6ab5fSopenharmony_ci return ts.isStringLiteralLike(expr) || this.isEnumStringLiteral(computedProperty.expression); 18383af6ab5fSopenharmony_ci } 18393af6ab5fSopenharmony_ci 18403af6ab5fSopenharmony_ci skipPropertyInferredTypeCheck( 18413af6ab5fSopenharmony_ci decl: ts.PropertyDeclaration, 18423af6ab5fSopenharmony_ci sourceFile: ts.SourceFile | undefined, 18433af6ab5fSopenharmony_ci isEtsFileCb: IsEtsFileCallback | undefined 18443af6ab5fSopenharmony_ci ): boolean { 18453af6ab5fSopenharmony_ci if (!sourceFile) { 18463af6ab5fSopenharmony_ci return false; 18473af6ab5fSopenharmony_ci } 18483af6ab5fSopenharmony_ci 18493af6ab5fSopenharmony_ci const isEts = this.useSdkLogic ? 18503af6ab5fSopenharmony_ci getScriptKind(sourceFile) === ts.ScriptKind.ETS : 18513af6ab5fSopenharmony_ci !!isEtsFileCb && isEtsFileCb(sourceFile); 18523af6ab5fSopenharmony_ci return ( 18533af6ab5fSopenharmony_ci isEts && 18543af6ab5fSopenharmony_ci sourceFile.isDeclarationFile && 18553af6ab5fSopenharmony_ci !!decl.modifiers?.some((m) => { 18563af6ab5fSopenharmony_ci return m.kind === ts.SyntaxKind.PrivateKeyword; 18573af6ab5fSopenharmony_ci }) 18583af6ab5fSopenharmony_ci ); 18593af6ab5fSopenharmony_ci } 18603af6ab5fSopenharmony_ci 18613af6ab5fSopenharmony_ci hasAccessModifier(decl: ts.HasModifiers): boolean { 18623af6ab5fSopenharmony_ci const modifiers = ts.getModifiers(decl); 18633af6ab5fSopenharmony_ci return ( 18643af6ab5fSopenharmony_ci !!modifiers && 18653af6ab5fSopenharmony_ci (this.useSdkLogic && TsUtils.hasModifier(modifiers, ts.SyntaxKind.ReadonlyKeyword) || 18663af6ab5fSopenharmony_ci TsUtils.hasModifier(modifiers, ts.SyntaxKind.PublicKeyword) || 18673af6ab5fSopenharmony_ci TsUtils.hasModifier(modifiers, ts.SyntaxKind.ProtectedKeyword) || 18683af6ab5fSopenharmony_ci TsUtils.hasModifier(modifiers, ts.SyntaxKind.PrivateKeyword)) 18693af6ab5fSopenharmony_ci ); 18703af6ab5fSopenharmony_ci } 18713af6ab5fSopenharmony_ci 18723af6ab5fSopenharmony_ci static getModifier( 18733af6ab5fSopenharmony_ci modifiers: readonly ts.Modifier[] | undefined, 18743af6ab5fSopenharmony_ci modifierKind: ts.SyntaxKind 18753af6ab5fSopenharmony_ci ): ts.Modifier | undefined { 18763af6ab5fSopenharmony_ci if (!modifiers) { 18773af6ab5fSopenharmony_ci return undefined; 18783af6ab5fSopenharmony_ci } 18793af6ab5fSopenharmony_ci return modifiers.find((x) => { 18803af6ab5fSopenharmony_ci return x.kind === modifierKind; 18813af6ab5fSopenharmony_ci }); 18823af6ab5fSopenharmony_ci } 18833af6ab5fSopenharmony_ci 18843af6ab5fSopenharmony_ci static getAccessModifier(modifiers: readonly ts.Modifier[] | undefined): ts.Modifier | undefined { 18853af6ab5fSopenharmony_ci return ( 18863af6ab5fSopenharmony_ci TsUtils.getModifier(modifiers, ts.SyntaxKind.PublicKeyword) ?? 18873af6ab5fSopenharmony_ci TsUtils.getModifier(modifiers, ts.SyntaxKind.ProtectedKeyword) ?? 18883af6ab5fSopenharmony_ci TsUtils.getModifier(modifiers, ts.SyntaxKind.PrivateKeyword) 18893af6ab5fSopenharmony_ci ); 18903af6ab5fSopenharmony_ci } 18913af6ab5fSopenharmony_ci 18923af6ab5fSopenharmony_ci static getBaseClassType(type: ts.Type): ts.InterfaceType | undefined { 18933af6ab5fSopenharmony_ci const baseTypes = type.getBaseTypes(); 18943af6ab5fSopenharmony_ci if (baseTypes) { 18953af6ab5fSopenharmony_ci for (const baseType of baseTypes) { 18963af6ab5fSopenharmony_ci if (baseType.isClass()) { 18973af6ab5fSopenharmony_ci return baseType; 18983af6ab5fSopenharmony_ci } 18993af6ab5fSopenharmony_ci } 19003af6ab5fSopenharmony_ci } 19013af6ab5fSopenharmony_ci 19023af6ab5fSopenharmony_ci return undefined; 19033af6ab5fSopenharmony_ci } 19043af6ab5fSopenharmony_ci 19053af6ab5fSopenharmony_ci static destructuringAssignmentHasSpreadOperator(node: ts.AssignmentPattern): boolean { 19063af6ab5fSopenharmony_ci if (ts.isArrayLiteralExpression(node)) { 19073af6ab5fSopenharmony_ci return node.elements.some((x) => { 19083af6ab5fSopenharmony_ci if (ts.isSpreadElement(x)) { 19093af6ab5fSopenharmony_ci return true; 19103af6ab5fSopenharmony_ci } 19113af6ab5fSopenharmony_ci if (ts.isObjectLiteralExpression(x) || ts.isArrayLiteralExpression(x)) { 19123af6ab5fSopenharmony_ci return TsUtils.destructuringAssignmentHasSpreadOperator(x); 19133af6ab5fSopenharmony_ci } 19143af6ab5fSopenharmony_ci return false; 19153af6ab5fSopenharmony_ci }); 19163af6ab5fSopenharmony_ci } 19173af6ab5fSopenharmony_ci 19183af6ab5fSopenharmony_ci return node.properties.some((x) => { 19193af6ab5fSopenharmony_ci if (ts.isSpreadAssignment(x)) { 19203af6ab5fSopenharmony_ci return true; 19213af6ab5fSopenharmony_ci } 19223af6ab5fSopenharmony_ci if ( 19233af6ab5fSopenharmony_ci ts.isPropertyAssignment(x) && 19243af6ab5fSopenharmony_ci (ts.isObjectLiteralExpression(x.initializer) || ts.isArrayLiteralExpression(x.initializer)) 19253af6ab5fSopenharmony_ci ) { 19263af6ab5fSopenharmony_ci return TsUtils.destructuringAssignmentHasSpreadOperator(x.initializer); 19273af6ab5fSopenharmony_ci } 19283af6ab5fSopenharmony_ci return false; 19293af6ab5fSopenharmony_ci }); 19303af6ab5fSopenharmony_ci } 19313af6ab5fSopenharmony_ci 19323af6ab5fSopenharmony_ci static destructuringDeclarationHasSpreadOperator(node: ts.BindingPattern): boolean { 19333af6ab5fSopenharmony_ci return node.elements.some((x) => { 19343af6ab5fSopenharmony_ci if (ts.isBindingElement(x)) { 19353af6ab5fSopenharmony_ci if (x.dotDotDotToken) { 19363af6ab5fSopenharmony_ci return true; 19373af6ab5fSopenharmony_ci } 19383af6ab5fSopenharmony_ci if (ts.isArrayBindingPattern(x.name) || ts.isObjectBindingPattern(x.name)) { 19393af6ab5fSopenharmony_ci return TsUtils.destructuringDeclarationHasSpreadOperator(x.name); 19403af6ab5fSopenharmony_ci } 19413af6ab5fSopenharmony_ci } 19423af6ab5fSopenharmony_ci return false; 19433af6ab5fSopenharmony_ci }); 19443af6ab5fSopenharmony_ci } 19453af6ab5fSopenharmony_ci 19463af6ab5fSopenharmony_ci static hasNestedObjectDestructuring(node: ts.ArrayBindingOrAssignmentPattern): boolean { 19473af6ab5fSopenharmony_ci if (ts.isArrayLiteralExpression(node)) { 19483af6ab5fSopenharmony_ci return node.elements.some((x) => { 19493af6ab5fSopenharmony_ci const elem = ts.isSpreadElement(x) ? x.expression : x; 19503af6ab5fSopenharmony_ci if (ts.isArrayLiteralExpression(elem)) { 19513af6ab5fSopenharmony_ci return TsUtils.hasNestedObjectDestructuring(elem); 19523af6ab5fSopenharmony_ci } 19533af6ab5fSopenharmony_ci return ts.isObjectLiteralExpression(elem); 19543af6ab5fSopenharmony_ci }); 19553af6ab5fSopenharmony_ci } 19563af6ab5fSopenharmony_ci 19573af6ab5fSopenharmony_ci return node.elements.some((x) => { 19583af6ab5fSopenharmony_ci if (ts.isBindingElement(x)) { 19593af6ab5fSopenharmony_ci if (ts.isArrayBindingPattern(x.name)) { 19603af6ab5fSopenharmony_ci return TsUtils.hasNestedObjectDestructuring(x.name); 19613af6ab5fSopenharmony_ci } 19623af6ab5fSopenharmony_ci return ts.isObjectBindingPattern(x.name); 19633af6ab5fSopenharmony_ci } 19643af6ab5fSopenharmony_ci return false; 19653af6ab5fSopenharmony_ci }); 19663af6ab5fSopenharmony_ci } 19673af6ab5fSopenharmony_ci 19683af6ab5fSopenharmony_ci static getDecoratorName(decorator: ts.Decorator): string { 19693af6ab5fSopenharmony_ci let decoratorName = ''; 19703af6ab5fSopenharmony_ci if (ts.isIdentifier(decorator.expression)) { 19713af6ab5fSopenharmony_ci decoratorName = decorator.expression.text; 19723af6ab5fSopenharmony_ci } else if (ts.isCallExpression(decorator.expression) && ts.isIdentifier(decorator.expression.expression)) { 19733af6ab5fSopenharmony_ci decoratorName = decorator.expression.expression.text; 19743af6ab5fSopenharmony_ci } 19753af6ab5fSopenharmony_ci return decoratorName; 19763af6ab5fSopenharmony_ci } 19773af6ab5fSopenharmony_ci 19783af6ab5fSopenharmony_ci static unwrapParenthesizedTypeNode(typeNode: ts.TypeNode): ts.TypeNode { 19793af6ab5fSopenharmony_ci let unwrappedTypeNode = typeNode; 19803af6ab5fSopenharmony_ci while (ts.isParenthesizedTypeNode(unwrappedTypeNode)) { 19813af6ab5fSopenharmony_ci unwrappedTypeNode = unwrappedTypeNode.type; 19823af6ab5fSopenharmony_ci } 19833af6ab5fSopenharmony_ci 19843af6ab5fSopenharmony_ci return unwrappedTypeNode; 19853af6ab5fSopenharmony_ci } 19863af6ab5fSopenharmony_ci 19873af6ab5fSopenharmony_ci isSendableTypeNode(typeNode: ts.TypeNode, isShared: boolean = false): boolean { 19883af6ab5fSopenharmony_ci 19893af6ab5fSopenharmony_ci /* 19903af6ab5fSopenharmony_ci * In order to correctly identify the usage of the enum member or 19913af6ab5fSopenharmony_ci * const enum in type annotation, we need to handle union type and 19923af6ab5fSopenharmony_ci * type alias cases by processing the type node and checking the 19933af6ab5fSopenharmony_ci * symbol in case of type reference node. 19943af6ab5fSopenharmony_ci */ 19953af6ab5fSopenharmony_ci 19963af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 19973af6ab5fSopenharmony_ci typeNode = TsUtils.unwrapParenthesizedTypeNode(typeNode); 19983af6ab5fSopenharmony_ci 19993af6ab5fSopenharmony_ci // Only a sendable union type is supported 20003af6ab5fSopenharmony_ci if (ts.isUnionTypeNode(typeNode)) { 20013af6ab5fSopenharmony_ci return typeNode.types.every((elemType) => { 20023af6ab5fSopenharmony_ci return this.isSendableTypeNode(elemType, isShared); 20033af6ab5fSopenharmony_ci }); 20043af6ab5fSopenharmony_ci } 20053af6ab5fSopenharmony_ci 20063af6ab5fSopenharmony_ci const sym = ts.isTypeReferenceNode(typeNode) ? this.trueSymbolAtLocation(typeNode.typeName) : undefined; 20073af6ab5fSopenharmony_ci 20083af6ab5fSopenharmony_ci if (sym && sym.getFlags() & ts.SymbolFlags.TypeAlias) { 20093af6ab5fSopenharmony_ci const typeDecl = TsUtils.getDeclaration(sym); 20103af6ab5fSopenharmony_ci if (typeDecl && ts.isTypeAliasDeclaration(typeDecl)) { 20113af6ab5fSopenharmony_ci const typeArgs = (typeNode as ts.TypeReferenceNode).typeArguments; 20123af6ab5fSopenharmony_ci if ( 20133af6ab5fSopenharmony_ci typeArgs && 20143af6ab5fSopenharmony_ci !typeArgs.every((typeArg) => { 20153af6ab5fSopenharmony_ci return this.isSendableTypeNode(typeArg); 20163af6ab5fSopenharmony_ci }) 20173af6ab5fSopenharmony_ci ) { 20183af6ab5fSopenharmony_ci return false; 20193af6ab5fSopenharmony_ci } 20203af6ab5fSopenharmony_ci return this.isSendableTypeNode(typeDecl.type, isShared); 20213af6ab5fSopenharmony_ci } 20223af6ab5fSopenharmony_ci } 20233af6ab5fSopenharmony_ci 20243af6ab5fSopenharmony_ci // Const enum type is supported 20253af6ab5fSopenharmony_ci if (TsUtils.isConstEnum(sym)) { 20263af6ab5fSopenharmony_ci return true; 20273af6ab5fSopenharmony_ci } 20283af6ab5fSopenharmony_ci const type: ts.Type = this.tsTypeChecker.getTypeFromTypeNode(typeNode); 20293af6ab5fSopenharmony_ci 20303af6ab5fSopenharmony_ci // In shared module, literal forms of primitive data types can be exported 20313af6ab5fSopenharmony_ci if (isShared && TsUtils.isPurePrimitiveLiteralType(type)) { 20323af6ab5fSopenharmony_ci return true; 20333af6ab5fSopenharmony_ci } 20343af6ab5fSopenharmony_ci 20353af6ab5fSopenharmony_ci return this.isSendableType(type); 20363af6ab5fSopenharmony_ci } 20373af6ab5fSopenharmony_ci 20383af6ab5fSopenharmony_ci isSendableType(type: ts.Type): boolean { 20393af6ab5fSopenharmony_ci if ( 20403af6ab5fSopenharmony_ci (type.flags & 20413af6ab5fSopenharmony_ci (ts.TypeFlags.Boolean | 20423af6ab5fSopenharmony_ci ts.TypeFlags.Number | 20433af6ab5fSopenharmony_ci ts.TypeFlags.String | 20443af6ab5fSopenharmony_ci ts.TypeFlags.BigInt | 20453af6ab5fSopenharmony_ci ts.TypeFlags.Null | 20463af6ab5fSopenharmony_ci ts.TypeFlags.Undefined | 20473af6ab5fSopenharmony_ci ts.TypeFlags.TypeParameter)) !== 20483af6ab5fSopenharmony_ci 0 20493af6ab5fSopenharmony_ci ) { 20503af6ab5fSopenharmony_ci return true; 20513af6ab5fSopenharmony_ci } 20523af6ab5fSopenharmony_ci if (this.isSendableTypeAlias(type)) { 20533af6ab5fSopenharmony_ci return true; 20543af6ab5fSopenharmony_ci } 20553af6ab5fSopenharmony_ci if (TsUtils.isSendableFunction(type)) { 20563af6ab5fSopenharmony_ci return true; 20573af6ab5fSopenharmony_ci } 20583af6ab5fSopenharmony_ci 20593af6ab5fSopenharmony_ci return this.isSendableClassOrInterface(type); 20603af6ab5fSopenharmony_ci } 20613af6ab5fSopenharmony_ci 20623af6ab5fSopenharmony_ci isShareableType(tsType: ts.Type): boolean { 20633af6ab5fSopenharmony_ci const sym = tsType.getSymbol(); 20643af6ab5fSopenharmony_ci if (TsUtils.isConstEnum(sym)) { 20653af6ab5fSopenharmony_ci return true; 20663af6ab5fSopenharmony_ci } 20673af6ab5fSopenharmony_ci 20683af6ab5fSopenharmony_ci if (tsType.isUnion()) { 20693af6ab5fSopenharmony_ci return tsType.types.every((elemType) => { 20703af6ab5fSopenharmony_ci return this.isShareableType(elemType); 20713af6ab5fSopenharmony_ci }); 20723af6ab5fSopenharmony_ci } 20733af6ab5fSopenharmony_ci 20743af6ab5fSopenharmony_ci if (TsUtils.isPurePrimitiveLiteralType(tsType)) { 20753af6ab5fSopenharmony_ci return true; 20763af6ab5fSopenharmony_ci } 20773af6ab5fSopenharmony_ci 20783af6ab5fSopenharmony_ci return this.isSendableType(tsType); 20793af6ab5fSopenharmony_ci } 20803af6ab5fSopenharmony_ci 20813af6ab5fSopenharmony_ci isSendableClassOrInterface(type: ts.Type): boolean { 20823af6ab5fSopenharmony_ci const sym = type.getSymbol(); 20833af6ab5fSopenharmony_ci if (!sym) { 20843af6ab5fSopenharmony_ci return false; 20853af6ab5fSopenharmony_ci } 20863af6ab5fSopenharmony_ci 20873af6ab5fSopenharmony_ci const targetType = TsUtils.reduceReference(type); 20883af6ab5fSopenharmony_ci 20893af6ab5fSopenharmony_ci // class with @Sendable decorator 20903af6ab5fSopenharmony_ci if (targetType.isClass()) { 20913af6ab5fSopenharmony_ci if (sym.declarations?.length) { 20923af6ab5fSopenharmony_ci const decl = sym.declarations[0]; 20933af6ab5fSopenharmony_ci if (ts.isClassDeclaration(decl)) { 20943af6ab5fSopenharmony_ci return TsUtils.hasSendableDecorator(decl); 20953af6ab5fSopenharmony_ci } 20963af6ab5fSopenharmony_ci } 20973af6ab5fSopenharmony_ci } 20983af6ab5fSopenharmony_ci // ISendable interface, or a class/interface that implements/extends ISendable interface 20993af6ab5fSopenharmony_ci return this.isOrDerivedFrom(type, TsUtils.isISendableInterface); 21003af6ab5fSopenharmony_ci } 21013af6ab5fSopenharmony_ci 21023af6ab5fSopenharmony_ci typeContainsSendableClassOrInterface(type: ts.Type): boolean { 21033af6ab5fSopenharmony_ci // Only check type contains sendable class / interface 21043af6ab5fSopenharmony_ci if ((type.flags & ts.TypeFlags.Union) !== 0) { 21053af6ab5fSopenharmony_ci return !!(type as ts.UnionType)?.types?.some((type) => { 21063af6ab5fSopenharmony_ci return this.typeContainsSendableClassOrInterface(type); 21073af6ab5fSopenharmony_ci }); 21083af6ab5fSopenharmony_ci } 21093af6ab5fSopenharmony_ci 21103af6ab5fSopenharmony_ci return this.isSendableClassOrInterface(type); 21113af6ab5fSopenharmony_ci } 21123af6ab5fSopenharmony_ci 21133af6ab5fSopenharmony_ci typeContainsNonSendableClassOrInterface(type: ts.Type): boolean { 21143af6ab5fSopenharmony_ci if (type.isUnion()) { 21153af6ab5fSopenharmony_ci return type.types.some((compType) => { 21163af6ab5fSopenharmony_ci return this.typeContainsNonSendableClassOrInterface(compType); 21173af6ab5fSopenharmony_ci }); 21183af6ab5fSopenharmony_ci } 21193af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 21203af6ab5fSopenharmony_ci type = TsUtils.reduceReference(type); 21213af6ab5fSopenharmony_ci return type.isClassOrInterface() && !this.isSendableClassOrInterface(type); 21223af6ab5fSopenharmony_ci } 21233af6ab5fSopenharmony_ci 21243af6ab5fSopenharmony_ci static isConstEnum(sym: ts.Symbol | undefined): boolean { 21253af6ab5fSopenharmony_ci return !!sym && sym.flags === ts.SymbolFlags.ConstEnum; 21263af6ab5fSopenharmony_ci } 21273af6ab5fSopenharmony_ci 21283af6ab5fSopenharmony_ci isSendableUnionType(type: ts.UnionType): boolean { 21293af6ab5fSopenharmony_ci const types = type?.types; 21303af6ab5fSopenharmony_ci if (!types) { 21313af6ab5fSopenharmony_ci return false; 21323af6ab5fSopenharmony_ci } 21333af6ab5fSopenharmony_ci 21343af6ab5fSopenharmony_ci return types.every((type) => { 21353af6ab5fSopenharmony_ci return this.isSendableType(type); 21363af6ab5fSopenharmony_ci }); 21373af6ab5fSopenharmony_ci } 21383af6ab5fSopenharmony_ci 21393af6ab5fSopenharmony_ci static hasSendableDecorator(decl: ts.ClassDeclaration | ts.FunctionDeclaration | ts.TypeAliasDeclaration): boolean { 21403af6ab5fSopenharmony_ci return !!TsUtils.getSendableDecorator(decl); 21413af6ab5fSopenharmony_ci } 21423af6ab5fSopenharmony_ci 21433af6ab5fSopenharmony_ci static getNonSendableDecorators( 21443af6ab5fSopenharmony_ci decl: ts.ClassDeclaration | ts.FunctionDeclaration | ts.TypeAliasDeclaration 21453af6ab5fSopenharmony_ci ): ts.Decorator[] | undefined { 21463af6ab5fSopenharmony_ci const decorators = ts.getAllDecorators(decl); 21473af6ab5fSopenharmony_ci return decorators?.filter((x) => { 21483af6ab5fSopenharmony_ci return TsUtils.getDecoratorName(x) !== SENDABLE_DECORATOR; 21493af6ab5fSopenharmony_ci }); 21503af6ab5fSopenharmony_ci } 21513af6ab5fSopenharmony_ci 21523af6ab5fSopenharmony_ci static getSendableDecorator( 21533af6ab5fSopenharmony_ci decl: ts.ClassDeclaration | ts.FunctionDeclaration | ts.TypeAliasDeclaration 21543af6ab5fSopenharmony_ci ): ts.Decorator | undefined { 21553af6ab5fSopenharmony_ci const decorators = ts.getAllDecorators(decl); 21563af6ab5fSopenharmony_ci return decorators?.find((x) => { 21573af6ab5fSopenharmony_ci return TsUtils.getDecoratorName(x) === SENDABLE_DECORATOR; 21583af6ab5fSopenharmony_ci }); 21593af6ab5fSopenharmony_ci } 21603af6ab5fSopenharmony_ci 21613af6ab5fSopenharmony_ci static getDecoratorsIfInSendableClass(declaration: ts.HasDecorators): readonly ts.Decorator[] | undefined { 21623af6ab5fSopenharmony_ci const classNode = TsUtils.getClassNodeFromDeclaration(declaration); 21633af6ab5fSopenharmony_ci if (classNode === undefined || !TsUtils.hasSendableDecorator(classNode)) { 21643af6ab5fSopenharmony_ci return undefined; 21653af6ab5fSopenharmony_ci } 21663af6ab5fSopenharmony_ci return ts.getDecorators(declaration); 21673af6ab5fSopenharmony_ci } 21683af6ab5fSopenharmony_ci 21693af6ab5fSopenharmony_ci private static getClassNodeFromDeclaration(declaration: ts.HasDecorators): ts.ClassDeclaration | undefined { 21703af6ab5fSopenharmony_ci if (declaration.kind === ts.SyntaxKind.Parameter) { 21713af6ab5fSopenharmony_ci return ts.isClassDeclaration(declaration.parent.parent) ? declaration.parent.parent : undefined; 21723af6ab5fSopenharmony_ci } 21733af6ab5fSopenharmony_ci return ts.isClassDeclaration(declaration.parent) ? declaration.parent : undefined; 21743af6ab5fSopenharmony_ci } 21753af6ab5fSopenharmony_ci 21763af6ab5fSopenharmony_ci static isISendableInterface(type: ts.Type): boolean { 21773af6ab5fSopenharmony_ci const symbol = type.aliasSymbol ?? type.getSymbol(); 21783af6ab5fSopenharmony_ci if (symbol?.declarations === undefined || symbol.declarations.length < 1) { 21793af6ab5fSopenharmony_ci return false; 21803af6ab5fSopenharmony_ci } 21813af6ab5fSopenharmony_ci 21823af6ab5fSopenharmony_ci return TsUtils.isArkTSISendableDeclaration(symbol.declarations[0]); 21833af6ab5fSopenharmony_ci } 21843af6ab5fSopenharmony_ci 21853af6ab5fSopenharmony_ci private static isArkTSISendableDeclaration(decl: ts.Declaration): boolean { 21863af6ab5fSopenharmony_ci if (!ts.isInterfaceDeclaration(decl) || !decl.name || decl.name.text !== ISENDABLE_TYPE) { 21873af6ab5fSopenharmony_ci return false; 21883af6ab5fSopenharmony_ci } 21893af6ab5fSopenharmony_ci 21903af6ab5fSopenharmony_ci if (!ts.isModuleBlock(decl.parent) || decl.parent.parent.name.text !== LANG_NAMESPACE) { 21913af6ab5fSopenharmony_ci return false; 21923af6ab5fSopenharmony_ci } 21933af6ab5fSopenharmony_ci 21943af6ab5fSopenharmony_ci if (path.basename(decl.getSourceFile().fileName).toLowerCase() !== ARKTS_LANG_D_ETS) { 21953af6ab5fSopenharmony_ci return false; 21963af6ab5fSopenharmony_ci } 21973af6ab5fSopenharmony_ci 21983af6ab5fSopenharmony_ci return true; 21993af6ab5fSopenharmony_ci } 22003af6ab5fSopenharmony_ci 22013af6ab5fSopenharmony_ci isAllowedIndexSignature(node: ts.IndexSignatureDeclaration): boolean { 22023af6ab5fSopenharmony_ci 22033af6ab5fSopenharmony_ci /* 22043af6ab5fSopenharmony_ci * For now, relax index signature only for specific array-like types 22053af6ab5fSopenharmony_ci * with the following signature: 'collections.Array<T>.[_: number]: T'. 22063af6ab5fSopenharmony_ci */ 22073af6ab5fSopenharmony_ci 22083af6ab5fSopenharmony_ci if (node.parameters.length !== 1) { 22093af6ab5fSopenharmony_ci return false; 22103af6ab5fSopenharmony_ci } 22113af6ab5fSopenharmony_ci 22123af6ab5fSopenharmony_ci const paramType = this.tsTypeChecker.getTypeAtLocation(node.parameters[0]); 22133af6ab5fSopenharmony_ci if ((paramType.flags & ts.TypeFlags.Number) === 0) { 22143af6ab5fSopenharmony_ci return false; 22153af6ab5fSopenharmony_ci } 22163af6ab5fSopenharmony_ci 22173af6ab5fSopenharmony_ci return this.isArkTSCollectionsArrayLikeDeclaration(node.parent); 22183af6ab5fSopenharmony_ci } 22193af6ab5fSopenharmony_ci 22203af6ab5fSopenharmony_ci isArkTSCollectionsArrayLikeType(type: ts.Type): boolean { 22213af6ab5fSopenharmony_ci const symbol = type.aliasSymbol ?? type.getSymbol(); 22223af6ab5fSopenharmony_ci if (symbol?.declarations === undefined || symbol.declarations.length < 1) { 22233af6ab5fSopenharmony_ci return false; 22243af6ab5fSopenharmony_ci } 22253af6ab5fSopenharmony_ci 22263af6ab5fSopenharmony_ci return this.isArkTSCollectionsArrayLikeDeclaration(symbol.declarations[0]); 22273af6ab5fSopenharmony_ci } 22283af6ab5fSopenharmony_ci 22293af6ab5fSopenharmony_ci private isArkTSCollectionsArrayLikeDeclaration(decl: ts.Declaration): boolean { 22303af6ab5fSopenharmony_ci if (!TsUtils.isArkTSCollectionsClassOrInterfaceDeclaration(decl)) { 22313af6ab5fSopenharmony_ci return false; 22323af6ab5fSopenharmony_ci } 22333af6ab5fSopenharmony_ci if (!this.tsTypeChecker.getTypeAtLocation(decl).getNumberIndexType()) { 22343af6ab5fSopenharmony_ci return false; 22353af6ab5fSopenharmony_ci } 22363af6ab5fSopenharmony_ci return true; 22373af6ab5fSopenharmony_ci } 22383af6ab5fSopenharmony_ci 22393af6ab5fSopenharmony_ci static isArkTSCollectionsClassOrInterfaceDeclaration(decl: ts.Node): boolean { 22403af6ab5fSopenharmony_ci if (!ts.isClassDeclaration(decl) && !ts.isInterfaceDeclaration(decl) || !decl.name) { 22413af6ab5fSopenharmony_ci return false; 22423af6ab5fSopenharmony_ci } 22433af6ab5fSopenharmony_ci if (!ts.isModuleBlock(decl.parent) || decl.parent.parent.name.text !== COLLECTIONS_NAMESPACE) { 22443af6ab5fSopenharmony_ci return false; 22453af6ab5fSopenharmony_ci } 22463af6ab5fSopenharmony_ci if (path.basename(decl.getSourceFile().fileName).toLowerCase() !== ARKTS_COLLECTIONS_D_ETS) { 22473af6ab5fSopenharmony_ci return false; 22483af6ab5fSopenharmony_ci } 22493af6ab5fSopenharmony_ci return true; 22503af6ab5fSopenharmony_ci } 22513af6ab5fSopenharmony_ci 22523af6ab5fSopenharmony_ci private proceedConstructorDeclaration( 22533af6ab5fSopenharmony_ci isFromPrivateIdentifierOrSdk: boolean, 22543af6ab5fSopenharmony_ci targetMember: ts.ClassElement, 22553af6ab5fSopenharmony_ci classMember: ts.ClassElement, 22563af6ab5fSopenharmony_ci isFromPrivateIdentifier: boolean 22573af6ab5fSopenharmony_ci ): boolean | undefined { 22583af6ab5fSopenharmony_ci if ( 22593af6ab5fSopenharmony_ci isFromPrivateIdentifierOrSdk && 22603af6ab5fSopenharmony_ci ts.isConstructorDeclaration(classMember) && 22613af6ab5fSopenharmony_ci classMember.parameters.some((x) => { 22623af6ab5fSopenharmony_ci return ( 22633af6ab5fSopenharmony_ci ts.isIdentifier(x.name) && 22643af6ab5fSopenharmony_ci this.hasAccessModifier(x) && 22653af6ab5fSopenharmony_ci this.isPrivateIdentifierDuplicateOfIdentifier( 22663af6ab5fSopenharmony_ci targetMember.name as ts.Identifier, 22673af6ab5fSopenharmony_ci x.name, 22683af6ab5fSopenharmony_ci isFromPrivateIdentifier 22693af6ab5fSopenharmony_ci ) 22703af6ab5fSopenharmony_ci ); 22713af6ab5fSopenharmony_ci }) 22723af6ab5fSopenharmony_ci ) { 22733af6ab5fSopenharmony_ci return true; 22743af6ab5fSopenharmony_ci } 22753af6ab5fSopenharmony_ci return undefined; 22763af6ab5fSopenharmony_ci } 22773af6ab5fSopenharmony_ci 22783af6ab5fSopenharmony_ci private proceedClassType( 22793af6ab5fSopenharmony_ci targetMember: ts.ClassElement, 22803af6ab5fSopenharmony_ci classType: ts.Type, 22813af6ab5fSopenharmony_ci isFromPrivateIdentifier: boolean 22823af6ab5fSopenharmony_ci ): boolean | undefined { 22833af6ab5fSopenharmony_ci if (classType) { 22843af6ab5fSopenharmony_ci const baseType = TsUtils.getBaseClassType(classType); 22853af6ab5fSopenharmony_ci if (baseType) { 22863af6ab5fSopenharmony_ci const baseDecl = baseType.getSymbol()?.valueDeclaration as ts.ClassLikeDeclaration; 22873af6ab5fSopenharmony_ci if (baseDecl) { 22883af6ab5fSopenharmony_ci return this.classMemberHasDuplicateName(targetMember, baseDecl, isFromPrivateIdentifier); 22893af6ab5fSopenharmony_ci } 22903af6ab5fSopenharmony_ci } 22913af6ab5fSopenharmony_ci } 22923af6ab5fSopenharmony_ci return undefined; 22933af6ab5fSopenharmony_ci } 22943af6ab5fSopenharmony_ci 22953af6ab5fSopenharmony_ci classMemberHasDuplicateName( 22963af6ab5fSopenharmony_ci targetMember: ts.ClassElement, 22973af6ab5fSopenharmony_ci tsClassLikeDecl: ts.ClassLikeDeclaration, 22983af6ab5fSopenharmony_ci isFromPrivateIdentifier: boolean, 22993af6ab5fSopenharmony_ci classType?: ts.Type 23003af6ab5fSopenharmony_ci ): boolean { 23013af6ab5fSopenharmony_ci 23023af6ab5fSopenharmony_ci /* 23033af6ab5fSopenharmony_ci * If two class members have the same name where one is a private identifer, 23043af6ab5fSopenharmony_ci * then such members are considered to have duplicate names. 23053af6ab5fSopenharmony_ci */ 23063af6ab5fSopenharmony_ci if (!TsUtils.isIdentifierOrPrivateIdentifier(targetMember.name)) { 23073af6ab5fSopenharmony_ci return false; 23083af6ab5fSopenharmony_ci } 23093af6ab5fSopenharmony_ci 23103af6ab5fSopenharmony_ci const isFromPrivateIdentifierOrSdk = this.isFromPrivateIdentifierOrSdk(isFromPrivateIdentifier); 23113af6ab5fSopenharmony_ci for (const classMember of tsClassLikeDecl.members) { 23123af6ab5fSopenharmony_ci if (targetMember === classMember) { 23133af6ab5fSopenharmony_ci continue; 23143af6ab5fSopenharmony_ci } 23153af6ab5fSopenharmony_ci 23163af6ab5fSopenharmony_ci // Check constructor parameter properties. 23173af6ab5fSopenharmony_ci const constructorDeclarationProceedResult = this.proceedConstructorDeclaration( 23183af6ab5fSopenharmony_ci isFromPrivateIdentifierOrSdk, 23193af6ab5fSopenharmony_ci targetMember, 23203af6ab5fSopenharmony_ci classMember, 23213af6ab5fSopenharmony_ci isFromPrivateIdentifier 23223af6ab5fSopenharmony_ci ); 23233af6ab5fSopenharmony_ci if (constructorDeclarationProceedResult) { 23243af6ab5fSopenharmony_ci return constructorDeclarationProceedResult; 23253af6ab5fSopenharmony_ci } 23263af6ab5fSopenharmony_ci if (!TsUtils.isIdentifierOrPrivateIdentifier(classMember.name)) { 23273af6ab5fSopenharmony_ci continue; 23283af6ab5fSopenharmony_ci } 23293af6ab5fSopenharmony_ci if (this.isPrivateIdentifierDuplicateOfIdentifier(targetMember.name, classMember.name, isFromPrivateIdentifier)) { 23303af6ab5fSopenharmony_ci return true; 23313af6ab5fSopenharmony_ci } 23323af6ab5fSopenharmony_ci } 23333af6ab5fSopenharmony_ci 23343af6ab5fSopenharmony_ci if (isFromPrivateIdentifierOrSdk) { 23353af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 23363af6ab5fSopenharmony_ci classType ??= this.tsTypeChecker.getTypeAtLocation(tsClassLikeDecl); 23373af6ab5fSopenharmony_ci const proceedClassTypeResult = this.proceedClassType(targetMember, classType, isFromPrivateIdentifier); 23383af6ab5fSopenharmony_ci if (proceedClassTypeResult) { 23393af6ab5fSopenharmony_ci return proceedClassTypeResult; 23403af6ab5fSopenharmony_ci } 23413af6ab5fSopenharmony_ci } 23423af6ab5fSopenharmony_ci 23433af6ab5fSopenharmony_ci return false; 23443af6ab5fSopenharmony_ci } 23453af6ab5fSopenharmony_ci 23463af6ab5fSopenharmony_ci private isFromPrivateIdentifierOrSdk(isFromPrivateIdentifier: boolean): boolean { 23473af6ab5fSopenharmony_ci return !this.useSdkLogic || isFromPrivateIdentifier; 23483af6ab5fSopenharmony_ci } 23493af6ab5fSopenharmony_ci 23503af6ab5fSopenharmony_ci private static isIdentifierOrPrivateIdentifier(node?: ts.PropertyName): node is ts.Identifier | ts.PrivateIdentifier { 23513af6ab5fSopenharmony_ci if (!node) { 23523af6ab5fSopenharmony_ci return false; 23533af6ab5fSopenharmony_ci } 23543af6ab5fSopenharmony_ci return ts.isIdentifier(node) || ts.isPrivateIdentifier(node); 23553af6ab5fSopenharmony_ci } 23563af6ab5fSopenharmony_ci 23573af6ab5fSopenharmony_ci private isPrivateIdentifierDuplicateOfIdentifier( 23583af6ab5fSopenharmony_ci ident1: ts.Identifier | ts.PrivateIdentifier, 23593af6ab5fSopenharmony_ci ident2: ts.Identifier | ts.PrivateIdentifier, 23603af6ab5fSopenharmony_ci isFromPrivateIdentifier: boolean 23613af6ab5fSopenharmony_ci ): boolean { 23623af6ab5fSopenharmony_ci if (ts.isIdentifier(ident1) && ts.isPrivateIdentifier(ident2)) { 23633af6ab5fSopenharmony_ci return ident1.text === ident2.text.substring(1); 23643af6ab5fSopenharmony_ci } 23653af6ab5fSopenharmony_ci if (ts.isIdentifier(ident2) && ts.isPrivateIdentifier(ident1)) { 23663af6ab5fSopenharmony_ci return ident2.text === ident1.text.substring(1); 23673af6ab5fSopenharmony_ci } 23683af6ab5fSopenharmony_ci if ( 23693af6ab5fSopenharmony_ci this.isFromPrivateIdentifierOrSdk(isFromPrivateIdentifier) && 23703af6ab5fSopenharmony_ci ts.isPrivateIdentifier(ident1) && 23713af6ab5fSopenharmony_ci ts.isPrivateIdentifier(ident2) 23723af6ab5fSopenharmony_ci ) { 23733af6ab5fSopenharmony_ci return ident1.text.substring(1) === ident2.text.substring(1); 23743af6ab5fSopenharmony_ci } 23753af6ab5fSopenharmony_ci return false; 23763af6ab5fSopenharmony_ci } 23773af6ab5fSopenharmony_ci 23783af6ab5fSopenharmony_ci findIdentifierNameForSymbol(symbol: ts.Symbol): string | undefined { 23793af6ab5fSopenharmony_ci let name = TsUtils.getIdentifierNameFromString(symbol.name); 23803af6ab5fSopenharmony_ci if (name === undefined || name === symbol.name) { 23813af6ab5fSopenharmony_ci return name; 23823af6ab5fSopenharmony_ci } 23833af6ab5fSopenharmony_ci 23843af6ab5fSopenharmony_ci const parentType = this.getTypeByProperty(symbol); 23853af6ab5fSopenharmony_ci if (parentType === undefined) { 23863af6ab5fSopenharmony_ci return undefined; 23873af6ab5fSopenharmony_ci } 23883af6ab5fSopenharmony_ci 23893af6ab5fSopenharmony_ci while (this.findProperty(parentType, name) !== undefined) { 23903af6ab5fSopenharmony_ci name = '_' + name; 23913af6ab5fSopenharmony_ci } 23923af6ab5fSopenharmony_ci 23933af6ab5fSopenharmony_ci return name; 23943af6ab5fSopenharmony_ci } 23953af6ab5fSopenharmony_ci 23963af6ab5fSopenharmony_ci private static getIdentifierNameFromString(str: string): string | undefined { 23973af6ab5fSopenharmony_ci let result: string = ''; 23983af6ab5fSopenharmony_ci 23993af6ab5fSopenharmony_ci let offset = 0; 24003af6ab5fSopenharmony_ci while (offset < str.length) { 24013af6ab5fSopenharmony_ci const codePoint = str.codePointAt(offset); 24023af6ab5fSopenharmony_ci if (!codePoint) { 24033af6ab5fSopenharmony_ci return undefined; 24043af6ab5fSopenharmony_ci } 24053af6ab5fSopenharmony_ci 24063af6ab5fSopenharmony_ci const charSize = TsUtils.charSize(codePoint); 24073af6ab5fSopenharmony_ci 24083af6ab5fSopenharmony_ci if (offset === 0 && !ts.isIdentifierStart(codePoint, undefined)) { 24093af6ab5fSopenharmony_ci result = '__'; 24103af6ab5fSopenharmony_ci } 24113af6ab5fSopenharmony_ci 24123af6ab5fSopenharmony_ci if (!ts.isIdentifierPart(codePoint, undefined)) { 24133af6ab5fSopenharmony_ci if (codePoint === 0x20) { 24143af6ab5fSopenharmony_ci result += '_'; 24153af6ab5fSopenharmony_ci } else { 24163af6ab5fSopenharmony_ci result += 'x' + codePoint.toString(16); 24173af6ab5fSopenharmony_ci } 24183af6ab5fSopenharmony_ci } else { 24193af6ab5fSopenharmony_ci for (let i = 0; i < charSize; i++) { 24203af6ab5fSopenharmony_ci result += str.charAt(offset + i); 24213af6ab5fSopenharmony_ci } 24223af6ab5fSopenharmony_ci } 24233af6ab5fSopenharmony_ci 24243af6ab5fSopenharmony_ci offset += charSize; 24253af6ab5fSopenharmony_ci } 24263af6ab5fSopenharmony_ci 24273af6ab5fSopenharmony_ci return result; 24283af6ab5fSopenharmony_ci } 24293af6ab5fSopenharmony_ci 24303af6ab5fSopenharmony_ci private static charSize(codePoint: number): number { 24313af6ab5fSopenharmony_ci return codePoint >= 0x10000 ? 2 : 1; 24323af6ab5fSopenharmony_ci } 24333af6ab5fSopenharmony_ci 24343af6ab5fSopenharmony_ci private getTypeByProperty(symbol: ts.Symbol): ts.Type | undefined { 24353af6ab5fSopenharmony_ci if (symbol.declarations === undefined) { 24363af6ab5fSopenharmony_ci return undefined; 24373af6ab5fSopenharmony_ci } 24383af6ab5fSopenharmony_ci 24393af6ab5fSopenharmony_ci for (const propDecl of symbol.declarations) { 24403af6ab5fSopenharmony_ci if ( 24413af6ab5fSopenharmony_ci !ts.isPropertyDeclaration(propDecl) && 24423af6ab5fSopenharmony_ci !ts.isPropertyAssignment(propDecl) && 24433af6ab5fSopenharmony_ci !ts.isPropertySignature(propDecl) 24443af6ab5fSopenharmony_ci ) { 24453af6ab5fSopenharmony_ci return undefined; 24463af6ab5fSopenharmony_ci } 24473af6ab5fSopenharmony_ci 24483af6ab5fSopenharmony_ci const type = this.tsTypeChecker.getTypeAtLocation(propDecl.parent); 24493af6ab5fSopenharmony_ci if (type !== undefined) { 24503af6ab5fSopenharmony_ci return type; 24513af6ab5fSopenharmony_ci } 24523af6ab5fSopenharmony_ci } 24533af6ab5fSopenharmony_ci 24543af6ab5fSopenharmony_ci return undefined; 24553af6ab5fSopenharmony_ci } 24563af6ab5fSopenharmony_ci 24573af6ab5fSopenharmony_ci static isPropertyOfInternalClassOrInterface(symbol: ts.Symbol): boolean { 24583af6ab5fSopenharmony_ci if (symbol.declarations === undefined) { 24593af6ab5fSopenharmony_ci return false; 24603af6ab5fSopenharmony_ci } 24613af6ab5fSopenharmony_ci 24623af6ab5fSopenharmony_ci for (const propDecl of symbol.declarations) { 24633af6ab5fSopenharmony_ci if (!ts.isPropertyDeclaration(propDecl) && !ts.isPropertySignature(propDecl)) { 24643af6ab5fSopenharmony_ci return false; 24653af6ab5fSopenharmony_ci } 24663af6ab5fSopenharmony_ci 24673af6ab5fSopenharmony_ci if (!ts.isClassDeclaration(propDecl.parent) && !ts.isInterfaceDeclaration(propDecl.parent)) { 24683af6ab5fSopenharmony_ci return false; 24693af6ab5fSopenharmony_ci } 24703af6ab5fSopenharmony_ci 24713af6ab5fSopenharmony_ci if (TsUtils.hasModifier(ts.getModifiers(propDecl.parent), ts.SyntaxKind.ExportKeyword)) { 24723af6ab5fSopenharmony_ci return false; 24733af6ab5fSopenharmony_ci } 24743af6ab5fSopenharmony_ci } 24753af6ab5fSopenharmony_ci 24763af6ab5fSopenharmony_ci return true; 24773af6ab5fSopenharmony_ci } 24783af6ab5fSopenharmony_ci 24793af6ab5fSopenharmony_ci static isIntrinsicObjectType(type: ts.Type): boolean { 24803af6ab5fSopenharmony_ci return !!(type.flags & ts.TypeFlags.NonPrimitive); 24813af6ab5fSopenharmony_ci } 24823af6ab5fSopenharmony_ci 24833af6ab5fSopenharmony_ci isStringType(tsType: ts.Type): boolean { 24843af6ab5fSopenharmony_ci if ((tsType.getFlags() & ts.TypeFlags.String) !== 0) { 24853af6ab5fSopenharmony_ci return true; 24863af6ab5fSopenharmony_ci } 24873af6ab5fSopenharmony_ci 24883af6ab5fSopenharmony_ci if (!TsUtils.isTypeReference(tsType)) { 24893af6ab5fSopenharmony_ci return false; 24903af6ab5fSopenharmony_ci } 24913af6ab5fSopenharmony_ci 24923af6ab5fSopenharmony_ci const symbol = tsType.symbol; 24933af6ab5fSopenharmony_ci const name = this.tsTypeChecker.getFullyQualifiedName(symbol); 24943af6ab5fSopenharmony_ci return name === 'String' && this.isGlobalSymbol(symbol); 24953af6ab5fSopenharmony_ci } 24963af6ab5fSopenharmony_ci 24973af6ab5fSopenharmony_ci isStdMapType(type: ts.Type): boolean { 24983af6ab5fSopenharmony_ci const sym = type.symbol; 24993af6ab5fSopenharmony_ci return !!sym && sym.getName() === 'Map' && this.isGlobalSymbol(sym); 25003af6ab5fSopenharmony_ci } 25013af6ab5fSopenharmony_ci 25023af6ab5fSopenharmony_ci hasGenericTypeParameter(type: ts.Type): boolean { 25033af6ab5fSopenharmony_ci if (type.isUnionOrIntersection()) { 25043af6ab5fSopenharmony_ci return type.types.some((x) => { 25053af6ab5fSopenharmony_ci return this.hasGenericTypeParameter(x); 25063af6ab5fSopenharmony_ci }); 25073af6ab5fSopenharmony_ci } 25083af6ab5fSopenharmony_ci if (TsUtils.isTypeReference(type)) { 25093af6ab5fSopenharmony_ci const typeArgs = this.tsTypeChecker.getTypeArguments(type); 25103af6ab5fSopenharmony_ci return typeArgs.some((x) => { 25113af6ab5fSopenharmony_ci return this.hasGenericTypeParameter(x); 25123af6ab5fSopenharmony_ci }); 25133af6ab5fSopenharmony_ci } 25143af6ab5fSopenharmony_ci return type.isTypeParameter(); 25153af6ab5fSopenharmony_ci } 25163af6ab5fSopenharmony_ci 25173af6ab5fSopenharmony_ci static getEnclosingTopLevelStatement(node: ts.Node): ts.Node | undefined { 25183af6ab5fSopenharmony_ci return ts.findAncestor(node, (ancestor) => { 25193af6ab5fSopenharmony_ci return ts.isSourceFile(ancestor.parent); 25203af6ab5fSopenharmony_ci }); 25213af6ab5fSopenharmony_ci } 25223af6ab5fSopenharmony_ci 25233af6ab5fSopenharmony_ci static isDeclarationStatement(node: ts.Node): node is ts.DeclarationStatement { 25243af6ab5fSopenharmony_ci const kind = node.kind; 25253af6ab5fSopenharmony_ci return ( 25263af6ab5fSopenharmony_ci kind === ts.SyntaxKind.FunctionDeclaration || 25273af6ab5fSopenharmony_ci kind === ts.SyntaxKind.ModuleDeclaration || 25283af6ab5fSopenharmony_ci kind === ts.SyntaxKind.ClassDeclaration || 25293af6ab5fSopenharmony_ci kind === ts.SyntaxKind.StructDeclaration || 25303af6ab5fSopenharmony_ci kind === ts.SyntaxKind.TypeAliasDeclaration || 25313af6ab5fSopenharmony_ci kind === ts.SyntaxKind.InterfaceDeclaration || 25323af6ab5fSopenharmony_ci kind === ts.SyntaxKind.EnumDeclaration || 25333af6ab5fSopenharmony_ci kind === ts.SyntaxKind.MissingDeclaration || 25343af6ab5fSopenharmony_ci kind === ts.SyntaxKind.ImportEqualsDeclaration || 25353af6ab5fSopenharmony_ci kind === ts.SyntaxKind.ImportDeclaration || 25363af6ab5fSopenharmony_ci kind === ts.SyntaxKind.NamespaceExportDeclaration 25373af6ab5fSopenharmony_ci ); 25383af6ab5fSopenharmony_ci } 25393af6ab5fSopenharmony_ci 25403af6ab5fSopenharmony_ci static declarationNameExists(srcFile: ts.SourceFile, name: string): boolean { 25413af6ab5fSopenharmony_ci return srcFile.statements.some((stmt) => { 25423af6ab5fSopenharmony_ci if (!ts.isImportDeclaration(stmt)) { 25433af6ab5fSopenharmony_ci return ( 25443af6ab5fSopenharmony_ci TsUtils.isDeclarationStatement(stmt) && 25453af6ab5fSopenharmony_ci stmt.name !== undefined && 25463af6ab5fSopenharmony_ci ts.isIdentifier(stmt.name) && 25473af6ab5fSopenharmony_ci stmt.name.text === name 25483af6ab5fSopenharmony_ci ); 25493af6ab5fSopenharmony_ci } 25503af6ab5fSopenharmony_ci 25513af6ab5fSopenharmony_ci if (!stmt.importClause) { 25523af6ab5fSopenharmony_ci return false; 25533af6ab5fSopenharmony_ci } 25543af6ab5fSopenharmony_ci 25553af6ab5fSopenharmony_ci if (!stmt.importClause.namedBindings) { 25563af6ab5fSopenharmony_ci return stmt.importClause.name?.text === name; 25573af6ab5fSopenharmony_ci } 25583af6ab5fSopenharmony_ci 25593af6ab5fSopenharmony_ci if (ts.isNamespaceImport(stmt.importClause.namedBindings)) { 25603af6ab5fSopenharmony_ci return stmt.importClause.namedBindings.name.text === name; 25613af6ab5fSopenharmony_ci } 25623af6ab5fSopenharmony_ci return stmt.importClause.namedBindings.elements.some((x) => { 25633af6ab5fSopenharmony_ci return x.name.text === name; 25643af6ab5fSopenharmony_ci }); 25653af6ab5fSopenharmony_ci }); 25663af6ab5fSopenharmony_ci } 25673af6ab5fSopenharmony_ci 25683af6ab5fSopenharmony_ci static generateUniqueName(nameGenerator: NameGenerator, srcFile: ts.SourceFile): string | undefined { 25693af6ab5fSopenharmony_ci let newName: string | undefined; 25703af6ab5fSopenharmony_ci 25713af6ab5fSopenharmony_ci do { 25723af6ab5fSopenharmony_ci newName = nameGenerator.getName(); 25733af6ab5fSopenharmony_ci if (newName !== undefined && TsUtils.declarationNameExists(srcFile, newName)) { 25743af6ab5fSopenharmony_ci continue; 25753af6ab5fSopenharmony_ci } 25763af6ab5fSopenharmony_ci break; 25773af6ab5fSopenharmony_ci } while (newName !== undefined); 25783af6ab5fSopenharmony_ci 25793af6ab5fSopenharmony_ci return newName; 25803af6ab5fSopenharmony_ci } 25813af6ab5fSopenharmony_ci 25823af6ab5fSopenharmony_ci static isSharedModule(sourceFile: ts.SourceFile): boolean { 25833af6ab5fSopenharmony_ci const statements = sourceFile.statements; 25843af6ab5fSopenharmony_ci for (const statement of statements) { 25853af6ab5fSopenharmony_ci if (ts.isImportDeclaration(statement)) { 25863af6ab5fSopenharmony_ci continue; 25873af6ab5fSopenharmony_ci } 25883af6ab5fSopenharmony_ci 25893af6ab5fSopenharmony_ci return ( 25903af6ab5fSopenharmony_ci ts.isExpressionStatement(statement) && 25913af6ab5fSopenharmony_ci ts.isStringLiteral(statement.expression) && 25923af6ab5fSopenharmony_ci statement.expression.text === USE_SHARED 25933af6ab5fSopenharmony_ci ); 25943af6ab5fSopenharmony_ci } 25953af6ab5fSopenharmony_ci return false; 25963af6ab5fSopenharmony_ci } 25973af6ab5fSopenharmony_ci 25983af6ab5fSopenharmony_ci getDeclarationNode(node: ts.Node): ts.Declaration | undefined { 25993af6ab5fSopenharmony_ci const sym = this.trueSymbolAtLocation(node); 26003af6ab5fSopenharmony_ci return TsUtils.getDeclaration(sym); 26013af6ab5fSopenharmony_ci } 26023af6ab5fSopenharmony_ci 26033af6ab5fSopenharmony_ci static isFunctionLikeDeclaration(node: ts.Declaration): boolean { 26043af6ab5fSopenharmony_ci return ( 26053af6ab5fSopenharmony_ci ts.isFunctionDeclaration(node) || 26063af6ab5fSopenharmony_ci ts.isMethodDeclaration(node) || 26073af6ab5fSopenharmony_ci ts.isGetAccessorDeclaration(node) || 26083af6ab5fSopenharmony_ci ts.isSetAccessorDeclaration(node) || 26093af6ab5fSopenharmony_ci ts.isConstructorDeclaration(node) || 26103af6ab5fSopenharmony_ci ts.isFunctionExpression(node) || 26113af6ab5fSopenharmony_ci ts.isArrowFunction(node) 26123af6ab5fSopenharmony_ci ); 26133af6ab5fSopenharmony_ci } 26143af6ab5fSopenharmony_ci 26153af6ab5fSopenharmony_ci isShareableEntity(node: ts.Node): boolean { 26163af6ab5fSopenharmony_ci const decl = this.getDeclarationNode(node); 26173af6ab5fSopenharmony_ci const typeNode = (decl as any)?.type; 26183af6ab5fSopenharmony_ci return typeNode && !TsUtils.isFunctionLikeDeclaration(decl!) ? 26193af6ab5fSopenharmony_ci this.isSendableTypeNode(typeNode, true) : 26203af6ab5fSopenharmony_ci this.isShareableType(this.tsTypeChecker.getTypeAtLocation(decl ? decl : node)); 26213af6ab5fSopenharmony_ci } 26223af6ab5fSopenharmony_ci 26233af6ab5fSopenharmony_ci isSendableClassOrInterfaceEntity(node: ts.Node): boolean { 26243af6ab5fSopenharmony_ci const decl = this.getDeclarationNode(node); 26253af6ab5fSopenharmony_ci if (!decl) { 26263af6ab5fSopenharmony_ci return false; 26273af6ab5fSopenharmony_ci } 26283af6ab5fSopenharmony_ci if (ts.isClassDeclaration(decl)) { 26293af6ab5fSopenharmony_ci return TsUtils.hasSendableDecorator(decl); 26303af6ab5fSopenharmony_ci } 26313af6ab5fSopenharmony_ci if (ts.isInterfaceDeclaration(decl)) { 26323af6ab5fSopenharmony_ci return this.isOrDerivedFrom(this.tsTypeChecker.getTypeAtLocation(decl), TsUtils.isISendableInterface); 26333af6ab5fSopenharmony_ci } 26343af6ab5fSopenharmony_ci return false; 26353af6ab5fSopenharmony_ci } 26363af6ab5fSopenharmony_ci 26373af6ab5fSopenharmony_ci static isInImportWhiteList(resolvedModule: ts.ResolvedModuleFull): boolean { 26383af6ab5fSopenharmony_ci if ( 26393af6ab5fSopenharmony_ci !resolvedModule.resolvedFileName || 26403af6ab5fSopenharmony_ci path.basename(resolvedModule.resolvedFileName).toLowerCase() !== ARKTS_LANG_D_ETS && 26413af6ab5fSopenharmony_ci path.basename(resolvedModule.resolvedFileName).toLowerCase() !== ARKTS_COLLECTIONS_D_ETS 26423af6ab5fSopenharmony_ci ) { 26433af6ab5fSopenharmony_ci return false; 26443af6ab5fSopenharmony_ci } 26453af6ab5fSopenharmony_ci return true; 26463af6ab5fSopenharmony_ci } 26473af6ab5fSopenharmony_ci 26483af6ab5fSopenharmony_ci // If it is an overloaded function, all declarations for that function are found 26493af6ab5fSopenharmony_ci static hasSendableDecoratorFunctionOverload(decl: ts.FunctionDeclaration): boolean { 26503af6ab5fSopenharmony_ci const decorators = TsUtils.getFunctionOverloadDecorators(decl); 26513af6ab5fSopenharmony_ci return !!decorators?.some((x) => { 26523af6ab5fSopenharmony_ci return TsUtils.getDecoratorName(x) === SENDABLE_DECORATOR; 26533af6ab5fSopenharmony_ci }); 26543af6ab5fSopenharmony_ci } 26553af6ab5fSopenharmony_ci 26563af6ab5fSopenharmony_ci static getFunctionOverloadDecorators(funcDecl: ts.FunctionDeclaration): readonly ts.Decorator[] | undefined { 26573af6ab5fSopenharmony_ci const decls = funcDecl.symbol.getDeclarations(); 26583af6ab5fSopenharmony_ci if (!decls?.length) { 26593af6ab5fSopenharmony_ci return undefined; 26603af6ab5fSopenharmony_ci } 26613af6ab5fSopenharmony_ci let result: ts.Decorator[] = []; 26623af6ab5fSopenharmony_ci decls.forEach((decl) => { 26633af6ab5fSopenharmony_ci if (!ts.isFunctionDeclaration(decl)) { 26643af6ab5fSopenharmony_ci return; 26653af6ab5fSopenharmony_ci } 26663af6ab5fSopenharmony_ci const decorators = ts.getAllDecorators(decl); 26673af6ab5fSopenharmony_ci if (decorators?.length) { 26683af6ab5fSopenharmony_ci result = result.concat(decorators); 26693af6ab5fSopenharmony_ci } 26703af6ab5fSopenharmony_ci }); 26713af6ab5fSopenharmony_ci return result.length ? result : undefined; 26723af6ab5fSopenharmony_ci } 26733af6ab5fSopenharmony_ci 26743af6ab5fSopenharmony_ci static isSendableFunction(type: ts.Type): boolean { 26753af6ab5fSopenharmony_ci const callSigns = type.getCallSignatures(); 26763af6ab5fSopenharmony_ci if (!callSigns?.length) { 26773af6ab5fSopenharmony_ci return false; 26783af6ab5fSopenharmony_ci } 26793af6ab5fSopenharmony_ci const decl = callSigns[0].declaration; 26803af6ab5fSopenharmony_ci if (!decl || !ts.isFunctionDeclaration(decl)) { 26813af6ab5fSopenharmony_ci return false; 26823af6ab5fSopenharmony_ci } 26833af6ab5fSopenharmony_ci return TsUtils.hasSendableDecoratorFunctionOverload(decl); 26843af6ab5fSopenharmony_ci } 26853af6ab5fSopenharmony_ci 26863af6ab5fSopenharmony_ci isSendableTypeAlias(type: ts.Type): boolean { 26873af6ab5fSopenharmony_ci const decl = this.getTypsAliasOriginalDecl(type); 26883af6ab5fSopenharmony_ci return !!decl && TsUtils.hasSendableDecorator(decl); 26893af6ab5fSopenharmony_ci } 26903af6ab5fSopenharmony_ci 26913af6ab5fSopenharmony_ci hasSendableTypeAlias(type: ts.Type): boolean { 26923af6ab5fSopenharmony_ci if (type.isUnion()) { 26933af6ab5fSopenharmony_ci return type.types.some((compType) => { 26943af6ab5fSopenharmony_ci return this.hasSendableTypeAlias(compType); 26953af6ab5fSopenharmony_ci }); 26963af6ab5fSopenharmony_ci } 26973af6ab5fSopenharmony_ci return this.isSendableTypeAlias(type); 26983af6ab5fSopenharmony_ci } 26993af6ab5fSopenharmony_ci 27003af6ab5fSopenharmony_ci isNonSendableFunctionTypeAlias(type: ts.Type): boolean { 27013af6ab5fSopenharmony_ci const decl = this.getTypsAliasOriginalDecl(type); 27023af6ab5fSopenharmony_ci return !!decl && ts.isFunctionTypeNode(decl.type) && !TsUtils.hasSendableDecorator(decl); 27033af6ab5fSopenharmony_ci } 27043af6ab5fSopenharmony_ci 27053af6ab5fSopenharmony_ci // If the alias refers to another alias, the search continues 27063af6ab5fSopenharmony_ci private getTypsAliasOriginalDecl(type: ts.Type): ts.TypeAliasDeclaration | undefined { 27073af6ab5fSopenharmony_ci if (!type.aliasSymbol) { 27083af6ab5fSopenharmony_ci return undefined; 27093af6ab5fSopenharmony_ci } 27103af6ab5fSopenharmony_ci const decl = TsUtils.getDeclaration(type.aliasSymbol); 27113af6ab5fSopenharmony_ci if (!decl || !ts.isTypeAliasDeclaration(decl)) { 27123af6ab5fSopenharmony_ci return undefined; 27133af6ab5fSopenharmony_ci } 27143af6ab5fSopenharmony_ci if (ts.isTypeReferenceNode(decl.type)) { 27153af6ab5fSopenharmony_ci const targetType = this.tsTypeChecker.getTypeAtLocation(decl.type.typeName); 27163af6ab5fSopenharmony_ci if (targetType.aliasSymbol && targetType.aliasSymbol.getFlags() & ts.SymbolFlags.TypeAlias) { 27173af6ab5fSopenharmony_ci return this.getTypsAliasOriginalDecl(targetType); 27183af6ab5fSopenharmony_ci } 27193af6ab5fSopenharmony_ci } 27203af6ab5fSopenharmony_ci return decl; 27213af6ab5fSopenharmony_ci } 27223af6ab5fSopenharmony_ci 27233af6ab5fSopenharmony_ci // not allow 'lhsType' contains 'sendable typeAlias' && 'rhsType' contains 'non-sendable function/non-sendable function typeAlias' 27243af6ab5fSopenharmony_ci isWrongSendableFunctionAssignment(lhsType: ts.Type, rhsType: ts.Type): boolean { 27253af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 27263af6ab5fSopenharmony_ci lhsType = this.getNonNullableType(lhsType); 27273af6ab5fSopenharmony_ci // eslint-disable-next-line no-param-reassign 27283af6ab5fSopenharmony_ci rhsType = this.getNonNullableType(rhsType); 27293af6ab5fSopenharmony_ci if (!this.hasSendableTypeAlias(lhsType)) { 27303af6ab5fSopenharmony_ci return false; 27313af6ab5fSopenharmony_ci } 27323af6ab5fSopenharmony_ci 27333af6ab5fSopenharmony_ci if (rhsType.isUnion()) { 27343af6ab5fSopenharmony_ci return rhsType.types.some((compType) => { 27353af6ab5fSopenharmony_ci return this.isInvalidSendableFunctionAssignmentType(compType); 27363af6ab5fSopenharmony_ci }); 27373af6ab5fSopenharmony_ci } 27383af6ab5fSopenharmony_ci return this.isInvalidSendableFunctionAssignmentType(rhsType); 27393af6ab5fSopenharmony_ci } 27403af6ab5fSopenharmony_ci 27413af6ab5fSopenharmony_ci private isInvalidSendableFunctionAssignmentType(type: ts.Type): boolean { 27423af6ab5fSopenharmony_ci if (type.aliasSymbol) { 27433af6ab5fSopenharmony_ci return this.isNonSendableFunctionTypeAlias(type); 27443af6ab5fSopenharmony_ci } 27453af6ab5fSopenharmony_ci if (TsUtils.isFunctionalType(type)) { 27463af6ab5fSopenharmony_ci return !TsUtils.isSendableFunction(type); 27473af6ab5fSopenharmony_ci } 27483af6ab5fSopenharmony_ci return false; 27493af6ab5fSopenharmony_ci } 27503af6ab5fSopenharmony_ci 27513af6ab5fSopenharmony_ci static isSetExpression(accessExpr: ts.ElementAccessExpression): boolean { 27523af6ab5fSopenharmony_ci if (!ts.isBinaryExpression(accessExpr.parent)) { 27533af6ab5fSopenharmony_ci return false; 27543af6ab5fSopenharmony_ci } 27553af6ab5fSopenharmony_ci const binaryExpr = accessExpr.parent; 27563af6ab5fSopenharmony_ci return binaryExpr.operatorToken.kind === ts.SyntaxKind.EqualsToken && binaryExpr.left === accessExpr; 27573af6ab5fSopenharmony_ci } 27583af6ab5fSopenharmony_ci 27593af6ab5fSopenharmony_ci haveSameBaseType(type1: ts.Type, type2: ts.Type): boolean { 27603af6ab5fSopenharmony_ci return this.tsTypeChecker.getBaseTypeOfLiteralType(type1) === this.tsTypeChecker.getBaseTypeOfLiteralType(type2); 27613af6ab5fSopenharmony_ci } 27623af6ab5fSopenharmony_ci 27633af6ab5fSopenharmony_ci isGetIndexableType(type: ts.Type, indexType: ts.Type): boolean { 27643af6ab5fSopenharmony_ci const getDecls = type.getProperty('$_get')?.getDeclarations(); 27653af6ab5fSopenharmony_ci if (getDecls?.length !== 1 || getDecls[0].kind !== ts.SyntaxKind.MethodDeclaration) { 27663af6ab5fSopenharmony_ci return false; 27673af6ab5fSopenharmony_ci } 27683af6ab5fSopenharmony_ci const getMethodDecl = getDecls[0] as ts.MethodDeclaration; 27693af6ab5fSopenharmony_ci const getParams = getMethodDecl.parameters; 27703af6ab5fSopenharmony_ci if (getMethodDecl.type === undefined || getParams.length !== 1 || getParams[0].type === undefined) { 27713af6ab5fSopenharmony_ci return false; 27723af6ab5fSopenharmony_ci } 27733af6ab5fSopenharmony_ci 27743af6ab5fSopenharmony_ci return this.haveSameBaseType(this.tsTypeChecker.getTypeFromTypeNode(getParams[0].type), indexType); 27753af6ab5fSopenharmony_ci } 27763af6ab5fSopenharmony_ci 27773af6ab5fSopenharmony_ci isSetIndexableType(type: ts.Type, indexType: ts.Type, valueType: ts.Type): boolean { 27783af6ab5fSopenharmony_ci const setProp = type.getProperty('$_set'); 27793af6ab5fSopenharmony_ci const setDecls = setProp?.getDeclarations(); 27803af6ab5fSopenharmony_ci if (setDecls?.length !== 1 || setDecls[0].kind !== ts.SyntaxKind.MethodDeclaration) { 27813af6ab5fSopenharmony_ci return false; 27823af6ab5fSopenharmony_ci } 27833af6ab5fSopenharmony_ci const setMethodDecl = setDecls[0] as ts.MethodDeclaration; 27843af6ab5fSopenharmony_ci const setParams = setMethodDecl.parameters; 27853af6ab5fSopenharmony_ci if ( 27863af6ab5fSopenharmony_ci setMethodDecl.type !== undefined || 27873af6ab5fSopenharmony_ci setParams.length !== 2 || 27883af6ab5fSopenharmony_ci setParams[0].type === undefined || 27893af6ab5fSopenharmony_ci setParams[1].type === undefined 27903af6ab5fSopenharmony_ci ) { 27913af6ab5fSopenharmony_ci return false; 27923af6ab5fSopenharmony_ci } 27933af6ab5fSopenharmony_ci 27943af6ab5fSopenharmony_ci return ( 27953af6ab5fSopenharmony_ci this.haveSameBaseType(this.tsTypeChecker.getTypeFromTypeNode(setParams[0].type), indexType) && 27963af6ab5fSopenharmony_ci this.haveSameBaseType(this.tsTypeChecker.getTypeFromTypeNode(setParams[1].type), valueType) 27973af6ab5fSopenharmony_ci ); 27983af6ab5fSopenharmony_ci } 27993af6ab5fSopenharmony_ci 28003af6ab5fSopenharmony_ci // Search for and save the exported declaration in the specified file, re-exporting another module will not be included. 28013af6ab5fSopenharmony_ci searchFileExportDecl(sourceFile: ts.SourceFile, targetDecls?: ts.SyntaxKind[]): Set<ts.Node> { 28023af6ab5fSopenharmony_ci const exportDeclSet = new Set<ts.Node>(); 28033af6ab5fSopenharmony_ci const appendDecl = (decl: ts.Node | undefined): void => { 28043af6ab5fSopenharmony_ci if (!decl || targetDecls && !targetDecls.includes(decl.kind)) { 28053af6ab5fSopenharmony_ci return; 28063af6ab5fSopenharmony_ci } 28073af6ab5fSopenharmony_ci exportDeclSet.add(decl); 28083af6ab5fSopenharmony_ci }; 28093af6ab5fSopenharmony_ci 28103af6ab5fSopenharmony_ci sourceFile.statements.forEach((statement: ts.Statement) => { 28113af6ab5fSopenharmony_ci if (ts.isExportAssignment(statement)) { 28123af6ab5fSopenharmony_ci // handle the case:"export default declName;" 28133af6ab5fSopenharmony_ci if (statement.isExportEquals) { 28143af6ab5fSopenharmony_ci return; 28153af6ab5fSopenharmony_ci } 28163af6ab5fSopenharmony_ci appendDecl(this.getDeclarationNode(statement.expression)); 28173af6ab5fSopenharmony_ci } else if (ts.isExportDeclaration(statement)) { 28183af6ab5fSopenharmony_ci // handle the case:"export { declName1, declName2 };" 28193af6ab5fSopenharmony_ci if (!statement.exportClause || !ts.isNamedExports(statement.exportClause)) { 28203af6ab5fSopenharmony_ci return; 28213af6ab5fSopenharmony_ci } 28223af6ab5fSopenharmony_ci statement.exportClause.elements.forEach((specifier) => { 28233af6ab5fSopenharmony_ci appendDecl(this.getDeclarationNode(specifier.propertyName ?? specifier.name)); 28243af6ab5fSopenharmony_ci }); 28253af6ab5fSopenharmony_ci } else if (ts.canHaveModifiers(statement)) { 28263af6ab5fSopenharmony_ci // handle the case:"export const/class/function... decalName;" 28273af6ab5fSopenharmony_ci if (!TsUtils.hasModifier(ts.getModifiers(statement), ts.SyntaxKind.ExportKeyword)) { 28283af6ab5fSopenharmony_ci return; 28293af6ab5fSopenharmony_ci } 28303af6ab5fSopenharmony_ci if (!ts.isVariableStatement(statement)) { 28313af6ab5fSopenharmony_ci appendDecl(statement); 28323af6ab5fSopenharmony_ci return; 28333af6ab5fSopenharmony_ci } 28343af6ab5fSopenharmony_ci for (const exportDecl of statement.declarationList.declarations) { 28353af6ab5fSopenharmony_ci appendDecl(exportDecl); 28363af6ab5fSopenharmony_ci } 28373af6ab5fSopenharmony_ci } 28383af6ab5fSopenharmony_ci }); 28393af6ab5fSopenharmony_ci return exportDeclSet; 28403af6ab5fSopenharmony_ci } 28413af6ab5fSopenharmony_ci 28423af6ab5fSopenharmony_ci static isAmbientNode(node: ts.Node): boolean { 28433af6ab5fSopenharmony_ci // Ambient flag is not exposed, so we apply dirty hack to make it visible 28443af6ab5fSopenharmony_ci return !!(node.flags & (ts.NodeFlags as any).Ambient); 28453af6ab5fSopenharmony_ci } 28463af6ab5fSopenharmony_ci} 2847