• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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