1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import ts from 'typescript'; 17import fs from 'fs'; 18import path from 'path'; 19import JSON5 from 'json5'; 20 21import { 22 EXTNAME_ETS, 23 EXTNAME_TS, 24 INDEX_ETS, 25 INDEX_TS, 26 CUSTOM_COMPONENT_DEFAULT, 27 CUSTOM_DECORATOR_NAME, 28 COMPONENT_DECORATOR_ENTRY, 29 COMPONENT_BUILDER_DECORATOR, 30 DECORATOR_REUSEABLE, 31 DECORATOR_REUSABLE_V2 32} from './pre_define'; 33import { 34 propertyCollection, 35 linkCollection, 36 componentCollection, 37 preprocessExtend, 38 preprocessNewExtend, 39 processSystemApi, 40 propCollection, 41 isObservedClass, 42 isCustomDialogClass, 43 observedClassCollection, 44 enumCollection, 45 getComponentSet, 46 IComponentSet, 47 builderParamObjectCollection, 48 stateCollection, 49 regularCollection, 50 storagePropCollection, 51 storageLinkCollection, 52 provideCollection, 53 consumeCollection, 54 objectLinkCollection, 55 localStorageLinkCollection, 56 localStoragePropCollection, 57 builderParamInitialization, 58 propInitialization, 59 regularInitialization, 60 stateInitialization, 61 provideInitialization, 62 privateCollection, 63 regularStaticCollection 64} from './validate_ui_syntax'; 65import { 66 getExtensionIfUnfullySpecifiedFilepath, 67 hasDecorator, 68 LogInfo, 69 LogType, 70 storedFileInfo 71} from './utils'; 72import { 73 projectConfig, 74 sdkConfigs, 75 sdkConfigPrefix, 76 globalProgram 77} from '../main'; 78import { 79 CUSTOM_BUILDER_METHOD, 80 INNER_COMPONENT_NAMES, 81 GLOBAL_CUSTOM_BUILDER_METHOD 82} from './component_map'; 83import { 84 type ResolveModuleInfo, 85 SOURCE_FILES 86} from './ets_checker'; 87import { 88 getRealModulePath, 89 validateModuleSpecifier 90} from './fast_build/system_api/api_check_utils'; 91import processStructComponentV2, { StructInfo } from './process_struct_componentV2'; 92 93const IMPORT_FILE_ASTCACHE: Map<string, ts.SourceFile> = 94 process.env.watchMode === 'true' ? new Map() : (SOURCE_FILES || new Map()); 95 96export default function processImport(node: ts.ImportDeclaration | ts.ImportEqualsDeclaration | 97 ts.ExportDeclaration, pagesDir: string, log: LogInfo[], asName: Map<string, string> = new Map(), 98 isEntryPage: boolean = true, pathCollection: Set<string> = new Set()): void { 99 let filePath: string; 100 let defaultName: string; 101 if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) { 102 filePath = node.moduleSpecifier.getText().replace(/'|"/g, ''); 103 if (ts.isImportDeclaration(node) && node.importClause && node.importClause.name && 104 ts.isIdentifier(node.importClause.name)) { 105 defaultName = node.importClause.name.escapedText.toString(); 106 if (isEntryPage) { 107 asName.set(defaultName, defaultName); 108 } 109 } 110 if (ts.isImportDeclaration(node) && node.importClause && node.importClause.namedBindings && 111 ts.isNamedImports(node.importClause.namedBindings) && 112 node.importClause.namedBindings.elements && isEntryPage) { 113 validateModuleSpecifier(node.moduleSpecifier, log); 114 node.importClause.namedBindings.elements.forEach(item => { 115 if (item.name && ts.isIdentifier(item.name)) { 116 validateModuleName(item.name, log); 117 if (item.propertyName && ts.isIdentifier(item.propertyName) && asName) { 118 asName.set(item.propertyName.escapedText.toString(), item.name.escapedText.toString()); 119 } else { 120 asName.set(item.name.escapedText.toString(), item.name.escapedText.toString()); 121 } 122 } 123 }); 124 } 125 } else { 126 if (node.moduleReference && ts.isExternalModuleReference(node.moduleReference) && 127 node.moduleReference.expression && ts.isStringLiteral(node.moduleReference.expression)) { 128 filePath = node.moduleReference.expression.text; 129 defaultName = node.name.escapedText.toString(); 130 if (isEntryPage) { 131 asName.set(defaultName, defaultName); 132 } 133 } 134 } 135 136 try { 137 const fileResolvePath: string = getFileFullPath(filePath, pagesDir); 138 if (fs.existsSync(fileResolvePath) && fs.statSync(fileResolvePath).isFile() && 139 !pathCollection.has(fileResolvePath)) { 140 let sourceFile: ts.SourceFile; 141 pathCollection.add(fileResolvePath); 142 if (IMPORT_FILE_ASTCACHE.has(fileResolvePath)) { 143 sourceFile = IMPORT_FILE_ASTCACHE.get(fileResolvePath); 144 } else { 145 sourceFile = generateSourceFileAST(fileResolvePath, filePath); 146 IMPORT_FILE_ASTCACHE[fileResolvePath] = sourceFile; 147 } 148 visitAllNode(sourceFile, sourceFile, defaultName, asName, path.dirname(fileResolvePath), log, 149 new Set(), new Set(), new Set(), new Map(), pathCollection, fileResolvePath, /\.d\.ets$/.test(fileResolvePath)); 150 } 151 } catch (e) { 152 // ignore 153 } 154} 155 156function generateSourceFileAST(fileResolvePath: string, filePath: string): ts.SourceFile { 157 const originContent: string = fs.readFileSync(fileResolvePath, { encoding: 'utf-8' }); 158 const content: string = path.extname(fileResolvePath) === EXTNAME_ETS ? 159 preprocessNewExtend(preprocessExtend(processSystemApi(originContent))) : originContent; 160 return ts.createSourceFile(fileResolvePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.ETS); 161} 162 163type structDecoratorResult = { 164 hasRecycle: boolean 165}; 166 167const MODIFIER_LENGTH: number = 2; 168 169function visitAllNode(node: ts.Node, sourceFile: ts.SourceFile, defaultNameFromParent: string, 170 asNameFromParent: Map<string, string>, pagesDir: string, log: LogInfo[], entryCollection: Set<string>, 171 exportCollection: Set<string>, defaultCollection: Set<string>, asExportCollection: Map<string, string>, 172 pathCollection: Set<string>, fileResolvePath: string, isDETS: boolean): void { 173 if (isObservedClass(node)) { 174 collectSpecialFunctionNode(node as ts.ClassDeclaration, asNameFromParent, defaultNameFromParent, defaultCollection, 175 asExportCollection, observedClassCollection); 176 // @ts-ignore 177 observedClassCollection.add(node.name.getText()); 178 } 179 if (isCustomDialogClass(node)) { 180 collectSpecialFunctionNode(node as ts.StructDeclaration, asNameFromParent, defaultNameFromParent, defaultCollection, 181 asExportCollection, componentCollection.customDialogs); 182 // @ts-ignore 183 componentCollection.customDialogs.add(node.name.getText()); 184 } 185 if (ts.isEnumDeclaration(node) && node.name) { 186 enumCollection.add(node.name.getText()); 187 } 188 const structDecorator: structDecoratorResult = { hasRecycle: false }; 189 if (ts.isStructDeclaration(node) && ts.isIdentifier(node.name) && isCustomComponent(node, structDecorator)) { 190 addDependencies(node, defaultNameFromParent, asNameFromParent, isDETS, structDecorator); 191 isExportEntry(node, log, entryCollection, exportCollection, defaultCollection, fileResolvePath, sourceFile); 192 if (asExportCollection.has(node.name.getText())) { 193 componentCollection.customComponents.add(asExportCollection.get(node.name.getText())); 194 if (isDETS) { 195 storedFileInfo.getCurrentArkTsFile().compFromDETS.add(asExportCollection.get(node.name.getText())); 196 } 197 if (structDecorator.hasRecycle) { 198 storedFileInfo.getCurrentArkTsFile().recycleComponents.add(asExportCollection.get(node.name.getText())); 199 } 200 } 201 const modifiers: readonly ts.Modifier[] = 202 ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 203 if (modifiers && modifiers.length >= MODIFIER_LENGTH && modifiers[0] && 204 modifiers[0].kind === ts.SyntaxKind.ExportKeyword && modifiers[1] && 205 modifiers[1].kind === ts.SyntaxKind.DefaultKeyword) { 206 if (!defaultNameFromParent && hasCollection(node.name)) { 207 addDefaultExport(node, isDETS, structDecorator); 208 } else if (defaultNameFromParent && asNameFromParent.has(defaultNameFromParent)) { 209 componentCollection.customComponents.add(asNameFromParent.get(defaultNameFromParent)); 210 if (isDETS) { 211 storedFileInfo.getCurrentArkTsFile().compFromDETS.add(asNameFromParent.get(defaultNameFromParent)); 212 } 213 if (structDecorator.hasRecycle) { 214 storedFileInfo.getCurrentArkTsFile().recycleComponents.add(asNameFromParent.get(defaultNameFromParent)); 215 } 216 } 217 } 218 if (defaultCollection.has(node.name.getText())) { 219 componentCollection.customComponents.add(CUSTOM_COMPONENT_DEFAULT); 220 if (isDETS) { 221 storedFileInfo.getCurrentArkTsFile().compFromDETS.add(CUSTOM_COMPONENT_DEFAULT); 222 } 223 if (structDecorator.hasRecycle) { 224 storedFileInfo.getCurrentArkTsFile().recycleComponents.add(CUSTOM_COMPONENT_DEFAULT); 225 } 226 } 227 } 228 if (ts.isFunctionDeclaration(node) && hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) { 229 collectSpecialFunctionNode(node, asNameFromParent, defaultNameFromParent, defaultCollection, 230 asExportCollection, CUSTOM_BUILDER_METHOD); 231 collectSpecialFunctionNode(node, asNameFromParent, defaultNameFromParent, defaultCollection, 232 asExportCollection, GLOBAL_CUSTOM_BUILDER_METHOD); 233 } 234 if (ts.isExportAssignment(node) && node.expression && ts.isIdentifier(node.expression) && 235 hasCollection(node.expression)) { 236 if (defaultNameFromParent) { 237 const propertiesName: string = node.expression.escapedText.toString(); 238 setDependencies(defaultNameFromParent, undefined, linkCollection.get(propertiesName), 239 propertyCollection.get(propertiesName), propCollection.get(propertiesName), 240 builderParamObjectCollection.get(propertiesName), stateCollection.get(propertiesName), 241 regularCollection.get(propertiesName), storagePropCollection.get(propertiesName), 242 storageLinkCollection.get(propertiesName), provideCollection.get(propertiesName), 243 consumeCollection.get(propertiesName), objectLinkCollection.get(propertiesName), 244 localStorageLinkCollection.get(propertiesName), localStoragePropCollection.get(propertiesName), 245 builderParamInitialization.get(propertiesName), propInitialization.get(propertiesName), isDETS, 246 structDecorator); 247 } 248 addDefaultExport(node, isDETS, structDecorator); 249 } 250 if (ts.isExportAssignment(node) && node.expression && ts.isIdentifier(node.expression)) { 251 if (defaultNameFromParent) { 252 asNameFromParent.set(node.expression.getText(), asNameFromParent.get(defaultNameFromParent)); 253 } 254 defaultCollection.add(node.expression.getText()); 255 } 256 if (ts.isExportDeclaration(node) && node.exportClause && 257 ts.isNamedExports(node.exportClause) && node.exportClause.elements) { 258 node.exportClause.elements.forEach(item => { 259 if (process.env.watchMode === 'true') { 260 exportCollection.add((item.propertyName ? item.propertyName : item.name).escapedText.toString()); 261 } 262 if (item.name && ts.isIdentifier(item.name)) { 263 if (!item.propertyName) { 264 asExportCollection.set(item.name.escapedText.toString(), item.name.escapedText.toString()); 265 } else if (item.propertyName && ts.isIdentifier(item.propertyName)) { 266 validateModuleName(item.name, log, sourceFile, fileResolvePath); 267 if (hasCollection(item.propertyName)) { 268 let asExportName: string = item.name.escapedText.toString(); 269 const asExportPropertyName: string = item.propertyName.escapedText.toString(); 270 if (asNameFromParent.has(asExportName)) { 271 asExportName = asNameFromParent.get(asExportName); 272 } 273 setDependencies(asExportName, undefined, linkCollection.get(asExportPropertyName), 274 propertyCollection.get(asExportPropertyName), 275 propCollection.get(asExportPropertyName), 276 builderParamObjectCollection.get(asExportPropertyName), 277 stateCollection.get(asExportPropertyName), regularCollection.get(asExportPropertyName), 278 storagePropCollection.get(asExportPropertyName), storageLinkCollection.get(asExportPropertyName), 279 provideCollection.get(asExportPropertyName), consumeCollection.get(asExportPropertyName), 280 objectLinkCollection.get(asExportPropertyName), localStorageLinkCollection.get(asExportPropertyName), 281 localStoragePropCollection.get(asExportPropertyName), builderParamInitialization.get(asExportPropertyName), 282 propInitialization.get(asExportPropertyName), isDETS, structDecorator); 283 } 284 asExportCollection.set(item.propertyName.escapedText.toString(), item.name.escapedText.toString()); 285 } 286 } 287 if (item.name && ts.isIdentifier(item.name) && asNameFromParent.has(item.name.escapedText.toString()) && 288 item.propertyName && ts.isIdentifier(item.propertyName)) { 289 asNameFromParent.set(item.propertyName.escapedText.toString(), 290 asNameFromParent.get(item.name.escapedText.toString())); 291 } 292 }); 293 } 294 if (ts.isExportDeclaration(node) && node.moduleSpecifier && 295 ts.isStringLiteral(node.moduleSpecifier)) { 296 if (process.env.watchMode === 'true' && node.exportClause && ts.isNamedExports(node.exportClause) && 297 node.exportClause.elements) { 298 node.exportClause.elements.forEach(item => { 299 exportCollection.add((item.propertyName ? item.propertyName : item.name).escapedText.toString()); 300 if (item.propertyName && ts.isIdentifier(item.propertyName) && item.name && 301 ts.isIdentifier(item.name) && asNameFromParent.has(item.name.escapedText.toString())) { 302 asNameFromParent.set(item.propertyName.escapedText.toString(), 303 asNameFromParent.get(item.name.escapedText.toString())); 304 defaultCollection.add(item.name.escapedText.toString()); 305 } 306 }); 307 } 308 processImport(node, pagesDir, log, asNameFromParent, true, new Set(pathCollection)); 309 } 310 if (ts.isImportDeclaration(node)) { 311 if (node.importClause && node.importClause.name && ts.isIdentifier(node.importClause.name) && 312 asNameFromParent.has(node.importClause.name.getText())) { 313 processImport(node, pagesDir, log, asNameFromParent, false, new Set(pathCollection)); 314 } else if (node.importClause && node.importClause.namedBindings && 315 ts.isNamedImports(node.importClause.namedBindings) && node.importClause.namedBindings.elements) { 316 let nested: boolean = false; 317 node.importClause.namedBindings.elements.forEach(item => { 318 if (item.name && ts.isIdentifier(item.name) && asNameFromParent.has(item.name.escapedText.toString())) { 319 nested = true; 320 if (item.propertyName && ts.isIdentifier(item.propertyName)) { 321 asNameFromParent.set(item.propertyName.escapedText.toString(), 322 asNameFromParent.get(item.name.escapedText.toString())); 323 } 324 } 325 }); 326 if (nested) { 327 processImport(node, pagesDir, log, asNameFromParent, false, new Set(pathCollection)); 328 } 329 } 330 } 331 node.getChildren().reverse().forEach((item: ts.Node) => visitAllNode(item, sourceFile, 332 defaultNameFromParent, asNameFromParent, pagesDir, log, entryCollection, exportCollection, 333 defaultCollection, asExportCollection, pathCollection, fileResolvePath, isDETS)); 334} 335 336function collectSpecialFunctionNode(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.StructDeclaration, 337 asNameFromParent: Map<string, string>, defaultNameFromParent: string, defaultCollection: Set<string>, 338 asExportCollection: Map<string, string>, collection: Set<string>): void { 339 const name: string = node.name.getText(); 340 const modifiers: readonly ts.Modifier[] = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 341 if (asNameFromParent.has(name)) { 342 collection.add(asNameFromParent.get(name)); 343 } else if (modifiers && modifiers.length >= 1 && modifiers[0] && 344 modifiers[0].kind === ts.SyntaxKind.ExportKeyword) { 345 if (modifiers.length === 1) { 346 collection.add(name); 347 } else if (modifiers.length >= MODIFIER_LENGTH && modifiers[1] && modifiers[1].kind === 348 ts.SyntaxKind.DefaultKeyword) { 349 collection.add(CUSTOM_COMPONENT_DEFAULT); 350 if (defaultNameFromParent && asNameFromParent.has(defaultNameFromParent)) { 351 collection.add(asNameFromParent.get(defaultNameFromParent)); 352 } 353 } 354 } else if (defaultCollection.has(name)) { 355 collection.add(CUSTOM_COMPONENT_DEFAULT); 356 } else if (asExportCollection.has(name)) { 357 collection.add(asExportCollection.get(name)); 358 } 359} 360 361function isExportEntry(node: ts.StructDeclaration, log: LogInfo[], entryCollection: Set<string>, 362 exportCollection: Set<string>, defaultCollection: Set<string>, fileResolvePath: string, 363 sourceFile: ts.SourceFile): void { 364 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 365 if (process.env.watchMode === 'true' && node && decorators) { 366 let existExport: boolean = false; 367 let existEntry: boolean = false; 368 const modifiers: readonly ts.Modifier[] = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 369 if (modifiers) { 370 for (let i = 0; i < modifiers.length; i++) { 371 if (modifiers[i].kind === ts.SyntaxKind.ExportKeyword) { 372 existExport = true; 373 break; 374 } 375 } 376 } 377 for (let i = 0; i < decorators.length; i++) { 378 if (decorators[i].getText() === COMPONENT_DECORATOR_ENTRY) { 379 entryCollection.add(node.name.escapedText.toString()); 380 existEntry = true; 381 break; 382 } 383 } 384 } 385} 386 387function addDependencies(node: ts.StructDeclaration, defaultNameFromParent: string, 388 asNameFromParent: Map<string, string>, isDETS: boolean, structDecorator: structDecoratorResult): void { 389 const componentName: string = node.name.getText(); 390 const ComponentSet: IComponentSet = getComponentSet(node, false); 391 const modifiers: readonly ts.Modifier[] = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 392 if (defaultNameFromParent && modifiers && modifiers.length >= MODIFIER_LENGTH && modifiers[0] && 393 modifiers[1] && modifiers[0].kind === ts.SyntaxKind.ExportKeyword && 394 modifiers[1].kind === ts.SyntaxKind.DefaultKeyword) { 395 setDependencies(defaultNameFromParent, undefined, ComponentSet.links, ComponentSet.properties, 396 ComponentSet.props, ComponentSet.builderParams, ComponentSet.states, ComponentSet.regulars, 397 ComponentSet.storageProps, ComponentSet.storageLinks, ComponentSet.provides, 398 ComponentSet.consumes, ComponentSet.objectLinks, ComponentSet.localStorageLink, 399 ComponentSet.localStorageProp, ComponentSet.builderParamData, ComponentSet.propData, isDETS, 400 structDecorator); 401 } else if (asNameFromParent.has(componentName)) { 402 setDependencies(asNameFromParent.get(componentName), undefined, ComponentSet.links, ComponentSet.properties, 403 ComponentSet.props, ComponentSet.builderParams, ComponentSet.states, ComponentSet.regulars, 404 ComponentSet.storageProps, ComponentSet.storageLinks, ComponentSet.provides, 405 ComponentSet.consumes, ComponentSet.objectLinks, ComponentSet.localStorageLink, 406 ComponentSet.localStorageProp, ComponentSet.builderParamData, ComponentSet.propData, isDETS, 407 structDecorator); 408 } else { 409 setDependencies(componentName, undefined, ComponentSet.links, ComponentSet.properties, ComponentSet.props, 410 ComponentSet.builderParams, ComponentSet.states, ComponentSet.regulars, 411 ComponentSet.storageProps, ComponentSet.storageLinks, ComponentSet.provides, 412 ComponentSet.consumes, ComponentSet.objectLinks, ComponentSet.localStorageLink, 413 ComponentSet.localStorageProp, ComponentSet.builderParamData, ComponentSet.propData, isDETS, 414 structDecorator); 415 } 416} 417 418function addDefaultExport(node: ts.StructDeclaration | ts.ExportAssignment, isDETS: boolean, 419 structDecorator: structDecoratorResult): void { 420 let name: string; 421 if (ts.isStructDeclaration(node) && node.name && ts.isIdentifier(node.name)) { 422 name = node.name.escapedText.toString(); 423 } else if (ts.isExportAssignment(node) && node.expression && ts.isIdentifier(node.expression)) { 424 name = node.expression.escapedText.toString(); 425 } else { 426 return; 427 } 428 setDependencies(CUSTOM_COMPONENT_DEFAULT, undefined, 429 linkCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 430 new Set([...linkCollection.get(CUSTOM_COMPONENT_DEFAULT), ...linkCollection.get(name)]) : 431 linkCollection.get(name), 432 propertyCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 433 new Set([...propertyCollection.get(CUSTOM_COMPONENT_DEFAULT), 434 ...propertyCollection.get(name)]) : propertyCollection.get(name), 435 propCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 436 new Set([...propCollection.get(CUSTOM_COMPONENT_DEFAULT), ...propCollection.get(name)]) : 437 propCollection.get(name), 438 builderParamObjectCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 439 new Set([...builderParamObjectCollection.get(CUSTOM_COMPONENT_DEFAULT), 440 ...builderParamObjectCollection.get(name)]) : builderParamObjectCollection.get(name), 441 stateCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 442 new Set([...stateCollection.get(CUSTOM_COMPONENT_DEFAULT), 443 ...stateCollection.get(name)]) : stateCollection.get(name), 444 regularCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 445 new Set([...regularCollection.get(CUSTOM_COMPONENT_DEFAULT), 446 ...regularCollection.get(name)]) : regularCollection.get(name), 447 storagePropCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 448 new Set([...storagePropCollection.get(CUSTOM_COMPONENT_DEFAULT), 449 ...storagePropCollection.get(name)]) : storagePropCollection.get(name), 450 storageLinkCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 451 new Set([...storageLinkCollection.get(CUSTOM_COMPONENT_DEFAULT), 452 ...storageLinkCollection.get(name)]) : storageLinkCollection.get(name), 453 provideCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 454 new Set([...provideCollection.get(CUSTOM_COMPONENT_DEFAULT), 455 ...provideCollection.get(name)]) : provideCollection.get(name), 456 consumeCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 457 new Set([...consumeCollection.get(CUSTOM_COMPONENT_DEFAULT), 458 ...consumeCollection.get(name)]) : consumeCollection.get(name), 459 objectLinkCollection.has(CUSTOM_COMPONENT_DEFAULT) ? 460 new Set([...objectLinkCollection.get(CUSTOM_COMPONENT_DEFAULT), 461 ...objectLinkCollection.get(name)]) : objectLinkCollection.get(name), 462 getNewLocalStorageMap(localStorageLinkCollection, name), 463 getNewLocalStorageMap(localStoragePropCollection, name), 464 builderParamInitialization.has(CUSTOM_COMPONENT_DEFAULT) ? 465 new Set([...builderParamInitialization.get(CUSTOM_COMPONENT_DEFAULT), 466 ...builderParamInitialization.get(name)]) : builderParamInitialization.get(name), 467 propInitialization.has(CUSTOM_COMPONENT_DEFAULT) ? 468 new Set([...propInitialization.get(CUSTOM_COMPONENT_DEFAULT), 469 ...propInitialization.get(name)]) : propInitialization.get(name), isDETS, 470 structDecorator 471 ); 472} 473 474function getNewLocalStorageMap(collection: Map<string, Map<string, Set<string>>>, name: string) 475 : Map<string, Set<string>> { 476 let localStorageLinkMap: Map<string, Set<string>> = new Map(); 477 if (collection.has(CUSTOM_COMPONENT_DEFAULT)) { 478 const tempSet: Set<string> = new Set(); 479 if (collection.get(CUSTOM_COMPONENT_DEFAULT)) { 480 for (const key of collection.get(CUSTOM_COMPONENT_DEFAULT).keys()) { 481 tempSet.add(key); 482 } 483 } 484 if (collection.get(name)) { 485 for (const key of collection.get(name).keys()) { 486 tempSet.add(key); 487 } 488 } 489 localStorageLinkMap.set(name, tempSet); 490 } else { 491 localStorageLinkMap = collection.get(name); 492 } 493 return localStorageLinkMap; 494} 495 496function setDependencies(component: string, asComponentName: string, linkArray: Set<string>, propertyArray: Set<string>, 497 propArray: Set<string>, builderParamArray: Set<string>, stateArray: Set<string>, 498 regularArray: Set<string>, storagePropsArray: Set<string>, storageLinksArray: Set<string>, 499 providesArray: Set<string>, consumesArray: Set<string>, objectLinksArray: Set<string>, 500 localStorageLinkMap: Map<string, Set<string>>, localStoragePropMap: Map<string, Set<string>>, 501 builderParamData: Set<string>, propData: Set<string>, isDETS: boolean, 502 structDecorator: structDecoratorResult): void { 503 if (asComponentName) { 504 linkCollection.set(asComponentName, linkArray); 505 storedFileInfo.overallLinkCollection.set(asComponentName, linkArray); 506 } else if (!asComponentName && component) { 507 linkCollection.set(component, linkArray); 508 if (projectConfig.compileMode === 'esmodule' && process.env.compileTool === 'rollup') { 509 storedFileInfo.overallLinkCollection.set(component, linkArray); 510 } 511 } 512 propertyCollection.set(component, propertyArray); 513 if (!propCollection.get(component)) { 514 propCollection.set(component, propArray); 515 } 516 if (asComponentName) { 517 storedFileInfo.overallBuilderParamCollection.set(asComponentName, builderParamArray); 518 } else if (!asComponentName && component && projectConfig.compileMode === 'esmodule' && 519 process.env.compileTool === 'rollup') { 520 storedFileInfo.overallBuilderParamCollection.set(component, builderParamArray); 521 } 522 builderParamObjectCollection.set(component, builderParamArray); 523 componentCollection.customComponents.add(component); 524 if (isDETS) { 525 storedFileInfo.getCurrentArkTsFile().compFromDETS.add(component); 526 } 527 if (structDecorator.hasRecycle) { 528 storedFileInfo.getCurrentArkTsFile().recycleComponents.add(component); 529 } 530 stateCollection.set(component, stateArray); 531 regularCollection.set(component, regularArray); 532 storagePropCollection.set(component, storagePropsArray); 533 storageLinkCollection.set(component, storageLinksArray); 534 provideCollection.set(component, providesArray); 535 consumeCollection.set(component, consumesArray); 536 if (asComponentName) { 537 storedFileInfo.overallObjectLinkCollection.set(asComponentName, objectLinksArray); 538 } else if (!asComponentName && component && projectConfig.compileMode === 'esmodule' && 539 process.env.compileTool === 'rollup') { 540 storedFileInfo.overallObjectLinkCollection.set(component, objectLinksArray); 541 } 542 objectLinkCollection.set(component, objectLinksArray); 543 localStorageLinkCollection.set(component, localStorageLinkMap); 544 localStoragePropCollection.set(component, localStoragePropMap); 545 if (!builderParamInitialization.get(component)) { 546 builderParamInitialization.set(component, builderParamData); 547 } 548 if (!propInitialization.get(component)) { 549 propInitialization.set(component, propData); 550 } 551} 552 553function hasCollection(node: ts.Identifier): boolean { 554 const name: string = node.escapedText.toString(); 555 return linkCollection.has(name) || 556 propCollection.has(name) || 557 propertyCollection.has(name) || 558 builderParamObjectCollection.has(name) || 559 stateCollection.has(name) || 560 regularCollection.has(name) || 561 storagePropCollection.has(name) || 562 storageLinkCollection.has(name) || 563 provideCollection.has(name) || 564 consumeCollection.has(name) || 565 objectLinkCollection.has(name) || 566 localStorageLinkCollection.has(name) || 567 localStoragePropCollection.has(name); 568} 569 570function isModule(filePath: string): boolean { 571 return !/^(\.|\.\.)?\//.test(filePath) || filePath.indexOf(projectConfig.packageDir) > -1; 572} 573 574function isCustomComponent(node: ts.StructDeclaration, structDecorator: structDecoratorResult): boolean { 575 let isComponent: boolean = false; 576 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 577 if (decorators && decorators.length) { 578 for (let i = 0; i < decorators.length; ++i) { 579 const decoratorName: ts.Expression = decorators[i].expression; 580 if (ts.isIdentifier(decoratorName) || ts.isCallExpression(decoratorName)) { 581 let name: string = ''; 582 if (ts.isCallExpression(decoratorName) && ts.isIdentifier(decoratorName.expression)) { 583 name = decoratorName.expression.escapedText.toString(); 584 } else if (ts.isIdentifier(decoratorName)) { 585 name = decoratorName.escapedText.toString(); 586 } 587 if (CUSTOM_DECORATOR_NAME.has(name)) { 588 isComponent = true; 589 } 590 if (name === DECORATOR_REUSEABLE) { 591 structDecorator.hasRecycle = true; 592 } 593 } 594 } 595 } 596 return isComponent; 597} 598 599let packageJsonEntry: string = ''; 600 601function isPackageJsonEntry(filePath: string): boolean { 602 const packageJsonPath: string = path.join(filePath, projectConfig.packageJson); 603 if (fs.existsSync(packageJsonPath)) { 604 let entryTypes: string; 605 let entryMain: string; 606 try { 607 const packageJson: Object = 608 (projectConfig.packageManagerType === 'npm' ? JSON : JSON5).parse(fs.readFileSync(packageJsonPath).toString()); 609 entryTypes = packageJson.types; 610 entryMain = packageJson.main; 611 } catch (e) { 612 return false; 613 } 614 if (entryExist(filePath, entryTypes)) { 615 packageJsonEntry = path.resolve(filePath, entryTypes); 616 return true; 617 } else if (entryExist(filePath, entryMain)) { 618 packageJsonEntry = path.resolve(filePath, entryMain); 619 return true; 620 } 621 } 622 return false; 623} 624 625function entryExist(filePath: string, entry: string): boolean { 626 return typeof entry === 'string' && fs.existsSync(path.resolve(filePath, entry)) && 627 fs.statSync(path.resolve(filePath, entry)).isFile(); 628} 629 630function getModuleFilePath(filePath: string): string { 631 if (filePath && path.extname(filePath) !== EXTNAME_ETS && isModule(filePath)) { 632 filePath += EXTNAME_ETS; 633 } 634 return filePath; 635} 636 637function getFileResolvePath(fileResolvePath: string, pagesDir: string, filePath: string, 638 projectPath: string): string { 639 const moduleFilePath: string = getModuleFilePath(filePath); 640 const defaultModule: string = path.join(projectPath, moduleFilePath); 641 if (fs.existsSync(defaultModule)) { 642 return defaultModule; 643 } 644 let entryModule: string; 645 let etsModule: string; 646 if (new RegExp(`^@(${sdkConfigPrefix})\\.`).test(filePath.trim())) { 647 for (let i = 0; i < sdkConfigs.length; i++) { 648 const resolveModuleInfo: ResolveModuleInfo = getRealModulePath(sdkConfigs[i].apiPath, filePath, ['.d.ts', '.d.ets']); 649 const systemModule: string = resolveModuleInfo.modulePath; 650 if (fs.existsSync(systemModule)) { 651 return systemModule; 652 } 653 } 654 } 655 if (!projectConfig.aceModuleJsonPath) { 656 entryModule = path.join(projectPath, '../../../../../', moduleFilePath); 657 etsModule = path.join(projectPath, '../../', moduleFilePath); 658 } else { 659 entryModule = path.join(projectPath, '../../../../', moduleFilePath); 660 etsModule = path.join(projectPath, '../', moduleFilePath); 661 } 662 if (fs.existsSync(entryModule)) { 663 return entryModule; 664 } 665 if (fs.existsSync(etsModule)) { 666 return etsModule; 667 } 668 let curPageDir: string = pagesDir; 669 while (!fs.existsSync(fileResolvePath)) { 670 if (filePath.indexOf(projectConfig.packageDir) > -1 && /^(\.|\.\.)\//.test(filePath)) { 671 fileResolvePath = path.join(curPageDir, filePath); 672 } else { 673 fileResolvePath = path.join(curPageDir, projectConfig.packageDir, filePath); 674 } 675 if (fs.existsSync(fileResolvePath + EXTNAME_ETS)) { 676 fileResolvePath = fileResolvePath + EXTNAME_ETS; 677 } else if (isPackageJsonEntry(fileResolvePath)) { 678 fileResolvePath = packageJsonEntry; 679 if (fs.statSync(fileResolvePath).isDirectory()) { 680 if (fs.existsSync(path.join(fileResolvePath, INDEX_ETS))) { 681 fileResolvePath = path.join(fileResolvePath, INDEX_ETS); 682 } else if (fs.existsSync(path.join(fileResolvePath, INDEX_TS))) { 683 fileResolvePath = path.join(fileResolvePath, INDEX_TS); 684 } 685 } 686 } else if (fs.existsSync(path.join(fileResolvePath, INDEX_ETS))) { 687 fileResolvePath = path.join(fileResolvePath, INDEX_ETS); 688 } else if (fs.existsSync(path.join(fileResolvePath, INDEX_TS))) { 689 fileResolvePath = path.join(fileResolvePath, INDEX_TS); 690 } 691 if (curPageDir === path.parse(curPageDir).root) { 692 break; 693 } 694 curPageDir = path.dirname(curPageDir); 695 } 696 return fileResolvePath; 697} 698 699function getFileFullPath(filePath: string, pagesDir: string): string { 700 if (filePath && path.extname(filePath) !== EXTNAME_ETS && path.extname(filePath) !== EXTNAME_TS && 701 !isModule(filePath)) { 702 const dirIndexEtsPath: string = path.resolve(path.resolve(pagesDir, filePath), INDEX_ETS); 703 const dirIndexTsPath: string = path.resolve(path.resolve(pagesDir, filePath), INDEX_TS); 704 if (/^(\.|\.\.)\//.test(filePath) && !fs.existsSync(path.resolve(pagesDir, filePath + EXTNAME_ETS)) && 705 fs.existsSync(dirIndexEtsPath)) { 706 filePath = dirIndexEtsPath; 707 } else if (/^(\.|\.\.)\//.test(filePath) && !fs.existsSync(path.resolve(pagesDir, filePath + EXTNAME_TS)) && 708 fs.existsSync(dirIndexTsPath)) { 709 filePath = dirIndexTsPath; 710 } else { 711 filePath += getExtensionIfUnfullySpecifiedFilepath(path.resolve(pagesDir, filePath)); 712 } 713 } 714 715 let fileResolvePath: string; 716 if (/^(\.|\.\.)\//.test(filePath) && filePath.indexOf(projectConfig.packageDir) < 0) { 717 fileResolvePath = path.resolve(pagesDir, filePath); 718 } else if (/^\//.test(filePath) && filePath.indexOf(projectConfig.packageDir) < 0 || 719 fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { 720 fileResolvePath = filePath; 721 } else { 722 fileResolvePath = getFileResolvePath(fileResolvePath, pagesDir, filePath, projectConfig.projectPath); 723 } 724 725 return fileResolvePath; 726} 727 728function validateModuleName(moduleNode: ts.Identifier, log: LogInfo[], sourceFile?: ts.SourceFile, 729 fileResolvePath?: string): void { 730 const moduleName: string = moduleNode.escapedText.toString(); 731 if (INNER_COMPONENT_NAMES.has(moduleName)) { 732 const error: LogInfo = { 733 type: LogType.ERROR, 734 message: `The module name '${moduleName}' can not be the same as the inner component name.`, 735 pos: moduleNode.getStart(), 736 code: '10905235' 737 }; 738 if (sourceFile && fileResolvePath) { 739 const posOfNode: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(moduleNode.getStart()); 740 const line: number = posOfNode.line + 1; 741 const column: number = posOfNode.character + 1; 742 Object.assign(error, { 743 fileName: fileResolvePath, 744 line: line, 745 column: column 746 }); 747 } 748 log.push(error); 749 } 750} 751 752interface PageInfo { 753 pageFile: string; 754 setChildOnce: boolean; 755} 756 757export function processImportModule(node: ts.ImportDeclaration, pageFile: string, log: LogInfo[]): void { 758 let importSymbol: ts.Symbol; 759 let realSymbol: ts.Symbol; 760 let originNode: ts.Node; 761 const pageInfo: PageInfo = { pageFile: pageFile, setChildOnce: false }; 762 validateModuleSpecifier(node.moduleSpecifier, log); 763 764 // import xxx from 'xxx' 765 if (node.importClause && node.importClause.name && ts.isIdentifier(node.importClause.name)) { 766 getDefinedNode(importSymbol, realSymbol, originNode, node.importClause.name, pageInfo); 767 } 768 769 // import {xxx} from 'xxx' 770 if (node.importClause && node.importClause.namedBindings && 771 ts.isNamedImports(node.importClause.namedBindings) && 772 node.importClause.namedBindings.elements) { 773 node.importClause.namedBindings.elements.forEach((importSpecifier: ts.ImportSpecifier) => { 774 if (ts.isImportSpecifier(importSpecifier) && importSpecifier.name && ts.isIdentifier(importSpecifier.name)) { 775 getDefinedNode(importSymbol, realSymbol, originNode, importSpecifier.name, pageInfo); 776 } 777 }); 778 } 779 780 // import * as xxx from 'xxx' 781 if (node.importClause && node.importClause.namedBindings && 782 ts.isNamespaceImport(node.importClause.namedBindings) && node.importClause.namedBindings.name && 783 ts.isIdentifier(node.importClause.namedBindings.name)) { 784 storedFileInfo.isAsPageImport = true; 785 getDefinedNode(importSymbol, realSymbol, originNode, node.importClause.namedBindings.name, pageInfo); 786 } 787} 788 789function getDefinedNode(importSymbol: ts.Symbol, realSymbol: ts.Symbol, originNode: ts.Node, 790 usedNode: ts.Identifier, pageInfo: PageInfo): void { 791 importSymbol = globalProgram.checker.getSymbolAtLocation(usedNode); 792 if (importSymbol) { 793 realSymbol = globalProgram.checker.getAliasedSymbol(importSymbol); 794 } else { 795 realSymbol = null; 796 } 797 if (realSymbol && realSymbol.declarations) { 798 originNode = realSymbol.declarations[0]; 799 } else { 800 originNode = null; 801 } 802 if (originNode) { 803 if (ts.isSourceFile(originNode) && realSymbol.escapedName) { 804 const escapedName: string = realSymbol.escapedName.toString().replace(/^("|')/, '').replace(/("|')$/, ''); 805 if (fs.existsSync(escapedName + '.ets') || fs.existsSync(escapedName + '.ts') && 806 realSymbol.exports && realSymbol.exports instanceof Map) { 807 getIntegrationNodeInfo(originNode, usedNode, realSymbol.exports, pageInfo); 808 return; 809 } 810 } 811 processImportNode(originNode, usedNode, false, null, pageInfo); 812 } 813} 814 815function getIntegrationNodeInfo(originNode: ts.Node, usedNode: ts.Identifier, exportsMap: ts.SymbolTable, 816 pageInfo: PageInfo): void { 817 for (const usedSymbol of exportsMap) { 818 try { 819 originNode = globalProgram.checker.getAliasedSymbol(usedSymbol[1]).declarations[0]; 820 } catch (e) { 821 if (usedSymbol[1] && usedSymbol[1].declarations) { 822 for (let i = 0; i < usedSymbol[1].declarations.length; i++) { 823 originNode = usedSymbol[1].declarations[i]; 824 exportAllManage(originNode, usedNode, pageInfo); 825 } 826 } 827 } 828 processImportNode(originNode, usedNode, true, usedSymbol[0], pageInfo); 829 } 830} 831 832// export * from 'xxx'; 833function exportAllManage(originNode: ts.Node, usedNode: ts.Identifier, pageInfo: PageInfo): void { 834 let exportOriginNode: ts.Node; 835 if (!originNode.exportClause && originNode.moduleSpecifier && ts.isStringLiteral(originNode.moduleSpecifier)) { 836 const exportSymbol: ts.Symbol = globalProgram.checker.getSymbolAtLocation(originNode.moduleSpecifier); 837 if (exportSymbol && exportSymbol.declarations) { 838 exportOriginNode = exportSymbol.declarations[0]; 839 } else { 840 exportOriginNode = null; 841 } 842 if (exportOriginNode) { 843 if (ts.isSourceFile(exportOriginNode) && exportSymbol.escapedName) { 844 const escapedName: string = exportSymbol.escapedName.toString().replace(/^("|')/, '').replace(/("|')$/, ''); 845 if (fs.existsSync(escapedName + '.ets') || fs.existsSync(escapedName + '.ts') && 846 exportSymbol.exports && exportSymbol.exports instanceof Map) { 847 getIntegrationNodeInfo(originNode, usedNode, exportSymbol.exports, pageInfo); 848 return; 849 } 850 } 851 } 852 } 853} 854 855function processImportNode(originNode: ts.Node, usedNode: ts.Identifier, importIntegration: boolean, 856 usedPropName: string, pageInfo: PageInfo): void { 857 const structDecorator: structDecoratorResult = { hasRecycle: false }; 858 let name: string; 859 let asComponentName: string; 860 if (importIntegration) { 861 if (storedFileInfo.isAsPageImport) { 862 asComponentName = usedNode.escapedText.toString() + '.' + usedPropName; 863 } 864 name = usedPropName; 865 } else { 866 name = usedNode.escapedText.toString(); 867 } 868 let needCollection: boolean = true; 869 const originFile: string = originNode.getSourceFile() ? originNode.getSourceFile().fileName : undefined; 870 if (ts.isStructDeclaration(originNode) && ts.isIdentifier(originNode.name)) { 871 parseComponentInImportNode(originNode, name, asComponentName, structDecorator, originFile); 872 } else if (isObservedClass(originNode)) { 873 observedClassCollection.add(name); 874 } else if (ts.isFunctionDeclaration(originNode) && hasDecorator(originNode, COMPONENT_BUILDER_DECORATOR)) { 875 CUSTOM_BUILDER_METHOD.add(name); 876 GLOBAL_CUSTOM_BUILDER_METHOD.add(name); 877 } else if (ts.isEnumDeclaration(originNode) && originNode.name) { 878 enumCollection.add(name); 879 } else { 880 needCollection = false; 881 } 882 if (needCollection && pageInfo.pageFile && !pageInfo.setChildOnce && originFile) { 883 const childFile: string = path.resolve(getRealPath(originFile) || originFile); 884 storedFileInfo.transformCacheFiles[pageInfo.pageFile].children.push({ 885 fileName: childFile, 886 mtimeMs: fs.existsSync(childFile) ? fs.statSync(childFile).mtimeMs : 0 887 }); 888 pageInfo.setChildOnce = true; 889 } 890} 891 892function getRealPath(filePath: string): string { 893 try { 894 const newPath: string = fs.realpathSync.native(filePath); 895 return newPath; 896 } catch (err) { 897 return undefined; 898 } 899} 900 901function setComponentCollectionInfo(name: string, componentSet: IComponentSet, isDETS: boolean, 902 structDecorator: structDecoratorResult, asComponentName: string): void { 903 setDependencies(name, asComponentName, componentSet.links, componentSet.properties, 904 componentSet.props, componentSet.builderParams, componentSet.states, componentSet.regulars, 905 componentSet.storageProps, componentSet.storageLinks, componentSet.provides, 906 componentSet.consumes, componentSet.objectLinks, componentSet.localStorageLink, 907 componentSet.localStorageProp, componentSet.builderParamData, componentSet.propData, isDETS, 908 structDecorator); 909 regularInitialization.set(name, componentSet.regularInit); 910 stateInitialization.set(name, componentSet.stateInit); 911 provideInitialization.set(name, componentSet.provideInit); 912 privateCollection.set(name, componentSet.privateCollection); 913 regularStaticCollection.set(name, componentSet.regularStaticCollection); 914 if (asComponentName) { 915 const asComponentNameStructInfo: StructInfo = 916 processStructComponentV2.getOrCreateStructInfo(asComponentName); 917 asComponentNameStructInfo.updatePropsDecoratorsV1.push( 918 ...componentSet.states, ...componentSet.props, 919 ...componentSet.provides, ...componentSet.objectLinks 920 ); 921 asComponentNameStructInfo.linkDecoratorsV1.push(...componentSet.links); 922 return; 923 } 924 const nameStructInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(name); 925 nameStructInfo.updatePropsDecoratorsV1.push( 926 ...componentSet.states, ...componentSet.props, 927 ...componentSet.provides, ...componentSet.objectLinks 928 ); 929 nameStructInfo.linkDecoratorsV1.push(...componentSet.links); 930} 931 932function parseComponentInImportNode(originNode: ts.StructDeclaration, name: string, 933 asComponentName: string, structDecorator: structDecoratorResult, originFile: string): void { 934 componentCollection.customComponents.add(name); 935 const structInfo: StructInfo = asComponentName ? 936 processStructComponentV2.getOrCreateStructInfo(asComponentName) : 937 processStructComponentV2.getOrCreateStructInfo(name); 938 if (isComponentV2(originNode)) { 939 parseComponentV2InImportNode(originNode, name, originFile, structInfo); 940 return; 941 } 942 if (isCustomDialogClass(originNode)) { 943 structInfo.isCustomDialog = true; 944 componentCollection.customDialogs.add(name); 945 } 946 if (isCustomComponent(originNode, structDecorator)) { 947 structInfo.isComponentV1 = true; 948 let isDETS: boolean = false; 949 const componentSet: IComponentSet = getComponentSet(originNode, false); 950 while (originNode) { 951 if (ts.isSourceFile(originNode) && /\.d\.ets$/.test(originNode.fileName)) { 952 isDETS = true; 953 } 954 originNode = originNode.parent; 955 } 956 setComponentCollectionInfo(name, componentSet, isDETS, structDecorator, asComponentName); 957 } 958} 959 960function parseComponentV2InImportNode(node: ts.StructDeclaration, name: string, originFile: string, 961 structInfo: StructInfo): void { 962 structInfo.isComponentV2 = true; 963 const isDETS: boolean = originFile && /\.d\.ets$/.test(originFile); 964 if (isDETS) { 965 storedFileInfo.getCurrentArkTsFile().compFromDETS.add(name); 966 } 967 if (isReusableV2(node)) { 968 storedFileInfo.getCurrentArkTsFile().reuseComponentsV2.add(name); 969 } 970 processStructComponentV2.parseComponentProperty(node, structInfo, null, null); 971} 972 973function isComponentV2(node: ts.StructDeclaration): boolean { 974 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 975 return decorators.some((item: ts.Decorator) => { 976 const name: string = item.getText().replace(/\([^\(\)]*\)/, '').replace('@', '').trim(); 977 return name === 'ComponentV2'; 978 }); 979} 980 981function isReusableV2(node: ts.StructDeclaration): boolean { 982 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 983 return decorators.some((item: ts.Decorator) => { 984 const name: string = item.getText().replace(/\([^\(\)]*\)/, '').replace('@', '').trim(); 985 return name === DECORATOR_REUSABLE_V2; 986 }); 987} 988