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 path from 'path'; 18import fs from 'fs'; 19 20import { 21 PAGE_ENTRY_FUNCTION_NAME, 22 PREVIEW_COMPONENT_FUNCTION_NAME, 23 STORE_PREVIEW_COMPONENTS, 24 GET_PREVIEW_FLAG_FUNCTION_NAME, 25 COMPONENT_CONSTRUCTOR_UNDEFINED, 26 BUILD_ON, 27 COMPONENT_BUILDER_DECORATOR, 28 COMPONENT_CONCURRENT_DECORATOR, 29 COMPONENT_SENDABLE_DECORATOR, 30 COMPONENT_EXTEND_DECORATOR, 31 COMPONENT_STYLES_DECORATOR, 32 RESOURCE, 33 RESOURCE_TYPE, 34 WORKER_OBJECT, 35 RESOURCE_NAME_ID, 36 RESOURCE_NAME_TYPE, 37 RESOURCE_NAME_PARAMS, 38 RESOURCE_RAWFILE, 39 RESOURCE_NAME_BUNDLE, 40 RESOURCE_NAME_MODULE, 41 ATTRIBUTE_ANIMATETO_SET, 42 GLOBAL_CONTEXT, 43 INSTANCE, 44 SET_CONTROLLER_CTR_TYPE, 45 SET_CONTROLLER_METHOD, 46 JS_DIALOG, 47 CUSTOM_DIALOG_CONTROLLER_BUILDER, 48 ESMODULE, 49 EXTNAME_ETS, 50 GENERATE_ID, 51 _GENERATE_ID, 52 VIEWSTACKPROCESSOR, 53 STARTGETACCESSRECORDINGFOR, 54 ALLOCATENEWELMETIDFORNEXTCOMPONENT, 55 STOPGETACCESSRECORDING, 56 CARD_ENTRY_FUNCTION_NAME, 57 CARD_LOG_TYPE_COMPONENTS, 58 CARD_LOG_TYPE_DECORATORS, 59 CARD_LOG_TYPE_IMPORT, 60 COMPONENT_ANIMATABLE_EXTEND_DECORATOR, 61 CHECK_EXTEND_DECORATORS, 62 ELMTID, 63 ROUTENAME_NODE, 64 STORAGE_NODE, 65 STORAGE, 66 REGISTER_NAMED_ROUTE, 67 ROUTE_NAME, 68 PAGE_PATH, 69 ISINITIALRENDER, 70 CREATE_ANIMATABLE_PROPERTY, 71 UPDATE_ANIMATABLE_PROPERTY, 72 MY_IDS, 73 VIEW_STACK_PROCESSOR, 74 GET_AND_PUSH_FRAME_NODE, 75 COMPONENT_CONSTRUCTOR_PARENT, 76 WRAPBUILDER_FUNCTION, 77 FINISH_UPDATE_FUNC, 78 GLOBAL_DECLARE_WHITE_LIST 79} from './pre_define'; 80import { 81 componentInfo, 82 LogInfo, 83 LogType, 84 hasDecorator, 85 FileLog, 86 getPossibleBuilderTypeParameter, 87 storedFileInfo, 88 ExtendResult, 89 startTimeStatisticsLocation, 90 stopTimeStatisticsLocation, 91 CompilationTimeStatistics 92} from './utils'; 93import { writeFileSyncByNode } from './process_module_files'; 94import { 95 componentCollection, 96 localStorageLinkCollection, 97 localStoragePropCollection 98} from './validate_ui_syntax'; 99import { 100 processComponentClass, 101 createParentParameter, 102 processBuildMember 103} from './process_component_class'; 104import processImport, { 105 processImportModule, 106 validateModuleSpecifier 107} from './process_import'; 108import { 109 processComponentBlock, 110 bindComponentAttr, 111 getName, 112 createViewStackProcessorStatement, 113 parseGlobalBuilderParams, 114 BuilderParamsResult 115} from './process_component_build'; 116import { 117 BUILDIN_STYLE_NAMES, 118 CUSTOM_BUILDER_METHOD, 119 EXTEND_ATTRIBUTE, 120 INNER_STYLE_FUNCTION, 121 GLOBAL_STYLE_FUNCTION, 122 INTERFACE_NODE_SET, 123 ID_ATTRS 124} from './component_map'; 125import { 126 resources, 127 projectConfig, 128 partialUpdateConfig, 129 globalProgram, 130 ohosSystemModulePaths 131} from '../main'; 132import { createCustomComponentNewExpression, createViewCreate } from './process_component_member'; 133import { 134 assignComponentParams, 135 assignmentFunction 136} from './process_custom_component'; 137import { processDecorator } from './fast_build/ark_compiler/process_decorator'; 138import { isArkuiDependence } from "./ets_checker"; 139 140export let transformLog: FileLog = new FileLog(); 141export let contextGlobal: ts.TransformationContext; 142export let resourceFileName: string = ''; 143export const builderTypeParameter: {params: string[]} = {params: []}; 144 145export function processUISyntax(program: ts.Program, ut = false, 146 compilationTime: CompilationTimeStatistics = null): Function { 147 let entryNodeKey: ts.Expression; 148 return (context: ts.TransformationContext) => { 149 contextGlobal = context; 150 let pagesDir: string; 151 let pageFile: string; 152 return (node: ts.SourceFile) => { 153 pagesDir = path.resolve(path.dirname(node.fileName)); 154 resourceFileName = path.resolve(node.fileName); 155 pageFile = node.fileName; 156 if (process.env.compiler === BUILD_ON || process.env.compileTool === 'rollup') { 157 storedFileInfo.transformCacheFiles[node.fileName] = { 158 mtimeMs: fs.existsSync(node.fileName) ? fs.statSync(node.fileName).mtimeMs : 0, 159 children: [] 160 }; 161 transformLog.sourceFile = node; 162 preprocessIdAttrs(node.fileName); 163 if (!ut && (process.env.compileMode !== 'moduleJson' && 164 path.resolve(node.fileName) === path.resolve(projectConfig.projectPath, 'app.ets') || 165 /\.ts$/.test(node.fileName))) { 166 node = ts.visitEachChild(node, processResourceNode, context); 167 if (projectConfig.compileMode === ESMODULE && projectConfig.processTs === true) { 168 if (process.env.compileTool !== 'rollup') { 169 const processedNode: ts.SourceFile = ts.getTypeExportImportAndConstEnumTransformer(context)(node); 170 writeFileSyncByNode(processedNode, projectConfig); 171 } 172 } 173 return node; 174 } 175 const id: number = ++componentInfo.id; 176 node = ts.visitEachChild(node, processAllNodes, context); 177 node = createEntryNode(node, context, entryNodeKey, id); 178 GLOBAL_STYLE_FUNCTION.forEach((block, styleName) => { 179 BUILDIN_STYLE_NAMES.delete(styleName); 180 }); 181 GLOBAL_STYLE_FUNCTION.clear(); 182 const statements: ts.Statement[] = Array.from(node.statements); 183 if (!partialUpdateConfig.partialUpdateMode) { 184 generateId(statements, node); 185 } 186 INTERFACE_NODE_SET.forEach(item => { 187 statements.unshift(item); 188 }); 189 node = ts.factory.updateSourceFile(node, statements); 190 INTERFACE_NODE_SET.clear(); 191 if (projectConfig.compileMode === ESMODULE && projectConfig.processTs === true) { 192 if (process.env.compileTool !== 'rollup') { 193 const processedNode: ts.SourceFile = ts.getTypeExportImportAndConstEnumTransformer(context)(node); 194 writeFileSyncByNode(processedNode, projectConfig); 195 } 196 } 197 return node; 198 } else { 199 return node; 200 } 201 }; 202 203 function entryKeyNode(node: ts.Node): ts.Expression { 204 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 205 if (node && decorators && decorators.length) { 206 decorators.forEach(item => { 207 if (item.expression && ts.isCallExpression(item.expression) && ts.isIdentifier(item.expression.expression) && 208 item.expression.expression.escapedText.toString() === 'Entry' && item.expression.arguments && 209 item.expression.arguments.length && ts.isIdentifier(item.expression.arguments[0])) { 210 entryNodeKey = item.expression.arguments[0]; 211 } 212 }); 213 } 214 return entryNodeKey; 215 } 216 217 function isESObjectNode(node: ts.Node): boolean { 218 if (node.kind === ts.SyntaxKind.TypeReference) { 219 const n: TypeReferenceNode = node as TypeReferenceNode; 220 if (n.typeName?.kind === ts.SyntaxKind.Identifier && (n.typeName as ts.Identifier).escapedText === 'ESObject') { 221 return true; 222 } 223 } 224 return false; 225 } 226 227 function processAllNodes(node: ts.Node): ts.Node { 228 if (projectConfig.compileMode === 'esmodule' && process.env.compileTool === 'rollup' && 229 ts.isImportDeclaration(node)) { 230 startTimeStatisticsLocation(compilationTime ? compilationTime.processImportTime : undefined); 231 processImportModule(node, pageFile, transformLog.errors); 232 stopTimeStatisticsLocation(compilationTime ? compilationTime.processImportTime : undefined); 233 } else if ((projectConfig.compileMode !== 'esmodule' || process.env.compileTool !== 'rollup') && 234 (ts.isImportDeclaration(node) || ts.isImportEqualsDeclaration(node) || 235 ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier))) { 236 processImport(node, pagesDir, transformLog.errors); 237 } 238 if (ts.isStructDeclaration(node)) { 239 componentCollection.currentClassName = node.name.getText(); 240 componentCollection.entryComponent === componentCollection.currentClassName && entryKeyNode(node); 241 startTimeStatisticsLocation(compilationTime ? compilationTime.processComponentClassTime : undefined); 242 node = processComponentClass(node, context, transformLog.errors, program); 243 stopTimeStatisticsLocation(compilationTime ? compilationTime.processComponentClassTime : undefined); 244 componentCollection.currentClassName = null; 245 INNER_STYLE_FUNCTION.forEach((block, styleName) => { 246 BUILDIN_STYLE_NAMES.delete(styleName); 247 }); 248 INNER_STYLE_FUNCTION.clear(); 249 } else if (ts.isFunctionDeclaration(node)) { 250 if (hasDecorator(node, COMPONENT_EXTEND_DECORATOR, null, transformLog.errors)) { 251 node = processExtend(node, transformLog.errors, COMPONENT_EXTEND_DECORATOR); 252 // @ts-ignore 253 if (node && node.illegalDecorators) { 254 // @ts-ignore 255 node.illegalDecorators = undefined; 256 } 257 } else if (hasDecorator(node, COMPONENT_BUILDER_DECORATOR) && node.name && node.body && 258 ts.isBlock(node.body)) { 259 storedFileInfo.processBuilder = true; 260 storedFileInfo.processGlobalBuilder = true; 261 CUSTOM_BUILDER_METHOD.add(node.name.getText()); 262 builderTypeParameter.params = getPossibleBuilderTypeParameter(node.parameters); 263 const parameters: ts.NodeArray<ts.ParameterDeclaration> = 264 ts.factory.createNodeArray(Array.from(node.parameters)); 265 parameters.push(createParentParameter()); 266 if (projectConfig.optLazyForEach) { 267 parameters.push(initializeMYIDS()); 268 } 269 storedFileInfo.builderLikeCollection = CUSTOM_BUILDER_METHOD; 270 const builderParamsResult: BuilderParamsResult = { firstParam: null }; 271 parseGlobalBuilderParams(node.parameters, builderParamsResult); 272 node = ts.factory.updateFunctionDeclaration(node, ts.getModifiers(node), 273 node.asteriskToken, node.name, node.typeParameters, parameters, node.type, 274 processComponentBlock(node.body, false, transformLog.errors, false, true, 275 node.name.getText(), undefined, true, builderParamsResult, true)); 276 builderParamsResult.firstParam = null; 277 // @ts-ignore 278 if (node && node.illegalDecorators) { 279 // @ts-ignore 280 node.illegalDecorators = undefined; 281 } 282 builderTypeParameter.params = []; 283 node = processBuildMember(node, context, transformLog.errors, true); 284 storedFileInfo.processBuilder = false; 285 storedFileInfo.processGlobalBuilder = false; 286 } else if (hasDecorator(node, COMPONENT_STYLES_DECORATOR)) { 287 if (node.parameters.length === 0) { 288 node = undefined; 289 } else { 290 transformLog.errors.push({ 291 type: LogType.ERROR, 292 message: `@Styles can't have parameters.`, 293 pos: node.getStart() 294 }); 295 } 296 } else if (hasDecorator(node, COMPONENT_CONCURRENT_DECORATOR)) { 297 // ark compiler's feature 298 node = processConcurrent(node); 299 if (node && node.illegalDecorators) { 300 // @ts-ignore 301 node.illegalDecorators = undefined; 302 } 303 } else if (hasDecorator(node, COMPONENT_ANIMATABLE_EXTEND_DECORATOR, null, transformLog.errors)) { 304 node = processExtend(node, transformLog.errors, COMPONENT_ANIMATABLE_EXTEND_DECORATOR); 305 // @ts-ignore 306 if (node && node.illegalDecorators) { 307 // @ts-ignore 308 node.illegalDecorators = undefined; 309 } 310 } 311 } else if (isResource(node)) { 312 node = processResourceData(node as ts.CallExpression); 313 } else if (isWorker(node)) { 314 node = processWorker(node as ts.NewExpression); 315 } else if (isAnimateToOrImmediately(node)) { 316 node = processAnimateToOrImmediately(node as ts.CallExpression); 317 } else if (isCustomDialogController(node)) { 318 node = createCustomDialogController(node.parent, node, transformLog.errors); 319 } else if (isESObjectNode(node)) { 320 node = ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword); 321 } else if (ts.isDecorator(node)) { 322 // This processing is for mock instead of ui transformation 323 node = processDecorator(node); 324 } else if (isWrapBuilderFunction(node)) { 325 if (node.arguments && node.arguments[0] && (!ts.isIdentifier(node.arguments[0]) || 326 ts.isIdentifier(node.arguments[0]) && 327 !CUSTOM_BUILDER_METHOD.has(node.arguments[0].escapedText.toString()))) { 328 transformLog.errors.push({ 329 type: LogType.ERROR, 330 message: `wrapBuilder's parameter should be @Builder function.`, 331 pos: node.getStart() 332 }); 333 } 334 } else if (ts.isClassDeclaration(node)) { 335 if (hasDecorator(node, COMPONENT_SENDABLE_DECORATOR)) { 336 node = processClassSendable(node); 337 } 338 } 339 return ts.visitEachChild(node, processAllNodes, context); 340 } 341 342 function processResourceNode(node: ts.Node): ts.Node { 343 if (ts.isImportDeclaration(node)) { 344 validateModuleSpecifier(node.moduleSpecifier, transformLog.errors); 345 } else if (isResource(node)) { 346 node = processResourceData(node as ts.CallExpression); 347 } else if (ts.isTypeReferenceNode(node)) { 348 checkTypeReference(node); 349 } 350 return ts.visitEachChild(node, processResourceNode, context); 351 } 352 353 function isWrapBuilderFunction(node: ts.Node): boolean { 354 if (ts.isCallExpression(node) && node.expression && ts.isIdentifier(node.expression) && 355 node.expression.escapedText.toString() === WRAPBUILDER_FUNCTION) { 356 return true; 357 } 358 return false; 359 } 360 }; 361} 362 363export function initializeMYIDS(): ts.ParameterDeclaration { 364 return ts.factory.createParameterDeclaration( 365 undefined, 366 undefined, 367 ts.factory.createIdentifier(MY_IDS), 368 undefined, 369 undefined, 370 ts.factory.createArrayLiteralExpression( 371 [], 372 false 373 ) 374 ); 375} 376 377function generateId(statements: ts.Statement[], node: ts.SourceFile): void { 378 statements.unshift( 379 ts.factory.createVariableStatement( 380 undefined, 381 ts.factory.createVariableDeclarationList( 382 [ts.factory.createVariableDeclaration( 383 ts.factory.createIdentifier(_GENERATE_ID), 384 undefined, 385 ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), 386 ts.factory.createNumericLiteral('0') 387 )], 388 ts.NodeFlags.Let 389 ) 390 ), 391 ts.factory.createFunctionDeclaration( 392 undefined, 393 undefined, 394 ts.factory.createIdentifier(GENERATE_ID), 395 undefined, 396 [], 397 ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), 398 ts.factory.createBlock( 399 [ts.factory.createReturnStatement(ts.factory.createBinaryExpression( 400 ts.factory.createStringLiteral(path.basename(node.fileName, EXTNAME_ETS) + '_'), 401 ts.factory.createToken(ts.SyntaxKind.PlusToken), ts.factory.createPrefixUnaryExpression( 402 ts.SyntaxKind.PlusPlusToken, 403 ts.factory.createIdentifier(_GENERATE_ID) 404 )))], 405 true 406 ) 407 ) 408 ); 409} 410 411function preprocessIdAttrs(fileName: string): void { 412 for (const [id, idInfo] of ID_ATTRS) { 413 if (fileName === idInfo.get('path')) { 414 ID_ATTRS.delete(id); 415 } 416 } 417} 418 419function isCustomDialogController(node: ts.Expression) { 420 const tempParent: ts.Node = node.parent; 421 // @ts-ignore 422 if (!node.parent && node.original) { 423 // @ts-ignore 424 node.parent = node.original.parent; 425 } 426 if (ts.isNewExpression(node) && node.expression && ts.isIdentifier(node.expression) && 427 node.expression.escapedText.toString() === SET_CONTROLLER_CTR_TYPE) { 428 return true; 429 } else { 430 // @ts-ignore 431 node.parent = tempParent; 432 return false; 433 } 434} 435 436function createCustomDialogController(parent: ts.Expression, node: ts.NewExpression, 437 log: LogInfo[]): ts.NewExpression { 438 if (node.arguments && node.arguments.length === 1 && 439 ts.isObjectLiteralExpression(node.arguments[0]) && node.arguments[0].properties) { 440 const newproperties: ts.ObjectLiteralElementLike[] = node.arguments[0].properties.map((item) => { 441 const componentName: string = isCustomDialogControllerPropertyAssignment(item, log); 442 if (componentName !== null) { 443 item = processCustomDialogControllerPropertyAssignment(parent, 444 item as ts.PropertyAssignment, componentName); 445 } 446 return item; 447 }); 448 return ts.factory.createNewExpression(node.expression, node.typeArguments, 449 [ts.factory.createObjectLiteralExpression(newproperties, true), ts.factory.createThis()]); 450 } else { 451 return node; 452 } 453} 454 455function isCustomDialogControllerPropertyAssignment(node: ts.ObjectLiteralElementLike, 456 log: LogInfo[]): string { 457 if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && 458 node.name.getText() === CUSTOM_DIALOG_CONTROLLER_BUILDER) { 459 if (node.initializer) { 460 const componentName: string = getName(node.initializer); 461 if (componentCollection.customDialogs.has(componentName)) { 462 return componentName; 463 } 464 } else { 465 validateCustomDialogControllerBuilderInit(node, log); 466 } 467 } 468 return null; 469} 470 471function validateCustomDialogControllerBuilderInit(node: ts.ObjectLiteralElementLike, 472 log: LogInfo[]): void { 473 log.push({ 474 type: LogType.ERROR, 475 message: 'The builder should be initialized with a @CustomDialog Component.', 476 pos: node.getStart() 477 }); 478} 479 480function processCustomDialogControllerPropertyAssignment(parent: ts.Expression, 481 node: ts.PropertyAssignment, componentName: string): ts.PropertyAssignment { 482 if (ts.isCallExpression(node.initializer)) { 483 return ts.factory.updatePropertyAssignment(node, node.name, 484 processCustomDialogControllerBuilder(parent, node.initializer, componentName)); 485 } 486} 487 488function processCustomDialogControllerBuilder(parent: ts.Expression, 489 node: ts.CallExpression, componentName: string): ts.ArrowFunction { 490 const newExp: ts.Expression = createCustomComponentNewExpression(node, componentName, false, false, true); 491 const jsDialog: ts.Identifier = ts.factory.createIdentifier(JS_DIALOG); 492 return createCustomComponentBuilderArrowFunction(node, parent, jsDialog, newExp); 493} 494 495function createCustomComponentBuilderArrowFunction(node: ts.CallExpression, parent: ts.Expression, 496 jsDialog: ts.Identifier, newExp: ts.Expression): ts.ArrowFunction { 497 let mountNodde: ts.PropertyAccessExpression; 498 if (ts.isBinaryExpression(parent)) { 499 mountNodde = parent.left; 500 } else if (ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent)) { 501 mountNodde = ts.factory.createPropertyAccessExpression(ts.factory.createThis(), 502 parent.name as ts.Identifier); 503 } 504 return ts.factory.createArrowFunction( 505 undefined, 506 undefined, 507 [], 508 undefined, 509 ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), 510 ts.factory.createBlock( 511 [ 512 ts.factory.createVariableStatement( 513 undefined, 514 ts.factory.createVariableDeclarationList( 515 [ts.factory.createVariableDeclaration(jsDialog, undefined, undefined, newExp)], 516 ts.NodeFlags.Let 517 ) 518 ), 519 ts.factory.createExpressionStatement( 520 ts.factory.createCallExpression( 521 ts.factory.createPropertyAccessExpression( 522 jsDialog, 523 ts.factory.createIdentifier(SET_CONTROLLER_METHOD) 524 ), 525 undefined, 526 mountNodde ? [mountNodde] : undefined 527 ) 528 ), 529 ts.factory.createExpressionStatement(createViewCreate(jsDialog)), 530 partialUpdateConfig.partialUpdateMode ? assignComponentParams(node) : undefined, 531 partialUpdateConfig.partialUpdateMode ? assignmentFunction(jsDialog.escapedText.toString()) : undefined 532 ], 533 true 534 ) 535 ); 536} 537 538export function isResource(node: ts.Node): boolean { 539 return ts.isCallExpression(node) && ts.isIdentifier(node.expression) && 540 (node.expression.escapedText.toString() === RESOURCE || 541 node.expression.escapedText.toString() === RESOURCE_RAWFILE) && node.arguments.length > 0; 542} 543 544export function isAnimateToOrImmediately(node: ts.Node): boolean { 545 return ts.isCallExpression(node) && ts.isIdentifier(node.expression) && 546 ATTRIBUTE_ANIMATETO_SET.has(node.expression.escapedText.toString()); 547} 548 549export function processResourceData(node: ts.CallExpression, 550 previewLog: {isAcceleratePreview: boolean, log: LogInfo[]} = {isAcceleratePreview: false, log: []}): ts.Node { 551 if (ts.isStringLiteral(node.arguments[0])) { 552 if (node.expression.getText() === RESOURCE_RAWFILE) { 553 isResourcefile(node, previewLog); 554 return createResourceParam(0, RESOURCE_TYPE.rawfile, [node.arguments[0]]); 555 } else { 556 return getResourceDataNode(node, previewLog); 557 } 558 } else if (node.expression.getText() === RESOURCE && node.arguments && node.arguments.length) { 559 if (previewLog.isAcceleratePreview) { 560 previewLog.log.push({ 561 type: LogType.ERROR, 562 message: 'not support AcceleratePreview' 563 }); 564 } 565 return createResourceParamWithVariable(node); 566 } 567 return node; 568} 569 570 571/** 572 * check arkui dependences in ts files 573 * api check from sdk 574 * 575 * @param {ts.TypeReferenceNode} node 576 * @returns {void} 577 */ 578function checkTypeReference(node: ts.TypeReferenceNode): void { 579 const fileName: string = transformLog.sourceFile.fileName; 580 const currentTypeName: string = node.getText(); 581 if (/(?<!\.d)\.ts$/g.test(fileName)) { 582 const checker: ts.TypeChecker = globalProgram.checker; 583 if (!checker) { 584 return; 585 } 586 const type: ts.Type = checker.getTypeAtLocation(node); 587 let sourceFile: ts.SourceFile | undefined = undefined; 588 if (type && type.aliasSymbol && type.aliasSymbol.declarations && type.aliasSymbol.declarations.length > 0) { 589 sourceFile = ts.getSourceFileOfNode(type.aliasSymbol.declarations[0]); 590 } else if (type && type.symbol && type.symbol.declarations && type.symbol.declarations.length > 0) { 591 sourceFile = ts.getSourceFileOfNode(type.symbol.declarations[0]); 592 } 593 if (!sourceFile) { 594 return; 595 } 596 const sourceBaseName: string = path.basename(sourceFile.fileName); 597 if (isArkuiDependence(sourceFile.fileName) && 598 sourceBaseName !== 'common_ts_ets_api.d.ts' && 599 sourceBaseName !== 'global.d.ts' || 600 GLOBAL_DECLARE_WHITE_LIST.has(currentTypeName) && 601 ohosSystemModulePaths.includes(sourceFile.fileName.replace(/\//g, '\\'))) { 602 transformLog.errors.push({ 603 type: LogType.WARN, 604 message: `Cannot find name '${currentTypeName}'.`, 605 pos: node.getStart() 606 }); 607 } 608 } 609} 610 611function getResourceDataNode(node: ts.CallExpression, 612 previewLog: {isAcceleratePreview: boolean, log: LogInfo[]}): ts.Node { 613 const resourceData: string[] = (node.arguments[0] as ts.StringLiteral).text.trim().split('.'); 614 if (preCheckResourceData(resourceData, resources, node.arguments[0].getStart(), previewLog)) { 615 const resourceType: number = RESOURCE_TYPE[resourceData[1]]; 616 if (resourceType === undefined && !previewLog.isAcceleratePreview) { 617 transformLog.errors.push({ 618 type: LogType.ERROR, 619 message: `The resource type ${resourceData[1]} is not supported.`, 620 pos: node.getStart() 621 }); 622 return node; 623 } 624 const resourceValue: number = resources[resourceData[0]][resourceData[1]][resourceData[2]]; 625 return createResourceParam(resourceValue, resourceType, 626 projectConfig.compileHar ? Array.from(node.arguments) : Array.from(node.arguments).slice(1)); 627 } 628 return node; 629} 630 631function isResourcefile(node: ts.CallExpression, previewLog: {isAcceleratePreview: boolean, log: LogInfo[]}): void { 632 if (process.env.rawFileResource && !storedFileInfo.resourcesArr.has(node.arguments[0].text) && 633 !previewLog.isAcceleratePreview && process.env.compileMode === 'moduleJson') { 634 transformLog.errors.push({ 635 type: LogType.ERROR, 636 message: `No such '${node.arguments[0].text}' resource in current module.`, 637 pos: node.getStart() 638 }); 639 } 640} 641 642function addBundleAndModuleParam(propertyArray: Array<ts.PropertyAssignment>): void { 643 if (projectConfig.compileHar) { 644 projectConfig.bundleName = '__harDefaultBundleName__'; 645 projectConfig.moduleName = '__harDefaultModuleName__'; 646 } 647 648 if (projectConfig.bundleName || projectConfig.bundleName === '') { 649 propertyArray.push(ts.factory.createPropertyAssignment( 650 ts.factory.createStringLiteral(RESOURCE_NAME_BUNDLE), 651 ts.factory.createStringLiteral(projectConfig.bundleName) 652 )); 653 } 654 655 if (projectConfig.moduleName || projectConfig.moduleName === '') { 656 propertyArray.push(ts.factory.createPropertyAssignment( 657 ts.factory.createStringLiteral(RESOURCE_NAME_MODULE), 658 ts.factory.createStringLiteral(projectConfig.moduleName) 659 )); 660 } 661} 662 663function createResourceParamWithVariable(node: ts.CallExpression): ts.ObjectLiteralExpression { 664 const propertyArray: Array<ts.PropertyAssignment> = [ 665 ts.factory.createPropertyAssignment( 666 ts.factory.createStringLiteral(RESOURCE_NAME_ID), 667 node.arguments[0] 668 ), 669 ts.factory.createPropertyAssignment( 670 ts.factory.createIdentifier(RESOURCE_NAME_PARAMS), 671 ts.factory.createArrayLiteralExpression(Array.from(node.arguments).slice(1), false) 672 ) 673 ]; 674 675 addBundleAndModuleParam(propertyArray); 676 677 const resourceParams: ts.ObjectLiteralExpression = ts.factory.createObjectLiteralExpression( 678 propertyArray, false); 679 return resourceParams; 680} 681 682function createResourceParam(resourceValue: number, resourceType: number, argsArr: ts.Expression[]): 683 ts.ObjectLiteralExpression { 684 if (projectConfig.compileHar) { 685 resourceValue = -1; 686 } 687 688 const propertyArray: Array<ts.PropertyAssignment> = [ 689 ts.factory.createPropertyAssignment( 690 ts.factory.createStringLiteral(RESOURCE_NAME_ID), 691 ts.factory.createNumericLiteral(resourceValue) 692 ), 693 ts.factory.createPropertyAssignment( 694 ts.factory.createStringLiteral(RESOURCE_NAME_TYPE), 695 ts.factory.createNumericLiteral(resourceType) 696 ), 697 ts.factory.createPropertyAssignment( 698 ts.factory.createIdentifier(RESOURCE_NAME_PARAMS), 699 ts.factory.createArrayLiteralExpression(argsArr, false) 700 ) 701 ]; 702 703 addBundleAndModuleParam(propertyArray); 704 705 const resourceParams: ts.ObjectLiteralExpression = ts.factory.createObjectLiteralExpression( 706 propertyArray, false); 707 return resourceParams; 708} 709 710function preCheckResourceData(resourceData: string[], resources: object, pos: number, 711 previewLog: {isAcceleratePreview: boolean, log: LogInfo[]}): boolean { 712 if (previewLog.isAcceleratePreview) { 713 return validateResourceData(resourceData, resources, pos, previewLog.log, true); 714 } else { 715 return validateResourceData(resourceData, resources, pos, transformLog.errors, false); 716 } 717} 718 719function validateResourceData(resourceData: string[], resources: object, pos: number, log: LogInfo[], isAcceleratePreview: boolean): boolean { 720 if (resourceData.length !== 3) { 721 log.push({ 722 type: LogType.ERROR, 723 message: 'The input parameter is not supported.', 724 pos: pos 725 }); 726 } else { 727 if (!isAcceleratePreview && process.env.compileTool === 'rollup' && process.env.compileMode === 'moduleJson') { 728 storedFileInfo.collectResourceInFile(resourceData[1] + '_' + resourceData[2], path.resolve(resourceFileName)); 729 } 730 if (!resources[resourceData[0]]) { 731 log.push({ 732 type: LogType.ERROR, 733 message: `Unknown resource source '${resourceData[0]}'.`, 734 pos: pos 735 }); 736 } else if (!resources[resourceData[0]][resourceData[1]]) { 737 log.push({ 738 type: LogType.ERROR, 739 message: `Unknown resource type '${resourceData[1]}'.`, 740 pos: pos 741 }); 742 } else if (!resources[resourceData[0]][resourceData[1]][resourceData[2]]) { 743 log.push({ 744 type: LogType.ERROR, 745 message: `Unknown resource name '${resourceData[2]}'.`, 746 pos: pos 747 }); 748 } else { 749 return true; 750 } 751 } 752 return false; 753} 754 755function isWorker(node: ts.Node): boolean { 756 return ts.isNewExpression(node) && ts.isPropertyAccessExpression(node.expression) && 757 ts.isIdentifier(node.expression.name) && 758 node.expression.name.escapedText.toString() === WORKER_OBJECT; 759} 760 761function processWorker(node: ts.NewExpression): ts.Node { 762 if (node.arguments.length && ts.isStringLiteral(node.arguments[0])) { 763 const args: ts.Expression[] = Array.from(node.arguments); 764 // @ts-ignore 765 const workerPath: string = node.arguments[0].text; 766 const stringNode: ts.StringLiteral = ts.factory.createStringLiteral( 767 workerPath.replace(/\.ts$/, '.js')); 768 args.splice(0, 1, stringNode); 769 return ts.factory.updateNewExpression(node, node.expression, node.typeArguments, args); 770 } 771 return node; 772} 773 774export function processAnimateToOrImmediately(node: ts.CallExpression): ts.CallExpression { 775 return ts.factory.updateCallExpression(node, ts.factory.createPropertyAccessExpression( 776 ts.factory.createIdentifier(GLOBAL_CONTEXT), 777 ts.factory.createIdentifier(node.expression.escapedText.toString())), 778 node.typeArguments, node.arguments); 779} 780 781function processExtend(node: ts.FunctionDeclaration, log: LogInfo[], 782 decoratorName: string): ts.FunctionDeclaration { 783 const componentName: string = isExtendFunction(node, { decoratorName: '', componentName: '' }, true); 784 if (componentName && node.body && node.body.statements.length) { 785 const statementArray: ts.Statement[] = []; 786 let bodynode: ts.Block; 787 if (decoratorName === COMPONENT_EXTEND_DECORATOR) { 788 const attrSet: ts.CallExpression = node.body.statements[0].expression; 789 if (isOriginalExtend(node.body)) { 790 const changeCompName: ts.ExpressionStatement = ts.factory.createExpressionStatement(processExtendBody(attrSet)); 791 bindComponentAttr(changeCompName as ts.ExpressionStatement, 792 ts.factory.createIdentifier(componentName), statementArray, log); 793 } else { 794 bodynode = ts.visitEachChild(node.body, traverseExtendExpression, contextGlobal); 795 } 796 let extendFunctionName: string; 797 if (node.name.getText().startsWith('__' + componentName + '__')) { 798 extendFunctionName = node.name.getText(); 799 } else { 800 extendFunctionName = '__' + componentName + '__' + node.name.getText(); 801 collectExtend(EXTEND_ATTRIBUTE, componentName, node.name.escapedText.toString()); 802 } 803 return ts.factory.updateFunctionDeclaration(node, ts.getModifiers(node), node.asteriskToken, 804 ts.factory.createIdentifier(extendFunctionName), node.typeParameters, 805 node.parameters, ts.factory.createToken(ts.SyntaxKind.VoidKeyword), isOriginalExtend(node.body) ? 806 ts.factory.updateBlock(node.body, statementArray) : bodynode); 807 } 808 if (decoratorName === COMPONENT_ANIMATABLE_EXTEND_DECORATOR) { 809 bindComponentAttr(node.body.statements[0], 810 ts.factory.createIdentifier(componentName), statementArray, log); 811 return ts.factory.updateFunctionDeclaration(node, ts.getModifiers(node), node.asteriskToken, 812 node.name, node.typeParameters, 813 [...node.parameters, ...createAnimatableParameterNode()], ts.factory.createToken(ts.SyntaxKind.VoidKeyword), 814 ts.factory.updateBlock(node.body, createAnimatableBody(componentName, node.name, 815 node.parameters, statementArray))); 816 } 817 } 818 function traverseExtendExpression(node: ts.Node): ts.Node { 819 if (ts.isExpressionStatement(node) && isDollarNode(node, componentName)) { 820 const changeCompName: ts.ExpressionStatement = 821 ts.factory.createExpressionStatement(processExtendBody(node.expression, componentName)); 822 const statementArray: ts.Statement[] = []; 823 bindComponentAttr(changeCompName, ts.factory.createIdentifier(componentName), statementArray, []); 824 return ts.factory.createBlock(statementArray, true); 825 } 826 return ts.visitEachChild(node, traverseExtendExpression, contextGlobal); 827 } 828} 829 830function createAnimatableParameterNode(): ts.ParameterDeclaration[] { 831 return [ 832 ts.factory.createParameterDeclaration( 833 undefined, undefined, ts.factory.createIdentifier(ELMTID)), 834 ts.factory.createParameterDeclaration( 835 undefined, undefined, ts.factory.createIdentifier(ISINITIALRENDER)), 836 ts.factory.createParameterDeclaration( 837 undefined, undefined, ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)) 838 ]; 839} 840 841function createAnimatableBody(componentName: string, funcName: ts.Identifier, 842 parameters: ts.NodeArray<ts.ParameterDeclaration>, attrArray: ts.Statement[]): ts.Statement[] { 843 const paramNode: ts.Identifier[] = []; 844 parameters.forEach((item: ts.ParameterDeclaration) => { 845 if (item.name && ts.isIdentifier(item.name)) { 846 paramNode.push(item.name); 847 } 848 }); 849 return [ 850 ts.factory.createIfStatement( 851 ts.factory.createIdentifier(ISINITIALRENDER), 852 ts.factory.createBlock([ 853 createAnimatableProperty(componentName, funcName, parameters, paramNode, attrArray), 854 ...attrArray 855 ], true), 856 ts.factory.createBlock([ 857 ts.factory.createExpressionStatement(ts.factory.createCallExpression( 858 ts.factory.createPropertyAccessExpression( 859 ts.factory.createIdentifier(componentName), 860 ts.factory.createIdentifier(UPDATE_ANIMATABLE_PROPERTY) 861 ), undefined, 862 [ts.factory.createStringLiteral(funcName.escapedText.toString()), ...paramNode] 863 )) 864 ]) 865 ) 866 ]; 867} 868 869function createAnimatableProperty(componentName: string, funcName: ts.Identifier, 870 parameters: ts.NodeArray<ts.ParameterDeclaration>, 871 paramNode: ts.Identifier[], attrArray: ts.Statement[]) { 872 const componentIdentifier: ts.Identifier = ts.factory.createIdentifier(componentName); 873 return ts.factory.createExpressionStatement( 874 ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( 875 componentIdentifier, 876 ts.factory.createIdentifier(CREATE_ANIMATABLE_PROPERTY)), 877 undefined, [ 878 ts.factory.createStringLiteral(funcName.escapedText.toString()), 879 ...paramNode, 880 ts.factory.createArrowFunction(undefined, undefined, parameters, undefined, 881 ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), 882 ts.factory.createBlock([ 883 createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID), 884 createAnimatableFrameNode(componentName), 885 ...attrArray, 886 createViewStackProcessorStatement(STOPGETACCESSRECORDING), 887 createAnimatableUpdateFunc() 888 ], true)) 889 ] 890 ) 891 ); 892} 893 894function createAnimatableFrameNode(componentName: string): ts.ExpressionStatement { 895 return ts.factory.createExpressionStatement(ts.factory.createCallExpression( 896 ts.factory.createPropertyAccessExpression( 897 ts.factory.createIdentifier(VIEW_STACK_PROCESSOR), 898 ts.factory.createIdentifier(GET_AND_PUSH_FRAME_NODE) 899 ), undefined, 900 [ 901 ts.factory.createStringLiteral(componentName), 902 ts.factory.createIdentifier(ELMTID) 903 ] 904 )); 905} 906 907function createAnimatableUpdateFunc(): ts.ExpressionStatement { 908 return ts.factory.createExpressionStatement(ts.factory.createCallExpression( 909 ts.factory.createPropertyAccessExpression( 910 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), 911 ts.factory.createIdentifier(FINISH_UPDATE_FUNC) 912 ), undefined, [ts.factory.createIdentifier(ELMTID)] 913 )); 914} 915 916function processConcurrent(node: ts.FunctionDeclaration): ts.FunctionDeclaration { 917 if (node.body) { 918 const statementArray: ts.Statement[] = 919 [ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use concurrent')), 920 ...node.body.statements]; 921 return ts.factory.updateFunctionDeclaration(node, ts.getModifiers(node), node.asteriskToken, node.name, 922 node.typeParameters, node.parameters, node.type, ts.factory.updateBlock(node.body, statementArray)); 923 } 924 return node; 925} 926 927function processClassSendable(node: ts.ClassDeclaration): ts.ClassDeclaration { 928 let hasConstructor = false; 929 let updatedMembers: ts.NodeArray<ts.ClassElement> = node.members; 930 let updatedModifiers: ts.NodeArray<ts.ModifierLike> = node.modifiers; 931 932 updatedModifiers = ts.factory.createNodeArray( 933 updatedModifiers.filter(decorator => { 934 const originalDecortor: string = decorator.getText().replace(/\(.*\)$/, '').trim(); 935 return originalDecortor !== COMPONENT_SENDABLE_DECORATOR; 936 }) 937 ); 938 939 for (const member of node.members) { 940 if (ts.isConstructorDeclaration(member)) { 941 hasConstructor = true; 942 const constructor: ts.ConstructorDeclaration = member as ts.ConstructorDeclaration; 943 944 const statementArray: ts.Statement[] = [ 945 ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable')), 946 ...constructor.body.statements 947 ]; 948 949 const updatedConstructor: ts.ConstructorDeclaration = ts.factory.updateConstructorDeclaration(constructor, constructor.modifiers, 950 constructor.parameters, ts.factory.updateBlock(constructor.body, statementArray)); 951 952 updatedMembers = ts.factory.createNodeArray( 953 updatedMembers.map(member => (member === constructor ? updatedConstructor : member)) 954 ); 955 break; 956 } 957 } 958 959 if (!hasConstructor) { 960 const constructor: ts.ConstructorDeclaration = ts.factory.createConstructorDeclaration( 961 undefined, 962 [], 963 ts.factory.createBlock( 964 [ts.factory.createExpressionStatement(ts.factory.createStringLiteral('use sendable'))], 965 true 966 ) 967 ); 968 updatedMembers = ts.factory.createNodeArray([constructor, ...(updatedMembers || [])]); 969 } 970 971 node = ts.factory.updateClassDeclaration(node, updatedModifiers, node.name, node.typeParameters, 972 node.heritageClauses, updatedMembers); 973 974 return node; 975} 976 977export function isOriginalExtend(node: ts.Block): boolean { 978 let innerNode: ts.Node = node.statements[0]; 979 if (node.statements.length === 1 && ts.isExpressionStatement(innerNode)) { 980 while (innerNode.expression) { 981 innerNode = innerNode.expression; 982 } 983 if (ts.isIdentifier(innerNode) && innerNode.pos && innerNode.end && innerNode.pos === innerNode.end && 984 innerNode.escapedText.toString().match(/Instance$/)) { 985 return true; 986 } 987 } 988 return false; 989} 990 991function isDollarNode(node: ts.ExpressionStatement, componentName: string): boolean { 992 let innerNode: ts.Node = node; 993 while (innerNode.expression) { 994 innerNode = innerNode.expression; 995 } 996 let changedIdentifier: string = '$'; 997 if (process.env.compileTool === 'rollup' && storedFileInfo.reUseProgram) { 998 changedIdentifier = `${componentName}Instance`; 999 } 1000 if (ts.isIdentifier(innerNode) && innerNode.getText() === changedIdentifier) { 1001 return true; 1002 } else { 1003 return false; 1004 } 1005} 1006 1007function processExtendBody(node: ts.Node, componentName?: string): ts.Expression { 1008 switch (node.kind) { 1009 case ts.SyntaxKind.CallExpression: 1010 return ts.factory.createCallExpression(processExtendBody(node.expression, componentName), 1011 undefined, node.arguments); 1012 case ts.SyntaxKind.PropertyAccessExpression: 1013 return ts.factory.createPropertyAccessExpression( 1014 processExtendBody(node.expression, componentName), node.name); 1015 case ts.SyntaxKind.Identifier: 1016 if (!componentName) { 1017 return ts.factory.createIdentifier(node.escapedText.toString().replace(INSTANCE, '')); 1018 } else { 1019 return ts.factory.createIdentifier(componentName); 1020 } 1021 } 1022} 1023 1024export function collectExtend(collectionSet: Map<string, Set<string>>, component: string, attribute: string): void { 1025 if (collectionSet.has(component)) { 1026 collectionSet.get(component).add(attribute); 1027 } else { 1028 collectionSet.set(component, new Set([attribute])); 1029 } 1030} 1031 1032export function isExtendFunction(node: ts.FunctionDeclaration, extendResult: ExtendResult, 1033 checkArguments: boolean = false): string { 1034 const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 1035 if (decorators && decorators.length) { 1036 for (let i = 0, len = decorators.length; i < len; i++) { 1037 if (ts.isCallExpression(decorators[i].expression)) { 1038 parseExtendNode(decorators[i].expression as ts.CallExpression, extendResult, checkArguments); 1039 if (CHECK_EXTEND_DECORATORS.includes(extendResult.decoratorName) && extendResult.componentName) { 1040 return extendResult.componentName; 1041 } 1042 } 1043 } 1044 } 1045 return null; 1046} 1047 1048function parseExtendNode(node: ts.CallExpression, extendResult: ExtendResult, checkArguments: boolean): void { 1049 if (ts.isIdentifier(node.expression)) { 1050 extendResult.decoratorName = node.expression.escapedText.toString(); 1051 if (checkArguments && CHECK_EXTEND_DECORATORS.includes(extendResult.decoratorName) && 1052 node.arguments && node.arguments.length !== 1) { 1053 transformLog.errors.push({ 1054 type: LogType.ERROR, 1055 message: `@${extendResult.decoratorName} should have one and only one parameter`, 1056 pos: node.getStart() 1057 }); 1058 } 1059 } 1060 if (node.arguments.length && ts.isIdentifier(node.arguments[0])) { 1061 extendResult.componentName = node.arguments[0].escapedText.toString(); 1062 } 1063} 1064 1065function createEntryNode(node: ts.SourceFile, context: ts.TransformationContext, 1066 entryNodeKey: ts.Expression, id: number): ts.SourceFile { 1067 let cardRelativePath: string; 1068 if (projectConfig && projectConfig.cardObj) { 1069 cardRelativePath = projectConfig.cardObj[resourceFileName]; 1070 } 1071 if (componentCollection.previewComponent.length === 0 || !projectConfig.isPreview) { 1072 if (componentCollection.entryComponent) { 1073 if (!partialUpdateConfig.partialUpdateMode) { 1074 const entryNode: ts.ExpressionStatement = 1075 createEntryFunction(componentCollection.entryComponent, context, 1076 cardRelativePath, entryNodeKey, id) as ts.ExpressionStatement; 1077 return context.factory.updateSourceFile(node, [...node.statements, entryNode]); 1078 } else { 1079 const entryNodes: ts.ExpressionStatement[] = 1080 createEntryFunction(componentCollection.entryComponent, context, 1081 cardRelativePath, entryNodeKey, id) as ts.ExpressionStatement[]; 1082 return entryNodes ? 1083 context.factory.updateSourceFile(node, [...node.statements, ...entryNodes]) : 1084 context.factory.updateSourceFile(node, [...node.statements]); 1085 } 1086 } else { 1087 return node; 1088 } 1089 } else { 1090 const statementsArray: ts.Statement = 1091 createPreviewComponentFunction(componentCollection.entryComponent, context, cardRelativePath, entryNodeKey, id); 1092 return context.factory.updateSourceFile(node, [...node.statements, statementsArray]); 1093 } 1094} 1095 1096function createEntryFunction(name: string, context: ts.TransformationContext, cardRelativePath: string, 1097 entryNodeKey: ts.Expression, id: number): ts.ExpressionStatement | (ts.ExpressionStatement | ts.Block | ts.IfStatement)[] { 1098 const newArray: ts.Expression[] = [ 1099 context.factory.createStringLiteral(id.toString()), 1100 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1101 context.factory.createObjectLiteralExpression([], false) 1102 ]; 1103 const [localStorageName, entryOptionNode]: [string, ts.Expression] = addStorageParam(name); 1104 if (localStorageName && entryNodeKey) { 1105 newArray.push(entryNodeKey); 1106 } 1107 const newExpressionParams: any[] = [ 1108 context.factory.createNewExpression( 1109 context.factory.createIdentifier(name), undefined, newArray)]; 1110 addCardStringliteral(newExpressionParams, context, cardRelativePath); 1111 if (!partialUpdateConfig.partialUpdateMode) { 1112 const newExpressionStatement: ts.ExpressionStatement = 1113 context.factory.createExpressionStatement(context.factory.createCallExpression( 1114 context.factory.createIdentifier(cardRelativePath ? CARD_ENTRY_FUNCTION_NAME : 1115 PAGE_ENTRY_FUNCTION_NAME), undefined, newExpressionParams)); 1116 return newExpressionStatement; 1117 } else { 1118 if (cardRelativePath) { 1119 if (entryOptionNode && ts.isObjectLiteralExpression(entryOptionNode)) { 1120 transformLog.errors.push({ 1121 type: LogType.ERROR, 1122 message: `@Entry doesn't support {} parameter in card`, 1123 pos: componentCollection.entryComponentPos 1124 }); 1125 } 1126 return [ 1127 createStartGetAccessRecording(context), 1128 createLoadDocument(context, name, cardRelativePath, localStorageName, entryNodeKey), 1129 createStopGetAccessRecording(context) 1130 ]; 1131 } else { 1132 return createLoadPageConditionalJudgMent(context, name, cardRelativePath, localStorageName, entryOptionNode); 1133 } 1134 } 1135} 1136 1137function createLoadPageConditionalJudgMent(context: ts.TransformationContext, name: string, 1138 cardRelativePath: string, localStorageName: string, entryOptionNode: ts.Expression, 1139 argsArr: ts.Expression[] = undefined, isComponentPreview: boolean = false) 1140 : (ts.ExpressionStatement | ts.Block | ts.IfStatement)[] { 1141 let isObject: boolean = false; 1142 let routeNameNode: ts.Expression; 1143 let storageNode: ts.Expression; 1144 if (!entryOptionNode) { 1145 let originArray: ts.ExpressionStatement[]; 1146 if (projectConfig.minAPIVersion > 10) { 1147 const newArray: ts.Expression[] = [ 1148 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1149 context.factory.createObjectLiteralExpression([], false) 1150 ]; 1151 const newExpressionParams: any[] = [ 1152 context.factory.createNewExpression( 1153 context.factory.createIdentifier(name), 1154 undefined, newArray)]; 1155 originArray = [ 1156 createRegisterNamedRoute(context, newExpressionParams, false, undefined, false) 1157 ]; 1158 } else { 1159 originArray = [ 1160 createStartGetAccessRecording(context), 1161 createLoadDocument(context, name, cardRelativePath, localStorageName, entryOptionNode), 1162 createStopGetAccessRecording(context) 1163 ]; 1164 } 1165 return originArray; 1166 } 1167 if (ts.isObjectLiteralExpression(entryOptionNode)) { 1168 isObject = true; 1169 if (entryOptionNode.properties) { 1170 entryOptionNode.properties.forEach((property) => { 1171 if (ts.isPropertyAssignment(property) && property.name && ts.isIdentifier(property.name)) { 1172 if (property.name.escapedText.toString() === ROUTE_NAME) { 1173 routeNameNode = property.initializer; 1174 } else if (property.name.escapedText.toString() === STORAGE) { 1175 storageNode = property.initializer; 1176 } 1177 } 1178 }); 1179 } 1180 } else { 1181 isObject = false; 1182 } 1183 return generateLoadDocumentEntrance(isObject, routeNameNode, storageNode, isComponentPreview, context, 1184 name, cardRelativePath, entryOptionNode, argsArr); 1185} 1186 1187function generateLoadDocumentEntrance(isObject: boolean, routeNameNode: ts.Expression, 1188 storageNode: ts.Expression, isComponentPreview: boolean, context: ts.TransformationContext, 1189 name: string, cardRelativePath: string, entryOptionNode: ts.Expression, 1190 argsArr: ts.Expression[]): (ts.ExpressionStatement | ts.Block | ts.IfStatement)[] { 1191 if (isObject) { 1192 if (routeNameNode && !storageNode) { 1193 return isComponentPreview ? [ 1194 ...assignRouteNameAndStorage(routeNameNode), 1195 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1196 routeNameNode, storageNode, true, false, false, argsArr) 1197 ] : [ts.factory.createBlock([ 1198 ...assignRouteNameAndStorage(routeNameNode), 1199 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1200 routeNameNode, storageNode, true, false, false, argsArr) 1201 ])]; 1202 } else if (!routeNameNode && !storageNode) { 1203 return isComponentPreview ? [ 1204 ...assignRouteNameAndStorage(routeNameNode), 1205 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1206 routeNameNode, storageNode, false, false, true, argsArr) 1207 ] : [ts.factory.createBlock([ 1208 ...assignRouteNameAndStorage(routeNameNode), 1209 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1210 routeNameNode, storageNode, false, false, true, argsArr) 1211 ])]; 1212 } else if (!routeNameNode && storageNode) { 1213 return isComponentPreview ? [ 1214 ...assignRouteNameAndStorage(routeNameNode), 1215 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1216 routeNameNode, storageNode, false, true, true, argsArr) 1217 ] : [ts.factory.createBlock([ 1218 ...assignRouteNameAndStorage(routeNameNode), 1219 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1220 routeNameNode, storageNode, false, true, true, argsArr) 1221 ])]; 1222 } else { 1223 return isComponentPreview ? [ 1224 ...assignRouteNameAndStorage(routeNameNode), 1225 judgeRouteNameAndStorage(context, name, cardRelativePath, isObject, entryOptionNode, routeNameNode, storageNode, argsArr) 1226 ] : [ts.factory.createBlock([ 1227 ...assignRouteNameAndStorage(routeNameNode), 1228 judgeRouteNameAndStorage(context, name, cardRelativePath, isObject, entryOptionNode, routeNameNode, storageNode, argsArr) 1229 ])]; 1230 } 1231 } else { 1232 return [ 1233 judgeRouteNameAndStorage(context, name, cardRelativePath, isObject, entryOptionNode, routeNameNode, storageNode, argsArr)]; 1234 } 1235} 1236 1237function judgeRouteNameAndStorage(context: ts.TransformationContext, name: string, 1238 cardRelativePath: string, isObject: boolean, entryOptionNode: ts.Expression, routeNameNode: ts.Expression, 1239 storageNode: ts.Expression, argsArr: ts.Expression[] = undefined): ts.IfStatement { 1240 return isObject ? judgeRouteNameAndStorageForObj(context, name, cardRelativePath, isObject, entryOptionNode, 1241 routeNameNode, storageNode, argsArr) : judgeRouteNameAndStorageForIdentifier(context, name, 1242 cardRelativePath, isObject, entryOptionNode, routeNameNode, storageNode, argsArr); 1243} 1244 1245function judgeRouteNameAndStorageForObj(context: ts.TransformationContext, name: string, 1246 cardRelativePath: string, isObject: boolean, entryOptionNode: ts.Expression, routeNameNode: ts.Expression, 1247 storageNode: ts.Expression, argsArr: ts.Expression[] = undefined): ts.IfStatement { 1248 return ts.factory.createIfStatement( 1249 judgeRouteAndStorageForObject(true), 1250 ts.factory.createBlock( 1251 [ 1252 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1253 routeNameNode, storageNode, true, true, false, argsArr) 1254 ], 1255 true 1256 ), ts.factory.createBlock( 1257 [ 1258 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1259 routeNameNode, storageNode, false, false, true, argsArr) 1260 ], 1261 true 1262 )); 1263} 1264 1265function judgeRouteNameAndStorageForIdentifier(context: ts.TransformationContext, name: string, 1266 cardRelativePath: string, isObject: boolean, entryOptionNode: ts.Expression, routeNameNode: ts.Expression, 1267 storageNode: ts.Expression, argsArr: ts.Expression[] = undefined): ts.IfStatement { 1268 return ts.factory.createIfStatement( 1269 judgeRouteAndStorageForIdentifier(entryOptionNode as ts.Identifier, true, true), 1270 ts.factory.createBlock( 1271 [ 1272 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1273 routeNameNode, storageNode, true, true, false, argsArr) 1274 ], 1275 true 1276 ), 1277 ts.factory.createIfStatement( 1278 judgeRouteAndStorageForIdentifier(entryOptionNode as ts.Identifier, true, false), 1279 ts.factory.createBlock( 1280 [ 1281 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1282 routeNameNode, storageNode, true, false, false, argsArr) 1283 ], 1284 true 1285 ), 1286 ts.factory.createIfStatement( 1287 judgeRouteAndStorageForIdentifier(entryOptionNode as ts.Identifier, false, true), 1288 ts.factory.createBlock( 1289 [ 1290 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1291 routeNameNode, storageNode, false, true, true, argsArr) 1292 ], 1293 true 1294 ), 1295 ts.factory.createBlock( 1296 [ 1297 ...createLoadDocumentWithRoute(context, name, cardRelativePath, isObject, entryOptionNode, 1298 routeNameNode, storageNode, false, false, true, argsArr) 1299 ], 1300 true 1301 ) 1302 ) 1303 ) 1304 ); 1305} 1306 1307function judgeRouteAndStorageForObject(hasRouteName: boolean): ts.BinaryExpression { 1308 return ts.factory.createBinaryExpression( 1309 ts.factory.createIdentifier(ROUTENAME_NODE), 1310 ts.factory.createToken(hasRouteName ? ts.SyntaxKind.ExclamationEqualsToken : ts.SyntaxKind.EqualsEqualsToken), 1311 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED) 1312 ); 1313} 1314 1315function judgeRouteAndStorageForIdentifier(entryOptionNode: ts.Identifier, hasRouteName: boolean, 1316 hasStorage: boolean): ts.BinaryExpression { 1317 return ts.factory.createBinaryExpression( 1318 ts.factory.createBinaryExpression( 1319 entryOptionNode, 1320 ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), 1321 ts.factory.createBinaryExpression( 1322 ts.factory.createPropertyAccessExpression( 1323 entryOptionNode, 1324 ts.factory.createIdentifier(ROUTE_NAME) 1325 ), 1326 ts.factory.createToken(hasRouteName ? ts.SyntaxKind.ExclamationEqualsToken : ts.SyntaxKind.EqualsEqualsToken), 1327 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED) 1328 ) 1329 ), 1330 ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), 1331 ts.factory.createBinaryExpression( 1332 ts.factory.createPropertyAccessExpression( 1333 entryOptionNode, 1334 ts.factory.createIdentifier(STORAGE) 1335 ), 1336 ts.factory.createToken(hasStorage ? ts.SyntaxKind.ExclamationEqualsToken : ts.SyntaxKind.EqualsEqualsToken), 1337 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED) 1338 ) 1339 ); 1340} 1341 1342function assignRouteNameAndStorage(routeNameNode): ts.ExpressionStatement[] { 1343 const assignOperation: ts.VariableStatement[] = []; 1344 if (routeNameNode) { 1345 assignOperation.push(ts.factory.createVariableStatement( 1346 undefined, 1347 ts.factory.createVariableDeclarationList( 1348 [ts.factory.createVariableDeclaration( 1349 ts.factory.createIdentifier(ROUTENAME_NODE), 1350 undefined, 1351 undefined, 1352 routeNameNode 1353 )], 1354 ts.NodeFlags.Let 1355 ) 1356 )); 1357 } 1358 return assignOperation; 1359} 1360 1361function createLoadDocumentWithRoute(context: ts.TransformationContext, name: string, 1362 cardRelativePath: string, isObject: boolean, entryOptionNode: ts.Expression, 1363 routeNameNode: ts.Node, storageNode: ts.Node, hasRouteName: boolean, hasStorage: boolean, 1364 shouldCreateAccsessRecording: boolean, argsArr: ts.Expression[]): ts.ExpressionStatement[] { 1365 const newArray: ts.Expression[] = [ 1366 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1367 context.factory.createObjectLiteralExpression([], false) 1368 ]; 1369 if (entryOptionNode) { 1370 if (!isObject) { 1371 if (hasStorage) { 1372 newArray.push(ts.factory.createPropertyAccessExpression( 1373 entryOptionNode, 1374 ts.factory.createIdentifier(STORAGE) 1375 )); 1376 } else if (!hasRouteName) { 1377 newArray.push(entryOptionNode); 1378 } 1379 } else if (storageNode) { 1380 newArray.push(storageNode); 1381 } 1382 } 1383 const newExpressionParams: any[] = [ 1384 context.factory.createNewExpression( 1385 context.factory.createIdentifier(name), 1386 undefined, newArray)]; 1387 if (argsArr) { 1388 argsArr = []; 1389 componentCollection.previewComponent.forEach((componentName: string) => { 1390 const newExpression: ts.Expression = context.factory.createNewExpression( 1391 context.factory.createIdentifier(componentName), 1392 undefined, 1393 componentName === name ? newArray : newArray.slice(0, newArray.length - 1) 1394 ); 1395 argsArr.push(context.factory.createStringLiteral(componentName), newExpression); 1396 }); 1397 } 1398 if (hasRouteName) { 1399 return [ 1400 shouldCreateAccsessRecording ? createStartGetAccessRecording(context) : undefined, 1401 createRegisterNamedRoute(context, newExpressionParams, isObject, entryOptionNode, hasRouteName), 1402 shouldCreateAccsessRecording ? createStopGetAccessRecording(context) : undefined]; 1403 } else { 1404 if (projectConfig.minAPIVersion > 10) { 1405 return [ 1406 createRegisterNamedRoute(context, newExpressionParams, isObject, entryOptionNode, hasRouteName) 1407 ]; 1408 } else { 1409 return [ 1410 shouldCreateAccsessRecording ? createStartGetAccessRecording(context) : undefined, 1411 context.factory.createExpressionStatement( 1412 context.factory.createCallExpression( 1413 context.factory.createIdentifier(cardRelativePath ? CARD_ENTRY_FUNCTION_NAME : 1414 PAGE_ENTRY_FUNCTION_NAME), undefined, newExpressionParams)), 1415 shouldCreateAccsessRecording ? createStopGetAccessRecording(context) : undefined]; 1416 } 1417 } 1418} 1419 1420function createRegisterNamedRoute(context: ts.TransformationContext, newExpressionParams: ts.NewExpression[], 1421 isObject: boolean, entryOptionNode: ts.Expression, hasRouteName: boolean): ts.ExpressionStatement { 1422 return context.factory.createExpressionStatement(context.factory.createCallExpression( 1423 context.factory.createIdentifier(REGISTER_NAMED_ROUTE), 1424 undefined, 1425 [ 1426 context.factory.createArrowFunction( 1427 undefined, 1428 undefined, 1429 [], 1430 undefined, 1431 context.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), 1432 newExpressionParams[0] 1433 ), 1434 hasRouteName ? isObject ? ts.factory.createIdentifier(ROUTENAME_NODE) : context.factory.createPropertyAccessExpression( 1435 entryOptionNode, 1436 context.factory.createIdentifier(ROUTE_NAME) 1437 ) : ts.factory.createStringLiteral(''), 1438 context.factory.createObjectLiteralExpression( 1439 [ 1440 context.factory.createPropertyAssignment( 1441 context.factory.createIdentifier(RESOURCE_NAME_BUNDLE), 1442 context.factory.createStringLiteral(projectConfig.bundleName || '') 1443 ), 1444 context.factory.createPropertyAssignment( 1445 context.factory.createIdentifier(RESOURCE_NAME_MODULE), 1446 context.factory.createStringLiteral(projectConfig.moduleName || '') 1447 ), 1448 context.factory.createPropertyAssignment( 1449 context.factory.createIdentifier(PAGE_PATH), 1450 context.factory.createStringLiteral( 1451 projectConfig.compileHar ? '' : 1452 path.relative(projectConfig.projectPath || '', resourceFileName).replace(/\\/g, '/').replace(/\.ets$/, '') 1453 ) 1454 ) 1455 ], 1456 false 1457 ) 1458 ] 1459 )); 1460} 1461 1462function createStartGetAccessRecording(context: ts.TransformationContext): ts.ExpressionStatement { 1463 return context.factory.createExpressionStatement( 1464 context.factory.createCallExpression( 1465 context.factory.createPropertyAccessExpression( 1466 context.factory.createIdentifier(VIEWSTACKPROCESSOR), 1467 context.factory.createIdentifier(STARTGETACCESSRECORDINGFOR) 1468 ), 1469 undefined, 1470 [context.factory.createCallExpression( 1471 context.factory.createPropertyAccessExpression( 1472 context.factory.createIdentifier(VIEWSTACKPROCESSOR), 1473 context.factory.createIdentifier(ALLOCATENEWELMETIDFORNEXTCOMPONENT) 1474 ), 1475 undefined, 1476 [] 1477 )] 1478 ) 1479 ); 1480} 1481 1482function createLoadDocument(context: ts.TransformationContext, name: string, 1483 cardRelativePath: string, localStorageName: string, entryNodeKey: ts.Expression): ts.ExpressionStatement { 1484 const newArray: ts.Expression[] = [ 1485 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1486 context.factory.createObjectLiteralExpression([], false) 1487 ]; 1488 if (localStorageName && entryNodeKey) { 1489 newArray.push(entryNodeKey); 1490 } 1491 const newExpressionParams: any[] = [ 1492 context.factory.createNewExpression( 1493 context.factory.createIdentifier(name), 1494 undefined, newArray)]; 1495 addCardStringliteral(newExpressionParams, context, cardRelativePath); 1496 return context.factory.createExpressionStatement( 1497 context.factory.createCallExpression( 1498 context.factory.createIdentifier(cardRelativePath ? CARD_ENTRY_FUNCTION_NAME : 1499 PAGE_ENTRY_FUNCTION_NAME), undefined, newExpressionParams) 1500 ); 1501} 1502 1503function createStopGetAccessRecording(context: ts.TransformationContext): ts.ExpressionStatement { 1504 return context.factory.createExpressionStatement( 1505 context.factory.createCallExpression( 1506 context.factory.createPropertyAccessExpression( 1507 context.factory.createIdentifier(VIEWSTACKPROCESSOR), 1508 context.factory.createIdentifier(STOPGETACCESSRECORDING) 1509 ), 1510 undefined, 1511 [] 1512 ) 1513 ); 1514} 1515 1516function addStorageParam(name: string): [string, ts.Expression] { 1517 let localStorageName: string; 1518 let localStorageNode: ts.Identifier | ts.ObjectLiteralExpression; 1519 const localStorageNum: number = (localStorageLinkCollection.get(name) || new Set()).size + 1520 (localStoragePropCollection.get(name) || new Set()).size; 1521 if (componentCollection.entryComponent === name && componentCollection.localStorageNode) { 1522 localStorageNode = componentCollection.localStorageNode; 1523 } 1524 if (componentCollection.entryComponent === name && componentCollection.localStorageName) { 1525 localStorageName = componentCollection.localStorageName; 1526 } else if (componentCollection.entryComponent === name && !componentCollection.localStorageName && 1527 !componentCollection.localStorageNode && localStorageNum) { 1528 transformLog.errors.push({ 1529 type: LogType.WARN, 1530 message: `@Entry should have a parameter, like '@Entry (storage)'.`, 1531 pos: componentCollection.entryComponentPos 1532 }); 1533 } 1534 return [localStorageName, localStorageNode]; 1535} 1536 1537function createPreviewComponentFunction(name: string, context: ts.TransformationContext, 1538 cardRelativePath: string, entryNodeKey: ts.Expression, id: number): ts.Statement { 1539 const newArray: ts.Expression[] = partialUpdateConfig.partialUpdateMode ? 1540 [ 1541 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1542 context.factory.createObjectLiteralExpression([], false) 1543 ] : 1544 [ 1545 context.factory.createStringLiteral(id.toString()), 1546 context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1547 context.factory.createObjectLiteralExpression([], false) 1548 ]; 1549 const [localStorageName, entryOptionNode]: [string, ts.Expression] = addStorageParam(name); 1550 if (entryOptionNode) { 1551 newArray.push(entryOptionNode); 1552 } 1553 const argsArr: ts.Expression[] = []; 1554 componentCollection.previewComponent.forEach(componentName => { 1555 const newExpression: ts.Expression = context.factory.createNewExpression( 1556 context.factory.createIdentifier(componentName), 1557 undefined, 1558 newArray 1559 ); 1560 argsArr.push(context.factory.createStringLiteral(componentName)); 1561 argsArr.push(newExpression); 1562 }); 1563 const newExpressionParams: any[] = name ? [context.factory.createNewExpression( 1564 context.factory.createIdentifier(name), undefined, newArray)] : []; 1565 addCardStringliteral(newExpressionParams, context, cardRelativePath); 1566 const ifStatement: ts.Statement = context.factory.createIfStatement( 1567 context.factory.createCallExpression( 1568 context.factory.createIdentifier(GET_PREVIEW_FLAG_FUNCTION_NAME), 1569 undefined, 1570 [] 1571 ), 1572 context.factory.createBlock( 1573 [...storePreviewComponents(name, entryOptionNode, argsArr), 1574 context.factory.createExpressionStatement(context.factory.createCallExpression( 1575 context.factory.createIdentifier(PREVIEW_COMPONENT_FUNCTION_NAME), 1576 undefined, 1577 [] 1578 ))], 1579 true 1580 ), 1581 context.factory.createBlock( 1582 createPreviewElseBlock(name, context, cardRelativePath, localStorageName, entryOptionNode, 1583 newExpressionParams, argsArr), 1584 true 1585 ) 1586 ); 1587 return ifStatement; 1588} 1589 1590function storePreviewComponents(name: string, entryOptionNode: ts.Expression, argsArr: ts.Expression[]): 1591 (ts.ExpressionStatement|ts.VariableStatement|ts.IfStatement)[] { 1592 let isObject: boolean = false; 1593 let storageNode: ts.Expression; 1594 if (!entryOptionNode) { 1595 return [ts.factory.createExpressionStatement(ts.factory.createCallExpression( 1596 ts.factory.createIdentifier(STORE_PREVIEW_COMPONENTS), 1597 undefined, 1598 [ 1599 ts.factory.createNumericLiteral(componentCollection.previewComponent.length), 1600 ...argsArr 1601 ] 1602 ))]; 1603 } 1604 if (ts.isObjectLiteralExpression(entryOptionNode)) { 1605 isObject = true; 1606 if (entryOptionNode.properties) { 1607 entryOptionNode.properties.forEach((property) => { 1608 if (ts.isPropertyAssignment(property) && property.name && ts.isIdentifier(property.name) && 1609 property.name.escapedText.toString() === STORAGE) { 1610 storageNode = property.initializer; 1611 } 1612 }); 1613 } 1614 } else { 1615 isObject = false; 1616 } 1617 const newArray: ts.Expression[] = [ 1618 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1619 ts.factory.createObjectLiteralExpression([], false) 1620 ]; 1621 const newArgsArr: ts.Expression[] = []; 1622 if (isObject) { 1623 return processObjectStorage(storageNode, newArray, name, newArgsArr); 1624 } else { 1625 return [ts.factory.createIfStatement( 1626 ts.factory.createBinaryExpression( 1627 entryOptionNode, 1628 ts.factory.createToken(ts.SyntaxKind.AmpersandAmpersandToken), 1629 ts.factory.createBinaryExpression( 1630 ts.factory.createPropertyAccessExpression( 1631 entryOptionNode, 1632 ts.factory.createIdentifier(STORAGE) 1633 ), 1634 ts.factory.createToken(ts.SyntaxKind.ExclamationEqualsToken), 1635 ts.factory.createIdentifier('undefined') 1636 ) 1637 ), 1638 ts.factory.createBlock( 1639 [returnStorePreview(entryOptionNode, true, name)], 1640 true 1641 ), 1642 ts.factory.createBlock( 1643 [returnStorePreview(entryOptionNode, false, name)], 1644 true 1645 ) 1646 )]; 1647 } 1648} 1649 1650function processObjectStorage(storageNode: ts.Expression, newArray: ts.Expression[], name: string, 1651 newArgsArr: ts.Expression[]): (ts.ExpressionStatement|ts.VariableStatement)[] { 1652 if (storageNode) { 1653 newArray.push(ts.factory.createIdentifier(STORAGE_NODE)); 1654 componentCollection.previewComponent.forEach(componentName => { 1655 const newExpression: ts.Expression = ts.factory.createNewExpression( 1656 ts.factory.createIdentifier(componentName), 1657 undefined, 1658 componentName === name ? newArray : newArray.slice(0, newArray.length - 1) 1659 ); 1660 newArgsArr.push(ts.factory.createStringLiteral(componentName)); 1661 newArgsArr.push(newExpression); 1662 }); 1663 return [ts.factory.createVariableStatement( 1664 undefined, 1665 ts.factory.createVariableDeclarationList( 1666 [ts.factory.createVariableDeclaration( 1667 ts.factory.createIdentifier(STORAGE_NODE), 1668 undefined, 1669 undefined, 1670 storageNode 1671 )], 1672 ts.NodeFlags.Let 1673 ) 1674 ), ts.factory.createExpressionStatement(ts.factory.createCallExpression( 1675 ts.factory.createIdentifier(STORE_PREVIEW_COMPONENTS), 1676 undefined, 1677 [ 1678 ts.factory.createNumericLiteral(componentCollection.previewComponent.length), 1679 ...newArgsArr 1680 ] 1681 ))]; 1682 } else { 1683 componentCollection.previewComponent.forEach(componentName => { 1684 const newExpression: ts.Expression = ts.factory.createNewExpression( 1685 ts.factory.createIdentifier(componentName), 1686 undefined, 1687 newArray 1688 ); 1689 newArgsArr.push(ts.factory.createStringLiteral(componentName)); 1690 newArgsArr.push(newExpression); 1691 }); 1692 return [ts.factory.createExpressionStatement(ts.factory.createCallExpression( 1693 ts.factory.createIdentifier(STORE_PREVIEW_COMPONENTS), 1694 undefined, 1695 [ 1696 ts.factory.createNumericLiteral(componentCollection.previewComponent.length), 1697 ...newArgsArr 1698 ] 1699 ))]; 1700 } 1701} 1702 1703function returnStorePreview(entryOptionNode: ts.Expression, hasStorage: boolean, name: string): ts.ExpressionStatement { 1704 const newArray: ts.Expression[] = [ 1705 ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), 1706 ts.factory.createObjectLiteralExpression([], false) 1707 ]; 1708 const newArgsArr: ts.Expression[] = []; 1709 newArray.push(hasStorage ? ts.factory.createPropertyAccessExpression( 1710 entryOptionNode, 1711 ts.factory.createIdentifier(STORAGE) 1712 ) : entryOptionNode); 1713 componentCollection.previewComponent.forEach(componentName => { 1714 const newExpression: ts.Expression = ts.factory.createNewExpression( 1715 ts.factory.createIdentifier(componentName), 1716 undefined, 1717 componentName === name ? newArray : newArray.slice(0, newArray.length - 1) 1718 ); 1719 newArgsArr.push(ts.factory.createStringLiteral(componentName)); 1720 newArgsArr.push(newExpression); 1721 }); 1722 return ts.factory.createExpressionStatement(ts.factory.createCallExpression( 1723 ts.factory.createIdentifier(STORE_PREVIEW_COMPONENTS), 1724 undefined, 1725 [ 1726 ts.factory.createNumericLiteral(componentCollection.previewComponent.length), 1727 ...newArgsArr 1728 ] 1729 )); 1730} 1731 1732function createPreviewElseBlock(name: string, context: ts.TransformationContext, cardRelativePath: string, 1733 localStorageName: string, entryOptionNode: ts.Expression, newExpressionParams: ts.Expression[], 1734 argsArr: ts.Expression[]): (ts.ExpressionStatement | ts.IfStatement | ts.Block)[] { 1735 if (name) { 1736 if (!partialUpdateConfig.partialUpdateMode) { 1737 return [context.factory.createExpressionStatement(context.factory.createCallExpression( 1738 context.factory.createIdentifier(STORE_PREVIEW_COMPONENTS), 1739 undefined, 1740 [ 1741 context.factory.createNumericLiteral(componentCollection.previewComponent.length), 1742 ...argsArr 1743 ] 1744 )), 1745 context.factory.createExpressionStatement(context.factory.createCallExpression( 1746 context.factory.createIdentifier(cardRelativePath ? CARD_ENTRY_FUNCTION_NAME : 1747 PAGE_ENTRY_FUNCTION_NAME), undefined, newExpressionParams 1748 ))]; 1749 } else { 1750 if (cardRelativePath) { 1751 if (entryOptionNode && ts.isObjectLiteralExpression(entryOptionNode)) { 1752 transformLog.errors.push({ 1753 type: LogType.ERROR, 1754 message: `@Entry doesn't support {} parameter in card`, 1755 pos: componentCollection.entryComponentPos 1756 }); 1757 } 1758 return [ 1759 name ? createStartGetAccessRecording(context) : undefined, 1760 name ? context.factory.createExpressionStatement(context.factory.createCallExpression( 1761 context.factory.createIdentifier(cardRelativePath ? CARD_ENTRY_FUNCTION_NAME : 1762 PAGE_ENTRY_FUNCTION_NAME), undefined, newExpressionParams 1763 )) : undefined, 1764 name ? createStopGetAccessRecording(context) : undefined 1765 ]; 1766 } 1767 return createLoadPageConditionalJudgMent(context, name, cardRelativePath, localStorageName, 1768 entryOptionNode, argsArr, true); 1769 } 1770 } 1771} 1772 1773export function resetLog(): void { 1774 transformLog.errors = []; 1775} 1776 1777function addCardStringliteral(newExpressionParams: any[], context: ts.TransformationContext, 1778 cardRelativePath: string): void { 1779 if (cardRelativePath) { 1780 newExpressionParams.push(context.factory.createStringLiteral( 1781 projectConfig.bundleName + '/' + projectConfig.moduleName + '/' + 1782 cardRelativePath)); 1783 } 1784} 1785 1786export function validatorCard(log: any[], type: number, pos: number, 1787 name: string = ''): void { 1788 if (projectConfig && projectConfig.cardObj && resourceFileName && 1789 projectConfig.cardObj[resourceFileName]) { 1790 const logInfo: object = { 1791 type: LogType.ERROR, 1792 message: '', 1793 pos: pos 1794 }; 1795 switch (type) { 1796 case CARD_LOG_TYPE_COMPONENTS: 1797 logInfo.message = `Card page cannot use the component ${name}.`; 1798 break; 1799 case CARD_LOG_TYPE_DECORATORS: 1800 logInfo.message = `Card page cannot use ${name}`; 1801 break; 1802 case CARD_LOG_TYPE_IMPORT: 1803 logInfo.message = `Card page cannot use import.`; 1804 break; 1805 } 1806 log.push(logInfo); 1807 } 1808} 1809 1810export function resetProcessUiSyntax(): void { 1811 transformLog = new FileLog(); 1812 contextGlobal = undefined; 1813} 1814