• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2024 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';
18
19import {
20  COMPONENT_RENDER_FUNCTION,
21  COMPONENT_CREATE_FUNCTION,
22  COMPONENT_POP_FUNCTION,
23  COMPONENT_BUTTON,
24  COMPONENT_CREATE_LABEL_FUNCTION,
25  COMPONENT_CREATE_CHILD_FUNCTION,
26  COMPONENT_FOREACH,
27  COMPONENT_LAZYFOREACH,
28  IS_RENDERING_IN_PROGRESS,
29  FOREACH_OBSERVED_OBJECT,
30  FOREACH_GET_RAW_OBJECT,
31  COMPONENT_IF,
32  COMPONENT_IF_BRANCH_ID_FUNCTION,
33  COMPONENT_IF_UNDEFINED,
34  ATTRIBUTE_ANIMATION,
35  GLOBAL_CONTEXT,
36  COMPONENT_GESTURE,
37  COMPONENT_GESTURE_GROUP,
38  GESTURE_ATTRIBUTE,
39  PARALLEL_GESTURE_ATTRIBUTE,
40  PRIORITY_GESTURE_ATTRIBUTE,
41  GESTURE_ENUM_KEY,
42  GESTURE_ENUM_VALUE_HIGH,
43  GESTURE_ENUM_VALUE_LOW,
44  GESTURE_ENUM_VALUE_PARALLEL,
45  COMPONENT_TRANSITION_NAME,
46  COMPONENT_DEBUGLINE_FUNCTION,
47  ATTRIBUTE_STATESTYLES,
48  THIS,
49  VISUAL_STATE,
50  VIEW_STACK_PROCESSOR,
51  STYLE_ADD_DOUBLE_DOLLAR,
52  STYLE_ADD_DOUBLE_EXCLAMATION,
53  $$_VALUE,
54  $$_CHANGE_EVENT,
55  $$_THIS,
56  $$_NEW_VALUE,
57  $_VALUE,
58  BUILDER_ATTR_NAME,
59  BUILDER_ATTR_BIND,
60  CUSTOM_DIALOG_CONTROLLER_BUILDER,
61  BIND_DRAG_SET,
62  BIND_POPUP_SET,
63  BIND_POPUP,
64  CUSTOM_COMPONENT_DEFAULT,
65  $$,
66  PROPERTIES_ADD_DOUBLE_DOLLAR,
67  PROPERTIES_ADD_DOUBLE_EXCLAMATION,
68  ATTRIBUTE_ID,
69  RESOURCE,
70  ISINITIALRENDER,
71  ELMTID,
72  VIEWSTACKPROCESSOR,
73  STOPGETACCESSRECORDING,
74  STARTGETACCESSRECORDINGFOR,
75  OBSERVECOMPONENTCREATION,
76  OBSERVECOMPONENTCREATION2,
77  DEEPRENDERFUNCTION,
78  ITEMCREATION,
79  ITEMCREATION2,
80  OBSERVEDDEEPRENDER,
81  ItemComponents,
82  FOREACHITEMGENFUNCTION,
83  __LAZYFOREACHITEMGENFUNCTION,
84  _ITEM,
85  FOREACHITEMIDFUNC,
86  __LAZYFOREACHITEMIDFUNC,
87  FOREACHUPDATEFUNCTION,
88  COMPONENT_INITIAL_RENDER_FUNCTION,
89  COMPONENT_REPEAT,
90  REPEAT_EACH,
91  REPEAT_TEMPLATE,
92  LIST_ITEM,
93  IFELSEBRANCHUPDATEFUNCTION,
94  CARD_ENABLE_COMPONENTS,
95  CARD_LOG_TYPE_COMPONENTS,
96  COMPONENT_CONSTRUCTOR_PARENT,
97  RESOURCE_NAME_TYPE,
98  XCOMPONENT_SINGLE_QUOTATION,
99  XCOMPONENT_DOUBLE_QUOTATION,
100  XCOMPONENTTYPE,
101  XCOMPONENTTYPE_CONTAINER,
102  BIND_OBJECT_PROPERTY,
103  TRUE,
104  FALSE,
105  HEADER,
106  INDICATORBUILDER,
107  FOOTER,
108  CALL,
109  CREATE_BIND_COMPONENT,
110  TabContentAndNavDestination,
111  START,
112  END,
113  BUILDER_PARAM_PROXY,
114  BUILDER_TYPE,
115  CHECK_COMPONENT_EXTEND_DECORATOR,
116  CHECK_COMPONENT_ANIMATABLE_EXTEND_DECORATOR,
117  RECYCLE_REUSE_ID,
118  UPDATE_FUNC_BY_ELMT_ID,
119  CREATE_SET_METHOD,
120  CAN_RETAKE,
121  PREVIEW,
122  IDS,
123  PUSH,
124  UPDATE_LAZY_FOREACH_ELEMENTS,
125  INDEX,
126  IS_INITIAL_ITEM,
127  MY_IDS,
128  WRAPBUILDER_BUILDERPROP,
129  WRAPPEDBUILDER_CLASS,
130  ALL_COMPONENTS,
131  ATTRIBUTE_ATTRIBUTE_MODIFIER,
132  ATTRIBUTE_CONTENT_MODIFIER,
133  ATTRIBUTE_MENUITEM_CONTENT_MODIFIER,
134  TITLE,
135  PAGE_PATH,
136  RESOURCE_NAME_MODULE,
137  NAV_DESTINATION,
138  NAVIGATION,
139  CREATE_ROUTER_COMPONENT_COLLECT,
140  NAV_PATH_STACK,
141  IS_USER_CREATE_STACK,
142  REUSE_ATTRIBUTE
143} from './pre_define';
144import {
145  INNER_COMPONENT_NAMES,
146  BUILDIN_CONTAINER_COMPONENT,
147  BUILDIN_STYLE_NAMES,
148  CUSTOM_BUILDER_METHOD,
149  GESTURE_ATTRS,
150  GESTURE_TYPE_NAMES,
151  EXTEND_ATTRIBUTE,
152  NO_DEBUG_LINE_COMPONENT,
153  NEEDPOP_COMPONENT,
154  INNER_STYLE_FUNCTION,
155  GLOBAL_STYLE_FUNCTION,
156  CUSTOM_BUILDER_PROPERTIES,
157  CUSTOM_BUILDER_PROPERTIES_WITHOUTKEY,
158  CUSTOM_BUILDER_CONSTRUCTORS,
159  ID_ATTRS,
160  SPECIFIC_PARENT_COMPONENT,
161  STYLES_ATTRIBUTE,
162  INNER_CUSTOM_LOCALBUILDER_METHOD,
163  COMMON_ATTRS
164} from './component_map';
165import {
166  componentCollection,
167  builderParamObjectCollection,
168  checkAllNode,
169  enumCollection
170} from './validate_ui_syntax';
171import {
172  processCustomComponent,
173  createConditionParent,
174  isRecycle,
175  isReuseInV2
176} from './process_custom_component';
177import {
178  LogType,
179  LogInfo,
180  componentInfo,
181  storedFileInfo
182} from './utils';
183import {
184  globalProgram,
185  partialUpdateConfig,
186  projectConfig
187} from '../main';
188import {
189  transformLog,
190  contextGlobal,
191  validatorCard,
192  builderTypeParameter,
193  resourceFileName
194} from './process_ui_syntax';
195import { regularCollection, getSymbolIfAliased } from './validate_ui_syntax';
196import { contextStackPushOrPop } from './process_component_class';
197import processStructComponentV2, { StructInfo } from './process_struct_componentV2';
198import logMessageCollection from './log_message_collection';
199
200export function processComponentBuild(node: ts.MethodDeclaration,
201  log: LogInfo[]): ts.MethodDeclaration {
202  let newNode: ts.MethodDeclaration;
203  let renderNode: ts.Identifier;
204  if (!partialUpdateConfig.partialUpdateMode) {
205    renderNode = ts.factory.createIdentifier(COMPONENT_RENDER_FUNCTION);
206  } else {
207    renderNode = ts.factory.createIdentifier(COMPONENT_INITIAL_RENDER_FUNCTION);
208  }
209  if (node.body && node.body.statements && node.body.statements.length &&
210    validateRootNode(node, log)) {
211    const componentBlock: ts.Block = processComponentBlock(node.body, false, log);
212    newNode = ts.factory.updateMethodDeclaration(node, ts.getModifiers(node),
213      node.asteriskToken, renderNode, node.questionToken, node.typeParameters, node.parameters,
214      node.type, componentBlock);
215    if (partialUpdateConfig.partialUpdateMode && storedFileInfo.hasLocalBuilderInFile) {
216      componentBlock.statements.unshift(contextStackPushOrPop(ts.factory.createIdentifier(PUSH), [ts.factory.createThis()]));
217      componentBlock.statements.push(contextStackPushOrPop(ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), []));
218    }
219  } else {
220    newNode = ts.factory.updateMethodDeclaration(node, ts.getModifiers(node),
221      node.asteriskToken, renderNode, node.questionToken, node.typeParameters, node.parameters,
222      node.type, node.body);
223  }
224  return newNode;
225}
226
227function createLazyForEachBlockNode(newStatements: ts.Statement[]): ts.IfStatement {
228  return ts.factory.createIfStatement(
229    ts.factory.createBinaryExpression(
230      ts.factory.createBinaryExpression(
231        ts.factory.createIdentifier(IS_INITIAL_ITEM),
232        ts.factory.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken),
233        ts.factory.createIdentifier(COMPONENT_IF_UNDEFINED)
234      ),
235      ts.factory.createToken(ts.SyntaxKind.BarBarToken),
236      ts.factory.createIdentifier(IS_INITIAL_ITEM)
237    ),
238    ts.factory.createBlock(newStatements, true),
239    ts.factory.createBlock([
240      ts.factory.createExpressionStatement(ts.factory.createCallExpression(
241        ts.factory.createPropertyAccessExpression(
242          ts.factory.createThis(),
243          ts.factory.createIdentifier(UPDATE_LAZY_FOREACH_ELEMENTS)
244        ), undefined, [
245          ts.factory.createIdentifier(IDS),
246          storedFileInfo.lazyForEachInfo.forEachParameters.name as ts.Identifier
247        ]
248      ))
249    ], true)
250  );
251}
252
253export type BuilderParamsResult = {
254  firstParam: ts.ParameterDeclaration;
255};
256
257export function parseGlobalBuilderParams(parameters: ts.NodeArray<ts.ParameterDeclaration>,
258  builderParamsResult: BuilderParamsResult) : void {
259  if (partialUpdateConfig.partialUpdateMode && parameters.length && parameters.length === 1 &&
260    ts.isIdentifier(parameters[0].name)) {
261    builderParamsResult.firstParam = parameters[0];
262  }
263}
264
265export function processComponentBlock(node: ts.Block, isLazy: boolean, log: LogInfo[],
266  isTransition: boolean = false, isBuilder: boolean = false, parent: string = undefined,
267  forEachParameters: ts.NodeArray<ts.ParameterDeclaration> = undefined,
268  isGlobalBuilder: boolean = false, builderParamsResult: BuilderParamsResult = null,
269  rootGlobalBuilder: boolean = false, isInRepeatTemplate: boolean = false): ts.Block {
270  const newStatements: ts.Statement[] = [];
271  processComponentChild(node, newStatements, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''},
272    isBuilder, parent, forEachParameters, isGlobalBuilder, isTransition, builderParamsResult, isInRepeatTemplate);
273  if (isLazy && !partialUpdateConfig.partialUpdateMode) {
274    newStatements.unshift(createRenderingInProgress(true));
275  }
276  if (isTransition) {
277    if (!partialUpdateConfig.partialUpdateMode) {
278      newStatements.unshift(ts.factory.createExpressionStatement(
279        createFunction(ts.factory.createIdentifier(COMPONENT_TRANSITION_NAME),
280          ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), null)));
281    } else {
282      newStatements.unshift(createComponentCreationStatement(ts.factory.createExpressionStatement(
283        createFunction(ts.factory.createIdentifier(COMPONENT_TRANSITION_NAME),
284          ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null)), [ts.factory.createExpressionStatement(
285        createFunction(ts.factory.createIdentifier(COMPONENT_TRANSITION_NAME),
286          ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), null))], COMPONENT_TRANSITION_NAME, false, isTransition));
287    }
288    newStatements.push(ts.factory.createExpressionStatement(
289      createFunction(ts.factory.createIdentifier(COMPONENT_TRANSITION_NAME),
290        ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null)));
291  }
292  if (isLazy && !partialUpdateConfig.partialUpdateMode) {
293    newStatements.push(createRenderingInProgress(false));
294  }
295  if (rootGlobalBuilder && isGlobalBuilder && builderParamsResult && builderParamsResult.firstParam) {
296    newStatements.unshift(forkBuilderParamNode(builderParamsResult.firstParam));
297  }
298  if (isLazy && projectConfig.optLazyForEach && storedFileInfo.processLazyForEach &&
299    storedFileInfo.lazyForEachInfo.forEachParameters) {
300    return ts.factory.updateBlock(node, [
301      createMyIdsNode(),
302      createLazyForEachBlockNode(newStatements),
303      ts.factory.createReturnStatement(ts.factory.createIdentifier(MY_IDS))
304    ]);
305  }
306  return ts.factory.updateBlock(node, newStatements);
307}
308
309function createMyIdsNode(): ts.Statement {
310  return ts.factory.createVariableStatement(
311    undefined,
312    ts.factory.createVariableDeclarationList(
313      [ts.factory.createVariableDeclaration(
314        ts.factory.createIdentifier(MY_IDS),
315        undefined,
316        undefined,
317        ts.factory.createArrayLiteralExpression(
318          [],
319          false
320        )
321      )],
322      ts.NodeFlags.Const
323    )
324  );
325}
326
327function visitComponent(node: ts.Node): void {
328  if (storedFileInfo.lazyForEachInfo && !ts.isBlock(node)) {
329    ts.forEachChild(node, (child: ts.Node) => {
330      if (storedFileInfo.lazyForEachInfo.isDependItem) {
331        return;
332      }
333      if (ts.isIdentifier(child)) {
334        const symbol: ts.Symbol = globalProgram.checker.getSymbolAtLocation(child);
335        if (symbol && symbol.valueDeclaration === storedFileInfo.lazyForEachInfo.forEachParameters) {
336          storedFileInfo.lazyForEachInfo.isDependItem = true;
337          return;
338        }
339      }
340      visitComponent(child);
341    });
342  }
343}
344
345function forkBuilderParamNode(node: ts.ParameterDeclaration): ts.Statement {
346  const paramNode: ts.Identifier = node.name as ts.Identifier;
347  return ts.factory.createVariableStatement(
348    undefined,
349    ts.factory.createVariableDeclarationList(
350      [ts.factory.createVariableDeclaration(
351        ts.factory.createIdentifier(`__${paramNode.escapedText.toString()}__`),
352        undefined,
353        undefined,
354        paramNode
355      )],
356      ts.NodeFlags.Const
357    )
358  );
359}
360
361function validateRootNode(node: ts.MethodDeclaration, log: LogInfo[]): boolean {
362  let isValid: boolean = false;
363  if (node.body.statements.length === 1) {
364    const statement: ts.Statement = node.body.statements[0];
365    if (ts.isIfStatement(statement) || validateFirstNode(statement)) {
366      isValid = true;
367    }
368  } else {
369    isValid = false;
370  }
371  if (!isValid) {
372    log.push({
373      type: LogType.ERROR,
374      message: `In an '@Entry' decorated component, the 'build' method can have only one root node,` +
375        ` which must be a container component.`,
376      pos: node.body.statements.pos,
377      code: '10905210'
378    });
379  }
380  return isValid;
381}
382
383function validateFirstNode(node: ts.Statement): boolean {
384  const isEntryComponent: boolean =
385    componentCollection.entryComponent === componentCollection.currentClassName;
386  if (isEntryComponent && !validateContainerComponent(node)) {
387    return false;
388  }
389  return true;
390}
391
392function validateContainerComponent(node: ts.Statement): boolean {
393  if (ts.isExpressionStatement(node) && node.expression &&
394    (ts.isEtsComponentExpression(node.expression) || ts.isCallExpression(node.expression))) {
395    const nameResult: NameResult = { name: null, node: null, arguments: [] };
396    validateEtsComponentNode(node.expression, nameResult);
397    if (nameResult.name && checkContainer(nameResult.name, nameResult.node)) {
398      return true;
399    }
400  }
401  return false;
402}
403
404interface supplementType {
405  isAcceleratePreview: boolean,
406  line: number,
407  column: number,
408  fileName: string
409}
410
411let newsupplement: supplementType = {
412  isAcceleratePreview: false,
413  line: 0,
414  column: 0,
415  fileName: ''
416};
417
418type NameResult = {
419  name: string,
420  arguments: ts.NodeArray<ts.Expression> | [],
421  node?: ts.Node
422};
423
424function validateEtsComponentNode(node: ts.CallExpression | ts.EtsComponentExpression, result?: NameResult): boolean {
425  let childNode: ts.Node = node;
426  result.name = null;
427  while (ts.isCallExpression(childNode) && childNode.expression &&
428    ts.isPropertyAccessExpression(childNode.expression) && childNode.expression.expression) {
429    childNode = childNode.expression.expression;
430  }
431  if (ts.isEtsComponentExpression(childNode)) {
432    if (ts.isIdentifier(childNode.expression)) {
433      result.name = childNode.expression.getText();
434      result.node = childNode;
435      result.arguments = childNode.arguments || [];
436    }
437    return true;
438  } else {
439    return false;
440  }
441}
442
443let sourceNode: ts.SourceFile;
444
445export function processComponentChild(node: ts.Block | ts.SourceFile, newStatements: ts.Statement[],
446  log: LogInfo[], supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''},
447  isBuilder: boolean = false, parent: string = undefined,
448  forEachParameters: ts.NodeArray<ts.ParameterDeclaration> = undefined, isGlobalBuilder: boolean = false,
449  isTransition: boolean = false, builderParamsResult: BuilderParamsResult = null,
450  isInRepeatTemplate: boolean = false): void {
451  if (supplement.isAcceleratePreview) {
452    newsupplement = supplement;
453    const compilerOptions = ts.readConfigFile(
454      path.resolve(__dirname, '../tsconfig.json'), ts.sys.readFile).config.compilerOptions;
455    Object.assign(compilerOptions, {
456      'sourceMap': false
457    });
458    sourceNode = ts.createSourceFile('', node.getText(), ts.ScriptTarget.Latest, true, ts.ScriptKind.ETS, compilerOptions);
459  }
460  if (node.statements.length) {
461    // Save parent component
462    const savedParent: string = parent;
463    node.statements.forEach((item) => {
464      if (ts.isExpressionStatement(item)) {
465        assignParameter(forEachParameters, item);
466        checkEtsComponent(item, log);
467        const name: string = getName(item);
468        if (CARD_ENABLE_COMPONENTS.has(name)) {
469          validatorCard(log, CARD_LOG_TYPE_COMPONENTS, item.getStart(), name);
470        }
471        switch (getComponentType(item, log, name, parent, forEachParameters)) {
472          case ComponentType.innerComponent: {
473            const [etsExpression, idName]: [ts.EtsComponentExpression, ts.Expression] =
474              checkEtsAndIdInIf(item, savedParent);
475            if (ts.isIdentifier(etsExpression.expression)) {
476              parent = etsExpression.expression.escapedText.toString();
477            }
478            processInnerComponent(item, newStatements, log, parent, isBuilder, isGlobalBuilder,
479              isTransition, idName, savedParent, builderParamsResult, isInRepeatTemplate);
480            break;
481          }
482          case ComponentType.customComponent: {
483            const idName: ts.Expression = checkIdInIf(item, savedParent);
484            parent = undefined;
485            if (!newsupplement.isAcceleratePreview) {
486              if (item.expression && ts.isEtsComponentExpression(item.expression) && item.expression.body) {
487                const expressionResult: ts.ExpressionStatement =
488                  processExpressionStatementChange(item, item.expression.body, log);
489                if (expressionResult) {
490                  item = expressionResult;
491                }
492              }
493              processCustomComponent(item as ts.ExpressionStatement, newStatements, log, name,
494                isBuilder, isGlobalBuilder, idName, builderParamsResult, isInRepeatTemplate);
495            }
496            break;
497          }
498          case ComponentType.forEachComponent:
499            parent = undefined;
500            if (!partialUpdateConfig.partialUpdateMode) {
501              processForEachComponent(item, newStatements, log, isBuilder, isGlobalBuilder);
502            } else {
503              processForEachComponentNew(item, newStatements, log, name, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
504            }
505            break;
506          case ComponentType.repeatComponent:
507            parent = undefined;
508            processRepeatComponent(item, newStatements, log, isBuilder, isGlobalBuilder, isTransition, builderParamsResult, isInRepeatTemplate);
509            break;
510          case ComponentType.customBuilderMethod:
511            parent = undefined;
512            if (partialUpdateConfig.partialUpdateMode) {
513              newStatements.push(transferBuilderCall(item, name, isBuilder));
514            } else {
515              newStatements.push(addInnerBuilderParameter(item, isGlobalBuilder));
516            }
517            break;
518          case ComponentType.builderParamMethod:
519            parent = undefined;
520            if (partialUpdateConfig.partialUpdateMode) {
521              newStatements.push(transferBuilderCall(item, name, isBuilder));
522            } else {
523              newStatements.push(addInnerBuilderParameter(item));
524            }
525            break;
526          case ComponentType.builderTypeFunction:
527            parent = undefined;
528            if (partialUpdateConfig.partialUpdateMode) {
529              newStatements.push(transferBuilderCall(item, name, isBuilder));
530            } else {
531              newStatements.push(addInnerBuilderParameter(item));
532            }
533            break;
534          case ComponentType.function:
535            parent = undefined;
536            newStatements.push(item);
537            break;
538        }
539      } else if (ts.isIfStatement(item)) {
540        assignParameter(forEachParameters, item);
541        processIfStatement(item, newStatements, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
542      } else if (!ts.isBlock(item)) {
543        log.push({
544          type: LogType.ERROR,
545          message: `Only UI component syntax can be written here.`,
546          pos: item.getStart(),
547          code: '10905209'
548        });
549      }
550      storedFileInfo.lazyForEachInfo.isDependItem = false;
551    });
552  }
553  if (supplement.isAcceleratePreview) {
554    newsupplement = {
555      isAcceleratePreview: false,
556      line: 0,
557      column: 0,
558      fileName: ''
559    };
560  }
561}
562
563function assignParameter(forEachParameters: ts.NodeArray<ts.ParameterDeclaration>, item: ts.Node): void {
564  if (partialUpdateConfig.partialUpdateMode && projectConfig.optLazyForEach &&
565    storedFileInfo.processLazyForEach) {
566    if (forEachParameters && forEachParameters[0]) {
567      storedFileInfo.lazyForEachInfo.forEachParameters = forEachParameters[0];
568    }
569    if (storedFileInfo.lazyForEachInfo.forEachParameters) {
570      visitComponent(item);
571    }
572  }
573}
574
575export function transferBuilderCall(node: ts.ExpressionStatement, name: string,
576  isBuilder: boolean = false): ts.ExpressionStatement {
577  if (node.expression && ts.isCallExpression(node.expression)) {
578    let newNode: ts.Expression = builderCallNode(node.expression);
579    newNode.expression.questionDotToken = node.expression.questionDotToken;
580    if (node.expression.arguments && node.expression.arguments.length === 1 && ts.isObjectLiteralExpression(node.expression.arguments[0])) {
581      return ts.factory.createExpressionStatement(ts.factory.updateCallExpression(
582        node.expression,
583        newNode,
584        undefined,
585        [ts.factory.createCallExpression(
586          ts.factory.createIdentifier(BUILDER_PARAM_PROXY),
587          undefined,
588          [
589            ts.factory.createStringLiteral(name),
590            traverseBuilderParams(node.expression.arguments[0], isBuilder)
591          ]
592        )]
593      ));
594    } else {
595      return ts.factory.createExpressionStatement(ts.factory.updateCallExpression(
596        node.expression,
597        newNode,
598        undefined,
599        !(projectConfig.optLazyForEach && (storedFileInfo.processLazyForEach &&
600          storedFileInfo.lazyForEachInfo.forEachParameters || isBuilder)) ? node.expression.arguments :
601          [...node.expression.arguments, ts.factory.createNull(), ts.factory.createIdentifier(MY_IDS)]
602      ));
603    }
604  }
605  return undefined;
606}
607
608function builderCallNode(node: ts.CallExpression): ts.Expression {
609  let newNode: ts.Expression;
610  if (node.expression && ts.isPropertyAccessExpression(node.expression) &&
611    node.expression.questionDotToken && node.expression.questionDotToken.kind === ts.SyntaxKind.QuestionDotToken) {
612    newNode = ts.factory.createCallChain(
613      ts.factory.createPropertyAccessChain(
614        node.expression,
615        node.questionDotToken,
616        ts.factory.createIdentifier(BUILDER_ATTR_BIND)
617      ),
618      undefined,
619      undefined,
620      [ts.factory.createThis()]
621    );
622  } else {
623    newNode = ts.factory.createCallExpression(
624      ts.factory.createPropertyAccessExpression(
625        node.expression,
626        ts.factory.createIdentifier(BUILDER_ATTR_BIND)
627      ),
628      undefined,
629      [ts.factory.createThis()]
630    );
631  }
632  return newNode;
633}
634
635function traverseBuilderParams(node: ts.ObjectLiteralExpression,
636  isBuilder: boolean): ts.ObjectLiteralExpression {
637  const properties: ts.ObjectLiteralElementLike[] = [];
638  if (node.properties && node.properties.length) {
639    node.properties.forEach(property => {
640      if (ts.isPropertyAssignment(property) && property.initializer &&
641        ts.isPropertyAccessExpression(property.initializer) && property.initializer.expression &&
642        property.initializer.name && ts.isIdentifier(property.initializer.name)) {
643        const name: string = property.initializer.name.escapedText.toString();
644        if (!storedFileInfo.processGlobalBuilder && property.initializer.expression.kind === ts.SyntaxKind.ThisKeyword ||
645          isBuilder && ts.isIdentifier(property.initializer.expression) &&
646          property.initializer.expression.escapedText.toString() === $$) {
647          const useThis: boolean = property.initializer.expression.kind === ts.SyntaxKind.ThisKeyword;
648          addProperties(properties, property, name, isBuilder, useThis);
649        } else {
650          addBuilderParamsProperties(properties, property);
651        }
652      } else {
653        addBuilderParamsProperties(properties, property);
654      }
655    });
656  }
657  return ts.factory.createObjectLiteralExpression(properties);
658}
659
660function addBuilderParamsProperties(properties: ts.ObjectLiteralElementLike[],
661  property: ts.ObjectLiteralElementLike): void {
662  const initializer: ts.Expression = ts.isShorthandPropertyAssignment(property) ?
663    property.name : property.initializer;
664  properties.push(ts.factory.createPropertyAssignment(
665    property.name,
666    ts.factory.createArrowFunction(
667      undefined,
668      undefined,
669      [],
670      undefined,
671      ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
672      initializer
673    )
674  ));
675}
676
677function addProperties(properties: ts.ObjectLiteralElementLike[], property: ts.ObjectLiteralElementLike,
678  name: string, isBuilder: boolean, useThis: boolean): void {
679  properties.push(ts.factory.createPropertyAssignment(
680    property.name,
681    ts.factory.createArrowFunction(
682      undefined,
683      undefined,
684      [],
685      undefined,
686      ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
687      ts.factory.createParenthesizedExpression(ts.factory.createConditionalExpression(
688        ts.factory.createElementAccessExpression(
689          (isBuilder && !useThis) ? ts.factory.createIdentifier($$) : ts.factory.createThis(),
690          ts.factory.createStringLiteral('__' + name)
691        ),
692        ts.factory.createToken(ts.SyntaxKind.QuestionToken),
693        ts.factory.createElementAccessExpression(
694          (isBuilder && !useThis) ? ts.factory.createIdentifier($$) : ts.factory.createThis(),
695          ts.factory.createStringLiteral('__' + name)
696        ),
697        ts.factory.createToken(ts.SyntaxKind.ColonToken),
698        ts.factory.createElementAccessExpression(
699          (isBuilder && !useThis) ? ts.factory.createIdentifier($$) : ts.factory.createThis(),
700          ts.factory.createStringLiteral(name)
701        )
702      ))
703    )
704  ));
705}
706
707function addInnerBuilderParameter(node: ts.ExpressionStatement,
708  isGlobalBuilder: boolean = false): ts.ExpressionStatement {
709  if (node.expression && ts.isCallExpression(node.expression) && node.expression.arguments) {
710    node.expression.arguments.push(isGlobalBuilder ? parentConditionalExpression() : ts.factory.createThis());
711    return ts.factory.createExpressionStatement(ts.factory.updateCallExpression(node.expression,
712      node.expression.expression, node.expression.typeArguments, node.expression.arguments));
713  } else {
714    return node;
715  }
716}
717
718function processExpressionStatementChange(node: ts.ExpressionStatement, nextNode: ts.Block,
719  log: LogInfo[]): ts.ExpressionStatement {
720  let name: string;
721  // @ts-ignore
722  if (node.expression.expression && ts.isIdentifier(node.expression.expression)) {
723    name = node.expression.expression.escapedText.toString();
724  } else if (node.expression.expression && ts.isPropertyAccessExpression(node.expression.expression)) {
725    name = node.expression.expression.getText();
726  }
727  if (builderParamObjectCollection.get(name) &&
728    builderParamObjectCollection.get(name).size === 1) {
729    return processBlockToExpression(node, nextNode, log, name, false);
730  } else if (projectConfig.compileMode === 'esmodule' && process.env.compileTool === 'rollup' &&
731    storedFileInfo.overallBuilderParamCollection.get(name) &&
732    storedFileInfo.overallBuilderParamCollection.get(name).size === 1
733  ) {
734    return processBlockToExpression(node, nextNode, log, name, true);
735  } else {
736    log.push({
737      type: LogType.ERROR,
738      message: `In the trailing lambda case, '${name}' must have one and only one property decorated with ` +
739        `'@BuilderParam', and its '@BuilderParam' expects no parameter.`,
740      pos: node.getStart(),
741      code: '10905102'
742    });
743    return null;
744  }
745}
746
747function processBlockToExpression(node: ts.ExpressionStatement, nextNode: ts.Block,
748  log: LogInfo[], name: string, isPropertyAccessExpressionNode: boolean): ts.ExpressionStatement {
749  const childParam: string = isPropertyAccessExpressionNode ? [...storedFileInfo.overallBuilderParamCollection.get(name)].slice(-1)[0] :
750    [...builderParamObjectCollection.get(name)].slice(-1)[0];
751  const newBlock: ts.Block = processComponentBlock(nextNode, false, log);
752  const arrowNode: ts.ArrowFunction = ts.factory.createArrowFunction(undefined, undefined,
753    [], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), newBlock);
754  const newPropertyAssignment:ts.PropertyAssignment = ts.factory.createPropertyAssignment(
755    ts.factory.createIdentifier(childParam), arrowNode);
756  // @ts-ignore
757  let argumentsArray: ts.ObjectLiteralExpression[] = node.expression.arguments;
758  if (argumentsArray && !argumentsArray.length) {
759    argumentsArray = [ts.factory.createObjectLiteralExpression([newPropertyAssignment], true)];
760  } else if (ts.isObjectLiteralExpression(argumentsArray[0]) && argumentsArray.length === 1) {
761    argumentsArray = [ts.factory.createObjectLiteralExpression(
762      // @ts-ignore
763      node.expression.arguments[0].properties.concat([newPropertyAssignment]), true)];
764  } else if (ts.isObjectLiteralExpression(argumentsArray[0]) && argumentsArray.length === 2) {
765    argumentsArray = [ts.factory.createObjectLiteralExpression(
766      // @ts-ignore
767      node.expression.arguments[0].properties.concat([newPropertyAssignment]), true), argumentsArray[1]];
768  }
769  const callNode: ts.CallExpression = ts.factory.updateCallExpression(
770    // @ts-ignore
771    node.expression, node.expression.expression, node.expression.expression.typeArguments,
772    argumentsArray);
773  // @ts-ignore
774  node.expression.expression.parent = callNode;
775  // @ts-ignore
776  callNode.parent = node.expression.parent;
777  node = ts.factory.updateExpressionStatement(node, callNode);
778  return node;
779}
780
781type EtsComponentResult = {
782  etsComponentNode: ts.EtsComponentExpression;
783  hasAttr: boolean;
784};
785function parseEtsComponentExpression(node: ts.ExpressionStatement): EtsComponentResult {
786  let etsComponentNode: ts.EtsComponentExpression;
787  let hasAttr: boolean = false;
788  let temp: any = node.expression;
789  while (temp) {
790    if (ts.isCallExpression(temp) && temp.expression &&
791      ts.isPropertyAccessExpression(temp.expression)) {
792      hasAttr = true;
793    }
794    if (ts.isEtsComponentExpression(temp)) {
795      etsComponentNode = temp;
796      break;
797    }
798    temp = temp.expression;
799  }
800  return { etsComponentNode: etsComponentNode, hasAttr: hasAttr };
801}
802
803export function createCollectElmtIdNode(): ts.ExpressionStatement {
804  return ts.factory.createExpressionStatement(ts.factory.createCallExpression(
805    ts.factory.createPropertyAccessExpression(
806      ts.factory.createIdentifier(MY_IDS),
807      ts.factory.createIdentifier(PUSH)
808    ),
809    undefined,
810    [ts.factory.createIdentifier(ELMTID)]
811  ));
812}
813
814function processInnerComponent(node: ts.ExpressionStatement, innerCompStatements: ts.Statement[],
815  log: LogInfo[], parent: string = undefined, isBuilder: boolean = false, isGlobalBuilder: boolean = false,
816  isTransition: boolean = false, idName: ts.Expression = undefined, savedParent: string = undefined,
817  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): void {
818  const newStatements: ts.Statement[] = [];
819  const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION);
820  newStatements.push(res.newNode);
821  const nameResult: NameResult = { name: null, arguments: [] };
822  validateEtsComponentNode(node.expression as ts.EtsComponentExpression, nameResult);
823  if (savedParent && nameResult.name) {
824    checkNonspecificParents(node, nameResult.name, savedParent, log);
825  }
826  if (partialUpdateConfig.partialUpdateMode && ItemComponents.includes(nameResult.name)) {
827    processItemComponent(node, nameResult, innerCompStatements, log, parent, isGlobalBuilder, idName, builderParamsResult, isInRepeatTemplate);
828  } else if (partialUpdateConfig.partialUpdateMode && TabContentAndNavDestination.has(nameResult.name)) {
829    processTabAndNav(node, innerCompStatements, nameResult, log, parent, isGlobalBuilder, idName, builderParamsResult, isInRepeatTemplate);
830  } else {
831    processNormalComponent(node, nameResult, innerCompStatements, log, parent, isBuilder, isGlobalBuilder,
832      isTransition, idName, builderParamsResult, isInRepeatTemplate);
833  }
834}
835
836function processNormalComponent(node: ts.ExpressionStatement, nameResult: NameResult,
837  innerCompStatements: ts.Statement[], log: LogInfo[], parent: string = undefined, isBuilder: boolean = false,
838  isGlobalBuilder: boolean = false, isTransition: boolean = false, idName: ts.Expression = undefined,
839  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): void {
840  const newStatements: ts.Statement[] = [];
841  if (addElmtIdNode()) {
842    newStatements.push(createCollectElmtIdNode());
843  }
844  const immutableStatements: ts.Statement[] = [];
845  const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION);
846  newStatements.push(res.newNode);
847  processDebug(node, nameResult, newStatements);
848  const etsComponentResult: EtsComponentResult = parseEtsComponentExpression(node);
849  const componentName: string = res.identifierNode.getText();
850  let judgeIdStart: number;
851  if (partialUpdateConfig.partialUpdateMode && idName) {
852    judgeIdStart = innerCompStatements.length;
853  }
854  if (etsComponentResult.etsComponentNode.body && ts.isBlock(etsComponentResult.etsComponentNode.body)) {
855    if (res.isButton) {
856      checkButtonParamHasLabel(etsComponentResult.etsComponentNode, log);
857      if (projectConfig.isPreview || projectConfig.enableDebugLine) {
858        newStatements.splice(-2, 1, createComponent(node, COMPONENT_CREATE_CHILD_FUNCTION).newNode);
859      } else {
860        newStatements.splice(-1, 1, createComponent(node, COMPONENT_CREATE_CHILD_FUNCTION).newNode);
861      }
862    }
863    if (etsComponentResult.hasAttr) {
864      bindComponentAttr(node, res.identifierNode, newStatements, log, true, false, immutableStatements);
865    }
866    processInnerCompStatements(innerCompStatements, newStatements, node, isGlobalBuilder,
867      isTransition, undefined, immutableStatements, componentName, builderParamsResult);
868    storedFileInfo.lazyForEachInfo.isDependItem = false;
869    processComponentChild(etsComponentResult.etsComponentNode.body, innerCompStatements, log,
870      {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isBuilder, parent, undefined,
871      isGlobalBuilder, false, builderParamsResult, isInRepeatTemplate);
872  } else {
873    bindComponentAttr(node, res.identifierNode, newStatements, log, true, false, immutableStatements);
874    processInnerCompStatements(innerCompStatements, newStatements, node, isGlobalBuilder,
875      isTransition, undefined, immutableStatements, componentName, builderParamsResult);
876  }
877  if (res.isContainerComponent || res.needPop) {
878    innerCompStatements.push(createComponent(node, COMPONENT_POP_FUNCTION).newNode);
879  }
880  if (partialUpdateConfig.partialUpdateMode && idName) {
881    innerCompStatements.splice(judgeIdStart, innerCompStatements.length - judgeIdStart,
882      ifRetakeId(innerCompStatements.slice(judgeIdStart), idName));
883  }
884}
885
886export function ifRetakeId(blockContent: ts.Statement[], idName: ts.Expression): ts.IfStatement {
887  return ts.factory.createIfStatement(
888    ts.factory.createPrefixUnaryExpression(
889      ts.SyntaxKind.ExclamationToken,
890      ts.factory.createCallExpression(
891        ts.factory.createPropertyAccessExpression(
892          ts.factory.createIdentifier(COMPONENT_IF),
893          ts.factory.createIdentifier(CAN_RETAKE)
894        ),
895        undefined,
896        [idName]
897      )
898    ),
899    ts.factory.createBlock(
900      blockContent,
901      true
902    ),
903    undefined
904  );
905}
906
907function processRepeatComponent(node: ts.ExpressionStatement, innerCompStatements: ts.Statement[],
908  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false,
909  isTransition: boolean = false, builderParamsResult: BuilderParamsResult = null,
910  isInRepeatTemplate: boolean = false): void {
911  const chainCallTransform: ts.CallExpression =
912    recurseRepeatExpression(node.expression as ts.CallExpression, log, isBuilder, isGlobalBuilder,
913      isTransition, isInRepeatTemplate) as ts.CallExpression;
914  innerCompStatements.push(createComponentCreationStatement(node,
915    [ts.factory.createExpressionStatement(ts.factory.createCallExpression(
916      ts.factory.createPropertyAccessExpression(
917        chainCallTransform,
918        ts.factory.createIdentifier(COMPONENT_RENDER_FUNCTION)
919      ),
920      undefined,
921      [ts.factory.createIdentifier(ISINITIALRENDER)]
922    ))], COMPONENT_REPEAT, isGlobalBuilder, isTransition, undefined, null, builderParamsResult));
923}
924
925function recurseRepeatExpression(node: ts.CallExpression | ts.PropertyAccessExpression,
926  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false, isTransition: boolean = false, isInRepeatTemplate: boolean = false):
927  ts.PropertyAccessExpression | ts.CallExpression {
928  if (ts.isCallExpression(node) && node.expression && ts.isIdentifier(node.expression) &&
929    node.expression.getText() === COMPONENT_REPEAT) {
930    return ts.factory.createCallExpression(node.expression, node.typeArguments, [...node.arguments, ts.factory.createThis()]);
931  } else if (ts.isPropertyAccessExpression(node)) {
932    return ts.factory.updatePropertyAccessExpression(node,
933      recurseRepeatExpression(node.expression, log, isBuilder, isGlobalBuilder, isTransition, isInRepeatTemplate), node.name);
934  } else {
935    let repeatPropArgs: ts.ArrowFunction[] = processRepeatAttributeArrowNode(node.arguments);
936    storedFileInfo.processRepeat = true;
937    repeatPropArgs = processRepeatPropWithChild(node, repeatPropArgs, log, isBuilder, isGlobalBuilder, isTransition, isInRepeatTemplate);
938    storedFileInfo.processRepeat = false;
939    return ts.factory.updateCallExpression(node,
940      recurseRepeatExpression(node.expression as ts.PropertyAccessExpression, log, isBuilder,
941        isGlobalBuilder, isTransition, isInRepeatTemplate) as ts.PropertyAccessExpression, undefined, repeatPropArgs);
942  }
943}
944
945function processRepeatPropWithChild(node: ts.CallExpression, repeatPropArgs: ts.ArrowFunction[],
946  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false, isTransition: boolean = false,
947  isInRepeatTemplate: boolean = false): ts.ArrowFunction[] {
948  if (ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) &&
949    node.expression.name.getText() === REPEAT_EACH && repeatPropArgs.length > 0 && repeatPropArgs[0].body) {
950    // transfer args for each property
951    return [
952      ts.factory.updateArrowFunction(repeatPropArgs[0], repeatPropArgs[0].modifiers, repeatPropArgs[0].typeParameters,
953        repeatPropArgs[0].parameters, repeatPropArgs[0].type, repeatPropArgs[0].equalsGreaterThanToken,
954        processComponentBlock(processRepeatCallBackBlock(repeatPropArgs[0]), false, log, isTransition,
955          isBuilder, undefined, undefined, isGlobalBuilder, null, false, isInRepeatTemplate)),
956      ...repeatPropArgs.slice(1)
957    ];
958  } else if (ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) &&
959    node.expression.name.getText() === REPEAT_TEMPLATE && repeatPropArgs.length > 1 && repeatPropArgs[1].body) {
960    // transfer args for template property
961    return [
962      repeatPropArgs[0], ts.factory.updateArrowFunction(repeatPropArgs[1], repeatPropArgs[1].modifiers, repeatPropArgs[1].typeParameters,
963        repeatPropArgs[1].parameters, repeatPropArgs[1].type, repeatPropArgs[1].equalsGreaterThanToken,
964        processComponentBlock(processRepeatCallBackBlock(repeatPropArgs[1]), false, log, isTransition, isBuilder, undefined, undefined,
965          isGlobalBuilder, null, false, true)),
966      ...repeatPropArgs.slice(2)
967    ];
968  }
969  return repeatPropArgs;
970}
971
972function processRepeatCallBackBlock(repeatPropArg: ts.ArrowFunction): ts.Block {
973  if (ts.isBlock(repeatPropArg.body)) {
974    return repeatPropArg.body;
975  } else {
976    return ts.factory.updateArrowFunction(repeatPropArg, ts.getModifiers(repeatPropArg), repeatPropArg.typeParameters,
977      repeatPropArg.parameters, repeatPropArg.type, repeatPropArg.equalsGreaterThanToken,
978      ts.factory.createBlock([ts.factory.createExpressionStatement(repeatPropArg.body)], true)).body as ts.Block;
979  }
980}
981
982function processRepeatAttributeArrowNode(argumentsNode: ts.ArrowFunction[]): ts.ArrowFunction[] {
983  for (let i = 0; i < argumentsNode.length; i++) {
984    while (ts.isParenthesizedExpression(argumentsNode[i])) {
985      if (ts.isArrowFunction(argumentsNode[i].expression)) {
986        argumentsNode.splice(i, 1, argumentsNode[i].expression);
987        break;
988      } else {
989        if (argumentsNode[i].expression) {
990          argumentsNode[i] = argumentsNode[i].expression;
991        } else {
992          break;
993        }
994      }
995    }
996  }
997  return argumentsNode;
998}
999
1000function processDebug(node: ts.Statement, nameResult: NameResult, newStatements: ts.Statement[],
1001  getNode: boolean = false): ts.ExpressionStatement {
1002  if ((projectConfig.isPreview || projectConfig.enableDebugLine) && nameResult.name &&
1003    !NO_DEBUG_LINE_COMPONENT.has(nameResult.name)) {
1004    let posOfNode: ts.LineAndCharacter;
1005    let curFileName: string;
1006    let line: number = 1;
1007    let col: number = 1;
1008    if (sourceNode && newsupplement.isAcceleratePreview) {
1009      posOfNode = sourceNode.getLineAndCharacterOfPosition(getRealNodePos(node) - 22);
1010      curFileName = newsupplement.fileName;
1011      if (posOfNode.line === 0) {
1012        col = newsupplement.column - 1;
1013      }
1014      line = newsupplement.line;
1015    } else {
1016      posOfNode = transformLog.sourceFile.getLineAndCharacterOfPosition(getRealNodePos(node));
1017      curFileName = transformLog.sourceFile.fileName.replace(/\.ts$/, '');
1018    }
1019    let debugInfo: string;
1020    if (projectConfig.isPreview) {
1021      if (projectConfig.minAPIVersion >= 11) {
1022        debugInfo = `${path.relative(projectConfig.projectRootPath, curFileName).replace(/\\+/g, '/')}` +
1023          `(${posOfNode.line + line}:${posOfNode.character + col})`;
1024      } else {
1025        debugInfo = `${path.relative(projectConfig.projectPath, curFileName).replace(/\\+/g, '/')}` +
1026          `(${posOfNode.line + line}:${posOfNode.character + col})`;
1027      }
1028    } else if (projectConfig.enableDebugLine) {
1029      debugInfo = `${path.relative(projectConfig.projectRootPath, curFileName)}` +
1030        `(${posOfNode.line + line}:${posOfNode.character + col})`;
1031    }
1032    const debugNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
1033      createFunction(ts.factory.createIdentifier(nameResult.name),
1034        ts.factory.createIdentifier(COMPONENT_DEBUGLINE_FUNCTION),
1035        createDebugLineArgs(debugInfo)));
1036    if (getNode) {
1037      return debugNode;
1038    }
1039    newStatements.push(debugNode);
1040  }
1041  return undefined;
1042}
1043
1044function createDebugLineArgs(debugInfo: string): ts.NodeArray {
1045  const argsArr: ts.Node[] = [ts.factory.createStringLiteral(debugInfo)];
1046  const pkgName: string = storedFileInfo.getCurrentArkTsFile().pkgName;
1047  if (pkgName) {
1048    argsArr.push(ts.factory.createStringLiteral(pkgName));
1049  }
1050  return ts.factory.createNodeArray(argsArr);
1051}
1052
1053function processInnerCompStatements(innerCompStatements: ts.Statement[],
1054  newStatements: ts.Statement[], node: ts.Statement, isGlobalBuilder: boolean, isTransition: boolean,
1055  nameResult: NameResult, immutableStatements: ts.Statement[], componentName: string,
1056  builderParamsResult: BuilderParamsResult): void {
1057  if (!partialUpdateConfig.partialUpdateMode) {
1058    innerCompStatements.push(...newStatements);
1059  } else {
1060    innerCompStatements.push(createComponentCreationStatement(node, newStatements, componentName,
1061      isGlobalBuilder, isTransition, nameResult, immutableStatements, builderParamsResult));
1062  }
1063}
1064
1065function createComponentCreationArrowParams(isGlobalBuilder: boolean,
1066  builderParamsResult: BuilderParamsResult, isRecycleComponent: boolean = false): ts.ParameterDeclaration[] {
1067  const arrowNodes: ts.ParameterDeclaration[] = [
1068    ts.factory.createParameterDeclaration(undefined, undefined,
1069      ts.factory.createIdentifier(ELMTID), undefined, undefined, undefined),
1070    ts.factory.createParameterDeclaration(undefined, undefined,
1071      ts.factory.createIdentifier(ISINITIALRENDER), undefined, undefined, undefined)
1072  ];
1073  if (!isRecycleComponent && partialUpdateConfig.optimizeComponent && isGlobalBuilder &&
1074    builderParamsResult && builderParamsResult.firstParam) {
1075    const paramName: ts.Identifier = builderParamsResult.firstParam.name as ts.Identifier;
1076    arrowNodes.push(ts.factory.createParameterDeclaration(undefined, undefined,
1077      paramName, undefined, undefined, ts.factory.createIdentifier(`__${paramName.escapedText.toString()}__`)
1078    ));
1079  }
1080  return arrowNodes;
1081}
1082
1083export function createComponentCreationStatement(node: ts.Statement, innerStatements: ts.Statement[],
1084  componentName: string, isGlobalBuilder: boolean = false, isTransition: boolean = false,
1085  nameResult: NameResult = undefined, immutableStatements: ts.Statement[] = null,
1086  builderParamsResult: BuilderParamsResult = null, isRecycleComponent: boolean = false): ts.Statement {
1087  const blockArr: ts.Statement[] = [...innerStatements];
1088  if (nameResult) {
1089    blockArr.push(processDebug(node, nameResult, innerStatements, true));
1090  }
1091  if (!isTransition) {
1092    createInitRenderStatement(node, immutableStatements, blockArr);
1093  }
1094  if (!partialUpdateConfig.optimizeComponent) {
1095    blockArr.unshift(createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID));
1096    blockArr.push(createViewStackProcessorStatement(STOPGETACCESSRECORDING));
1097  }
1098  const creationArgs: ts.Expression[] = [
1099    ts.factory.createArrowFunction(undefined, undefined,
1100      createComponentCreationArrowParams(isGlobalBuilder, builderParamsResult, isRecycleComponent),
1101      undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1102      ts.factory.createBlock(blockArr, true)
1103    )
1104  ];
1105  if (partialUpdateConfig.optimizeComponent) {
1106    creationArgs.push(isTransition ? ts.factory.createNull() :
1107      ts.factory.createIdentifier(componentName));
1108  }
1109  return ts.factory.createExpressionStatement(
1110    ts.factory.createCallExpression(
1111      ts.factory.createPropertyAccessExpression(createConditionParent(isGlobalBuilder),
1112        ts.factory.createIdentifier(partialUpdateConfig.optimizeComponent ?
1113          OBSERVECOMPONENTCREATION2 : OBSERVECOMPONENTCREATION)
1114      ), undefined, creationArgs)
1115  );
1116}
1117
1118export function createViewStackProcessorStatement(propertyAccessName: string, elmtId?: string): ts.Statement {
1119  return ts.factory.createExpressionStatement(
1120    ts.factory.createCallExpression(
1121      ts.factory.createPropertyAccessExpression(
1122        ts.factory.createIdentifier(VIEWSTACKPROCESSOR),
1123        ts.factory.createIdentifier(propertyAccessName)
1124      ),
1125      undefined,
1126      elmtId ? [ts.factory.createIdentifier(ELMTID)] : []
1127    )
1128  );
1129}
1130
1131function createInitRenderStatement(node: ts.Statement,
1132  immutableStatements: ts.Statement[], blockArr: ts.Statement[]): void {
1133  if (partialUpdateConfig.optimizeComponent) {
1134    if (immutableStatements && immutableStatements.length) {
1135      blockArr.push(ts.factory.createIfStatement(
1136        ts.factory.createIdentifier(ISINITIALRENDER),
1137        ts.factory.createBlock(immutableStatements, true)
1138      ));
1139    }
1140  } else {
1141    blockArr.push(ts.factory.createIfStatement(
1142      ts.factory.createPrefixUnaryExpression(
1143        ts.SyntaxKind.ExclamationToken,
1144        ts.factory.createIdentifier(ISINITIALRENDER)
1145      ),
1146      ts.factory.createBlock(
1147        [
1148          ts.isExpressionStatement(node) ?
1149            createComponent(node, COMPONENT_POP_FUNCTION).newNode : createIfPop()
1150        ],
1151        true
1152      ),
1153      immutableStatements && immutableStatements.length ?
1154        ts.factory.createBlock(immutableStatements, true) : undefined
1155    ));
1156  }
1157}
1158
1159function processItemComponent(node: ts.ExpressionStatement, nameResult: NameResult, innerCompStatements: ts.Statement[],
1160  log: LogInfo[], parent: string = undefined, isGlobalBuilder: boolean = false, idName: ts.Expression = undefined,
1161  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): void {
1162  const itemRenderInnerStatements: ts.Statement[] = [];
1163  const immutableStatements: ts.Statement[] = [];
1164  const deepItemRenderInnerStatements: ts.Statement[] = [];
1165  if (addElmtIdNode()) {
1166    itemRenderInnerStatements.push(createCollectElmtIdNode());
1167  }
1168  const res: CreateResult = createComponent(node, COMPONENT_CREATE_FUNCTION);
1169  const isLazyCreate: boolean = checkLazyCreate(node, nameResult);
1170  const itemCreateStatement: ts.Statement = createItemCreate(nameResult, isLazyCreate);
1171  itemRenderInnerStatements.push(itemCreateStatement);
1172  const etsComponentResult: EtsComponentResult = parseEtsComponentExpression(node);
1173  if (etsComponentResult.etsComponentNode.body && ts.isBlock(etsComponentResult.etsComponentNode.body)) {
1174    if (etsComponentResult.hasAttr) {
1175      bindComponentAttr(node, res.identifierNode, itemRenderInnerStatements, log, true, false, immutableStatements);
1176    }
1177    storedFileInfo.lazyForEachInfo.isDependItem = false;
1178    processComponentChild(etsComponentResult.etsComponentNode.body, deepItemRenderInnerStatements, log,
1179      {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, false, parent, undefined, isGlobalBuilder, false,
1180      builderParamsResult, isInRepeatTemplate);
1181  } else {
1182    bindComponentAttr(node, res.identifierNode, itemRenderInnerStatements, log, true, false, immutableStatements);
1183  }
1184  let generateItem: ts.IfStatement | ts.Block;
1185  if (idName) {
1186    generateItem = ifRetakeId([createItemBlock(
1187      node, itemRenderInnerStatements, deepItemRenderInnerStatements, nameResult, isLazyCreate,
1188      immutableStatements, isGlobalBuilder, builderParamsResult)], idName);
1189  } else {
1190    generateItem = createItemBlock(
1191      node, itemRenderInnerStatements, deepItemRenderInnerStatements, nameResult, isLazyCreate,
1192      immutableStatements, isGlobalBuilder, builderParamsResult);
1193  }
1194  innerCompStatements.push(generateItem);
1195}
1196
1197function createItemCreate(nameResult: NameResult, isLazyCreate: boolean): ts.Statement {
1198  const itemCreateArgs: ts.Expression[] = [];
1199  if (isLazyCreate) {
1200    itemCreateArgs.push(ts.factory.createIdentifier(DEEPRENDERFUNCTION), ts.factory.createTrue());
1201  } else {
1202    itemCreateArgs.push(
1203      ts.factory.createArrowFunction(undefined, undefined, [], undefined,
1204        ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1205        ts.factory.createBlock([], false)),
1206      ts.factory.createFalse()
1207    );
1208  }
1209  itemCreateArgs.push(...nameResult.arguments);
1210  return ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1211    ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(nameResult.name),
1212      ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined, itemCreateArgs));
1213}
1214
1215type ItemCreation = {
1216  creationArgs: ts.Expression[],
1217  creationName: string,
1218};
1219
1220function getItemCreation(nameResult: NameResult): ItemCreation {
1221  const creationArgs: ts.Expression[] = [];
1222  let creationName: string = OBSERVECOMPONENTCREATION;
1223  if (partialUpdateConfig.optimizeComponent) {
1224    creationArgs.push(
1225      ts.factory.createIdentifier(ITEMCREATION2),
1226      ts.factory.createIdentifier(nameResult.name));
1227    creationName = OBSERVECOMPONENTCREATION2;
1228  } else {
1229    creationArgs.push(ts.factory.createIdentifier(ITEMCREATION));
1230  }
1231  return { creationArgs, creationName };
1232}
1233
1234function createItemBlock(
1235  node: ts.ExpressionStatement,
1236  itemRenderInnerStatements: ts.Statement[],
1237  deepItemRenderInnerStatements: ts.Statement[],
1238  nameResult: NameResult, isLazyCreate: boolean,
1239  immutableStatements: ts.Statement[],
1240  isGlobalBuilder: boolean,
1241  builderParamsResult: BuilderParamsResult
1242): ts.Block {
1243  const blockNode: ts.Statement[] = [
1244    createItemCreation2(node, itemRenderInnerStatements, nameResult, immutableStatements,
1245      isGlobalBuilder, builderParamsResult)
1246  ];
1247  const itemCreation: ItemCreation = getItemCreation(nameResult);
1248  if (isLazyCreate) {
1249    blockNode.unshift(createItemCreation(node, isGlobalBuilder, builderParamsResult));
1250    blockNode.push(
1251      createDeepRenderFunction(node, deepItemRenderInnerStatements, isGlobalBuilder, builderParamsResult),
1252      ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1253        ts.factory.createPropertyAccessExpression(
1254          ts.factory.createThis(),
1255          ts.factory.createIdentifier(itemCreation.creationName)
1256        ), undefined, itemCreation.creationArgs
1257      )),
1258      createComponent(node, COMPONENT_POP_FUNCTION).newNode
1259    );
1260  } else {
1261    if (!partialUpdateConfig.optimizeComponent) {
1262      blockNode.unshift(createItemCreation(node, isGlobalBuilder, builderParamsResult));
1263    }
1264    blockNode.push(
1265      createObservedDeepRender(node, deepItemRenderInnerStatements, itemCreation),
1266      ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1267        ts.factory.createIdentifier(OBSERVEDDEEPRENDER), undefined, []))
1268    );
1269  }
1270  return ts.factory.createBlock(blockNode, true);
1271}
1272
1273function checkLazyCreate(node: ts.ExpressionStatement, nameResult: NameResult): boolean {
1274  if (nameResult.name === LIST_ITEM) {
1275    if (nameResult.arguments.length && ts.isStringLiteral(nameResult.arguments[0]) &&
1276      nameResult.arguments[0].text === 'false') {
1277      return false;
1278    }
1279    if (storedFileInfo.processRepeat) {
1280      return false;
1281    }
1282    if (isLazyForEachChild(node)) {
1283      return false;
1284    }
1285    return true;
1286  }
1287  return false;
1288}
1289
1290function createItemCreation(node: ts.ExpressionStatement, isGlobalBuilder: boolean,
1291  builderParamsResult: BuilderParamsResult): ts.VariableStatement {
1292  return ts.factory.createVariableStatement(
1293    undefined,
1294    ts.factory.createVariableDeclarationList(
1295      [ts.factory.createVariableDeclaration(
1296        ts.factory.createIdentifier(ITEMCREATION), undefined, undefined,
1297        ts.factory.createArrowFunction(undefined, undefined,
1298          createComponentCreationArrowParams(isGlobalBuilder, builderParamsResult), undefined,
1299          ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1300          ts.factory.createBlock(
1301            [
1302              createViewStackProcessorStatement(STARTGETACCESSRECORDINGFOR, ELMTID),
1303              ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1304                ts.factory.createIdentifier(ITEMCREATION2),
1305                undefined, createItemCreationArgs(isGlobalBuilder, builderParamsResult)
1306              )),
1307              ts.factory.createIfStatement(
1308                ts.factory.createPrefixUnaryExpression(
1309                  ts.SyntaxKind.ExclamationToken,
1310                  ts.factory.createIdentifier(ISINITIALRENDER)
1311                ),
1312                ts.factory.createBlock(
1313                  [createComponent(node, COMPONENT_POP_FUNCTION).newNode],
1314                  true
1315                )
1316              ),
1317              createViewStackProcessorStatement(STOPGETACCESSRECORDING)
1318            ],
1319            true
1320          )
1321        )
1322      )],
1323      ts.NodeFlags.Const
1324    )
1325  );
1326}
1327
1328function createItemCreation2(
1329  node: ts.ExpressionStatement,
1330  itemRenderInnerStatements: ts.Statement[],
1331  nameResult: NameResult,
1332  immutableStatements: ts.Statement[],
1333  isGlobalBuilder: boolean,
1334  builderParamsResult: BuilderParamsResult
1335): ts.VariableStatement {
1336  const itemBlock: ts.Statement[] = [
1337    ...itemRenderInnerStatements,
1338    processDebug(node, nameResult, itemRenderInnerStatements, true)
1339  ];
1340  if (immutableStatements && immutableStatements.length) {
1341    itemBlock.push(ts.factory.createIfStatement(
1342      ts.factory.createIdentifier(ISINITIALRENDER),
1343      ts.factory.createBlock(immutableStatements, true)
1344    ));
1345  }
1346  return ts.factory.createVariableStatement(
1347    undefined,
1348    ts.factory.createVariableDeclarationList(
1349      [ts.factory.createVariableDeclaration(
1350        ts.factory.createIdentifier(ITEMCREATION2), undefined, undefined,
1351        ts.factory.createArrowFunction(undefined, undefined,
1352          createComponentCreationArrowParams(isGlobalBuilder, builderParamsResult), undefined,
1353          ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1354          ts.factory.createBlock(itemBlock, true)
1355        )
1356      )],
1357      ts.NodeFlags.Const
1358    )
1359  );
1360}
1361
1362function createItemCreationArgs(isGlobalBuilder: boolean,
1363  builderParamsResult: BuilderParamsResult): ts.Expression[] {
1364  const itemCreationArgs: ts.Expression[] = [
1365    ts.factory.createIdentifier(ELMTID), ts.factory.createIdentifier(ISINITIALRENDER)];
1366  if (partialUpdateConfig.optimizeComponent && isGlobalBuilder && builderParamsResult &&
1367    builderParamsResult.firstParam) {
1368    itemCreationArgs.push(builderParamsResult.firstParam.name as ts.Identifier);
1369  }
1370  return itemCreationArgs;
1371}
1372
1373function createDeepRenderFunction(
1374  node: ts.ExpressionStatement,
1375  deepItemRenderInnerStatements: ts.Statement[],
1376  isGlobalBuilder: boolean,
1377  builderParamsResult: BuilderParamsResult
1378): ts.VariableStatement {
1379  const blockNode: ts.Statement[] = [
1380    ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1381      ts.factory.createIdentifier(ITEMCREATION), undefined,
1382      createItemCreationArgs(isGlobalBuilder, builderParamsResult)
1383    )),
1384    ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1385      ts.factory.createPropertyAccessExpression(
1386        ts.factory.createPropertyAccessExpression(
1387          ts.factory.createThis(),
1388          ts.factory.createIdentifier(UPDATE_FUNC_BY_ELMT_ID)
1389        ),
1390        ts.factory.createIdentifier(CREATE_SET_METHOD)
1391      ), undefined,
1392      [ts.factory.createIdentifier(ELMTID), ts.factory.createIdentifier(ITEMCREATION)]
1393    )),
1394    ...deepItemRenderInnerStatements,
1395    createComponent(node, COMPONENT_POP_FUNCTION).newNode
1396  ];
1397  if (partialUpdateConfig.optimizeComponent) {
1398    blockNode.splice(1, 1);
1399  }
1400  return ts.factory.createVariableStatement(
1401    undefined,
1402    ts.factory.createVariableDeclarationList(
1403      [ts.factory.createVariableDeclaration(
1404        ts.factory.createIdentifier(DEEPRENDERFUNCTION), undefined, undefined,
1405        ts.factory.createArrowFunction(undefined, undefined,
1406          createComponentCreationArrowParams(isGlobalBuilder, builderParamsResult), undefined,
1407          ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1408          ts.factory.createBlock(blockNode, true)
1409        )
1410      )],
1411      ts.NodeFlags.Const
1412    )
1413  );
1414}
1415
1416function createObservedDeepRender(
1417  node: ts.ExpressionStatement,
1418  deepItemRenderInnerStatements: ts.Statement[],
1419  itemCreation: ItemCreation
1420): ts.VariableStatement {
1421  return ts.factory.createVariableStatement(
1422    undefined,
1423    ts.factory.createVariableDeclarationList(
1424      [ts.factory.createVariableDeclaration(
1425        ts.factory.createIdentifier(OBSERVEDDEEPRENDER),
1426        undefined,
1427        undefined,
1428        ts.factory.createArrowFunction(
1429          undefined,
1430          undefined,
1431          [],
1432          undefined,
1433          ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1434          ts.factory.createBlock(
1435            [
1436              ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1437                ts.factory.createPropertyAccessExpression(
1438                  ts.factory.createThis(),
1439                  ts.factory.createIdentifier(itemCreation.creationName)
1440                ), undefined, itemCreation.creationArgs
1441              )),
1442              ...deepItemRenderInnerStatements,
1443              createComponent(node, COMPONENT_POP_FUNCTION).newNode
1444            ],
1445            true
1446          )
1447        )
1448      )],
1449      ts.NodeFlags.Const
1450    )
1451  );
1452}
1453
1454function processTabAndNav(node: ts.ExpressionStatement, innerCompStatements: ts.Statement[],
1455  nameResult: NameResult, log: LogInfo[], parent: string = undefined, isGlobalBuilder: boolean = false,
1456  idName: ts.Expression = undefined, builderParamsResult: BuilderParamsResult = null,
1457  isInRepeatTemplate: boolean = false): void {
1458  const name: string = nameResult.name;
1459  const tabContentComp: ts.EtsComponentExpression = getEtsComponentExpression(node);
1460  const tabContentBody: ts.Block = tabContentComp.body;
1461  let tabContentCreation: ts.Statement;
1462  const tabContentPop: ts.Statement = ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1463    ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(name),
1464      ts.factory.createIdentifier(COMPONENT_POP_FUNCTION)), undefined, []));
1465  const tabAttrs: ts.Statement[] = [];
1466  if (addElmtIdNode()) {
1467    tabAttrs.push(createCollectElmtIdNode());
1468  }
1469  const immutableStatements: ts.Statement[] = [];
1470  let judgeIdStart: number;
1471  if (idName) {
1472    judgeIdStart = innerCompStatements.length;
1473  }
1474  if (tabContentBody && tabContentBody.statements.length) {
1475    const newTabContentChildren: ts.Statement[] = [];
1476    processComponentChild(tabContentBody, newTabContentChildren, log, {isAcceleratePreview: false, line: 0, column: 0, fileName: ''},
1477      false, parent, undefined, isGlobalBuilder, false, builderParamsResult, isInRepeatTemplate);
1478    const navDestinationCallback: (ts.ArrowFunction | ts.NewExpression | ts.ObjectLiteralExpression)[] =
1479      [ts.factory.createArrowFunction(undefined, undefined, [], undefined,
1480      ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1481      ts.factory.createBlock([...newTabContentChildren], true))];
1482    if (name === NAV_DESTINATION) {
1483      navDestinationCallback.push(...navigationCreateParam(NAV_DESTINATION, COMPONENT_CREATE_FUNCTION, undefined, true));
1484    }
1485    tabContentCreation = ts.factory.createExpressionStatement(
1486      ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
1487        ts.factory.createIdentifier(name), ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)),
1488      undefined, navDestinationCallback));
1489    bindComponentAttr(node, ts.factory.createIdentifier(name), tabAttrs, log, true, false, immutableStatements);
1490    processInnerCompStatements(
1491      innerCompStatements, [tabContentCreation, ...tabAttrs], node, isGlobalBuilder, false,
1492      nameResult, immutableStatements, name, builderParamsResult);
1493    storedFileInfo.lazyForEachInfo.isDependItem = false;
1494  } else {
1495    tabContentCreation = ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1496      ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(name),
1497        ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined,
1498        name === NAV_DESTINATION ? navigationCreateParam(NAV_DESTINATION, COMPONENT_CREATE_FUNCTION) : []));
1499    bindComponentAttr(node, ts.factory.createIdentifier(name), tabAttrs, log, true, false, immutableStatements);
1500    processInnerCompStatements(
1501      innerCompStatements, [tabContentCreation, ...tabAttrs], node, isGlobalBuilder, false,
1502      nameResult, immutableStatements, name, builderParamsResult);
1503  }
1504  innerCompStatements.push(tabContentPop);
1505  if (idName) {
1506    innerCompStatements.splice(judgeIdStart, innerCompStatements.length - judgeIdStart,
1507      ifRetakeId(innerCompStatements.slice(judgeIdStart), idName));
1508  }
1509}
1510
1511export function getRealNodePos(node: ts.Node): number {
1512  // @ts-ignore
1513  if (node.pos === -1 && node.expression) {
1514    // @ts-ignore
1515    return getRealNodePos(node.expression);
1516  } else {
1517    return node.getStart();
1518  }
1519}
1520
1521function processForEachComponent(node: ts.ExpressionStatement, newStatements: ts.Statement[],
1522  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false): void {
1523  const popNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(createFunction(
1524    // @ts-ignore
1525    node.expression.expression as ts.Identifier,
1526    ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null));
1527  if (ts.isCallExpression(node.expression)) {
1528    const propertyNode: ts.PropertyAccessExpression = ts.factory.createPropertyAccessExpression(
1529      node.expression.expression as ts.Identifier,
1530      ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)
1531    );
1532    const argumentsArray: ts.Expression[] = Array.from(node.expression.arguments);
1533    let arrayObserveredObject: ts.CallExpression;
1534    if (argumentsArray.length) {
1535      arrayObserveredObject = ts.factory.createCallExpression(
1536        ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(FOREACH_OBSERVED_OBJECT),
1537          ts.factory.createIdentifier(FOREACH_GET_RAW_OBJECT)), undefined, [argumentsArray[0]]);
1538    }
1539    argumentsArray.splice(0, 1, arrayObserveredObject);
1540    const newForEachArrowFunc: ts.ArrowFunction = processForEachFunctionBlock(node.expression);
1541    const newArrowNode: ts.ArrowFunction =
1542      processForEachBlock(node.expression, log, newForEachArrowFunc, isBuilder) as ts.ArrowFunction;
1543    if (newArrowNode) {
1544      argumentsArray.splice(1, 1, newArrowNode);
1545    }
1546    node = addForEachId(ts.factory.updateExpressionStatement(node, ts.factory.updateCallExpression(
1547      node.expression, propertyNode, node.expression.typeArguments, argumentsArray)), isGlobalBuilder);
1548  }
1549  newStatements.push(node, popNode);
1550}
1551
1552function collectForEachAttribute(node: ts.ExpressionStatement,
1553  attributeList: ts.ExpressionStatement[], name: string): ts.ExpressionStatement {
1554  let tempNode = node.expression;
1555  while (tempNode && ts.isCallExpression(tempNode)) {
1556    if (tempNode.expression && ts.isPropertyAccessExpression(tempNode.expression)) {
1557      attributeList.unshift(generateForEachAttribute(tempNode, name));
1558    } else if (tempNode.expression && ts.isIdentifier(tempNode.expression)) {
1559      return ts.factory.updateExpressionStatement(node, tempNode);
1560    }
1561    tempNode = tempNode.expression?.expression;
1562  }
1563  return node;
1564}
1565
1566function generateForEachAttribute(tempNode: ts.CallExpression, name: string): ts.ExpressionStatement {
1567  return ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1568    ts.factory.createPropertyAccessExpression(
1569      ts.factory.createIdentifier(name),
1570      tempNode.expression.name
1571    ),
1572    undefined,
1573    tempNode.arguments
1574  ));
1575}
1576
1577function processForEachComponentNew(node: ts.ExpressionStatement, newStatements: ts.Statement[],
1578  log: LogInfo[], name: string, isGlobalBuilder: boolean = false, builderParamsResult: BuilderParamsResult = null,
1579  isInRepeatTemplate: boolean = false): void {
1580  const attributeList: ts.ExpressionStatement[] = [];
1581  const newNode = collectForEachAttribute(node, attributeList, name);
1582  const newForEachStatements: ts.Statement[] = [];
1583  const popNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(createFunction(
1584    (newNode.expression as ts.CallExpression).expression as ts.Identifier,
1585    ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null));
1586  if (ts.isCallExpression(newNode.expression)) {
1587    if (checkForEachComponent(newNode)) {
1588      storedFileInfo.processForEach += 1;
1589    } else {
1590      storedFileInfo.processLazyForEach += 1;
1591    }
1592    const argumentsArray: ts.Expression[] = Array.from(newNode.expression.arguments);
1593    const propertyNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
1594      ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
1595        newNode.expression.expression as ts.Identifier,
1596        ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)), undefined, []));
1597    const newForEachArrowFunc: ts.ArrowFunction = processForEachFunctionBlock(newNode.expression);
1598    const newArrowNode: ts.NodeArray<ts.Statement> =
1599      processForEachBlock(newNode.expression, log, newForEachArrowFunc, false, isGlobalBuilder,
1600        builderParamsResult, isInRepeatTemplate) as ts.NodeArray<ts.Statement>;
1601    const itemGenFunctionStatement: ts.VariableStatement = createItemGenFunctionStatement(newNode.expression, newArrowNode, newForEachArrowFunc);
1602    const itemIdFuncStatement: ts.VariableStatement = createItemIdFuncStatement(newNode.expression, argumentsArray);
1603    const updateFunctionStatement: ts.ExpressionStatement = createUpdateFunctionStatement(argumentsArray, newForEachArrowFunc, isGlobalBuilder);
1604    const lazyForEachStatement: ts.ExpressionStatement = createLazyForEachStatement(argumentsArray);
1605    if (newNode.expression.expression.getText() === COMPONENT_FOREACH) {
1606      newForEachStatements.push(propertyNode, ...attributeList, itemGenFunctionStatement, updateFunctionStatement);
1607      newStatements.push(createComponentCreationStatement(newNode, newForEachStatements, COMPONENT_FOREACH,
1608        isGlobalBuilder, false, undefined, null, builderParamsResult), popNode);
1609    } else {
1610      if (argumentsArray[2]) {
1611        newStatements.push(ts.factory.createBlock([itemGenFunctionStatement, itemIdFuncStatement, lazyForEachStatement,
1612          ...attributeList, popNode], true));
1613      } else {
1614        newStatements.push(ts.factory.createBlock([itemGenFunctionStatement, lazyForEachStatement, popNode, ...attributeList], true));
1615      }
1616    }
1617    if (checkForEachComponent(newNode)) {
1618      storedFileInfo.processForEach -= 1;
1619    } else {
1620      storedFileInfo.processLazyForEach -= 1;
1621    }
1622  }
1623}
1624
1625function checkForEachComponent(node: ts.ExpressionStatement): boolean {
1626  return node.expression.expression && ts.isIdentifier(node.expression.expression) &&
1627    node.expression.expression.getText() === COMPONENT_FOREACH;
1628}
1629
1630function createItemGenFunctionStatement(
1631  node: ts.CallExpression,
1632  newArrowNode: ts.NodeArray<ts.Statement>,
1633  newForEachArrowFunc: ts.ArrowFunction
1634): ts.VariableStatement {
1635  if (newForEachArrowFunc && ts.isArrowFunction(newForEachArrowFunc)) {
1636    return ts.factory.createVariableStatement(
1637      undefined,
1638      ts.factory.createVariableDeclarationList(
1639        [ts.factory.createVariableDeclaration(
1640          ts.factory.createIdentifier(node.expression.getText() === COMPONENT_FOREACH ?
1641            FOREACHITEMGENFUNCTION : __LAZYFOREACHITEMGENFUNCTION),
1642          undefined, undefined,
1643          ts.factory.createArrowFunction(
1644            undefined, undefined,
1645            newForEachArrowFunc.parameters && newForEachArrowFunc.parameters.length >= 1 ?
1646              getParameters(newForEachArrowFunc) : [],
1647            undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1648            ts.factory.createBlock(
1649              newForEachArrowFunc.parameters && newForEachArrowFunc.parameters.length >= 1 ?
1650                isForEachItemGeneratorParam(newForEachArrowFunc, newArrowNode) :
1651                newArrowNode ? [...newArrowNode] : undefined,
1652              true
1653            )
1654          )
1655        )
1656        ],
1657        ts.NodeFlags.Const
1658      )
1659    );
1660  }
1661  return undefined;
1662}
1663
1664function isForEachItemGeneratorParam(argumentsArray: ts.Expression, newArrowNode: ts.NodeArray<ts.Statement>): ts.Statement[] {
1665  const createVariableStatementNode: ts.Statement[] = [];
1666  createVariableStatementNode.push(ts.factory.createVariableStatement(
1667    undefined,
1668    ts.factory.createVariableDeclarationList(
1669      [ts.factory.createVariableDeclaration(
1670        ts.factory.createIdentifier(
1671          argumentsArray.parameters[0] && argumentsArray.parameters[0].name.getText()),
1672        undefined,
1673        undefined,
1674        ts.factory.createIdentifier(_ITEM)
1675      )],
1676      ts.NodeFlags.Const
1677    )
1678  ));
1679  if (newArrowNode) {
1680    createVariableStatementNode.push(...newArrowNode);
1681  }
1682  return createVariableStatementNode;
1683}
1684
1685function getParameters(node: ts.ArrowFunction): ts.ParameterDeclaration[] {
1686  const parameterArr: ts.ParameterDeclaration[] = [
1687    ts.factory.createParameterDeclaration(
1688      undefined, undefined, ts.factory.createIdentifier(_ITEM))
1689  ];
1690  if (node.parameters && node.parameters.length > 1) {
1691    parameterArr.push(node.parameters[1]);
1692  }
1693  if (projectConfig.optLazyForEach && storedFileInfo.processLazyForEach) {
1694    if (node.parameters.length === 1) {
1695      parameterArr.push(ts.factory.createParameterDeclaration(
1696        undefined, undefined, ts.factory.createIdentifier(INDEX)));
1697    }
1698    parameterArr.push(
1699      ts.factory.createParameterDeclaration(
1700        undefined, undefined, ts.factory.createIdentifier(IS_INITIAL_ITEM)),
1701      ts.factory.createParameterDeclaration(
1702        undefined, undefined, ts.factory.createIdentifier(IDS))
1703    );
1704  }
1705  return parameterArr;
1706}
1707
1708function createItemIdFuncStatement(
1709  node: ts.CallExpression,
1710  argumentsArray: ts.Expression[]
1711): ts.VariableStatement {
1712  if (argumentsArray[2]) {
1713    return ts.factory.createVariableStatement(
1714      undefined,
1715      ts.factory.createVariableDeclarationList(
1716        [ts.factory.createVariableDeclaration(
1717          ts.factory.createIdentifier(node.expression.getText() === COMPONENT_FOREACH ?
1718            FOREACHITEMIDFUNC : __LAZYFOREACHITEMIDFUNC), undefined, undefined,
1719          argumentsArray[2]
1720        )],
1721        ts.NodeFlags.Const
1722      )
1723    );
1724  }
1725  return undefined;
1726}
1727
1728function createUpdateFunctionStatement(argumentsArray: ts.Expression[],
1729  newForEachArrowFunc: ts.ArrowFunction, isGlobalBuilder: boolean = false): ts.ExpressionStatement {
1730  return ts.factory.createExpressionStatement(
1731    ts.factory.createCallExpression(
1732      ts.factory.createPropertyAccessExpression(
1733        isGlobalBuilder ? parentConditionalExpression() : ts.factory.createThis(),
1734        ts.factory.createIdentifier(FOREACHUPDATEFUNCTION)
1735      ),
1736      undefined,
1737      addForEachIdFuncParameter(argumentsArray, newForEachArrowFunc)
1738    )
1739  );
1740}
1741
1742function addForEachIdFuncParameter(argumentsArray: ts.Expression[], newForEachArrowFunc: ts.ArrowFunction): ts.Expression[] {
1743  const addForEachIdFuncParameterArr: ts.Expression[] = [];
1744  addForEachIdFuncParameterArr.push(
1745    ts.factory.createIdentifier(ELMTID),
1746    argumentsArray[0],
1747    ts.factory.createIdentifier(FOREACHITEMGENFUNCTION)
1748  );
1749  // @ts-ignore
1750  if (newForEachArrowFunc && newForEachArrowFunc.parameters && newForEachArrowFunc.parameters[1]) {
1751    if (!argumentsArray[2]) {
1752      addForEachIdFuncParameterArr.push(...addForEachParameter(ts.factory.createIdentifier(COMPONENT_IF_UNDEFINED), TRUE, FALSE));
1753    } else {
1754      // @ts-ignore
1755      argumentsArray[2].parameters && argumentsArray[2].parameters[1] ?
1756        addForEachIdFuncParameterArr.push(...addForEachParameter(argumentsArray[2], TRUE, TRUE)) :
1757        addForEachIdFuncParameterArr.push(...addForEachParameter(argumentsArray[2], TRUE, FALSE));
1758    }
1759  }
1760  // @ts-ignore
1761  if (newForEachArrowFunc && newForEachArrowFunc.parameters && newForEachArrowFunc.parameters.length < 2 && newForEachArrowFunc.parameters[0] &&
1762    argumentsArray && argumentsArray.length > 2 && argumentsArray[2]) {
1763    // @ts-ignore
1764    argumentsArray[2].parameters && argumentsArray[2].parameters[1] ?
1765      addForEachIdFuncParameterArr.push(...addForEachParameter(argumentsArray[2], FALSE, TRUE)) :
1766      addForEachIdFuncParameterArr.push(...addForEachParameter(argumentsArray[2], FALSE, FALSE));
1767  }
1768  return addForEachIdFuncParameterArr;
1769}
1770
1771function addForEachParameter(forEachItemIdContent: ts.Expression, forEachItemGen: string, forEachItemId: string): ts.Expression[] {
1772  return [forEachItemIdContent, ts.factory.createIdentifier(forEachItemGen),
1773    ts.factory.createIdentifier(forEachItemId)];
1774}
1775
1776function createLazyForEachStatement(argumentsArray: ts.Expression[]): ts.ExpressionStatement {
1777  const parameterList: ts.Expression[] = [
1778    ts.factory.createStringLiteral(componentInfo.id.toString()),
1779    ts.factory.createThis(),
1780    argumentsArray[0],
1781    ts.factory.createIdentifier(__LAZYFOREACHITEMGENFUNCTION)
1782  ];
1783  if (argumentsArray.length >= 3 && argumentsArray[2]) {
1784    parameterList.push(ts.factory.createIdentifier(__LAZYFOREACHITEMIDFUNC));
1785  }
1786  if (projectConfig.optLazyForEach) {
1787    parameterList.push(ts.factory.createTrue());
1788  }
1789  return ts.factory.createExpressionStatement(
1790    ts.factory.createCallExpression(
1791      ts.factory.createPropertyAccessExpression(
1792        ts.factory.createIdentifier(COMPONENT_LAZYFOREACH),
1793        ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION)
1794      ),
1795      undefined,
1796      parameterList
1797    )
1798  );
1799}
1800
1801function addForEachId(node: ts.ExpressionStatement, isGlobalBuilder: boolean = false): ts.ExpressionStatement {
1802  const forEachComponent: ts.CallExpression = node.expression as ts.CallExpression;
1803  return ts.factory.updateExpressionStatement(node, ts.factory.updateCallExpression(
1804    forEachComponent, forEachComponent.expression, forEachComponent.typeArguments,
1805    [ts.factory.createStringLiteral((++componentInfo.id).toString()),
1806      isGlobalBuilder ? parentConditionalExpression() : ts.factory.createThis(),
1807      ...forEachComponent.arguments]));
1808}
1809
1810export function parentConditionalExpression(): ts.ConditionalExpression {
1811  return ts.factory.createConditionalExpression(
1812    ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT),
1813    ts.factory.createToken(ts.SyntaxKind.QuestionToken),
1814    ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT),
1815    ts.factory.createToken(ts.SyntaxKind.ColonToken),
1816    ts.factory.createThis());
1817}
1818function processForEachFunctionBlock(node: ts.CallExpression): ts.ArrowFunction {
1819  if (ts.isArrowFunction(node.arguments[1])) {
1820    return node.arguments[1];
1821  } else if (ts.isParenthesizedExpression(node.arguments[1]) && ts.isArrowFunction(node.arguments[1].expression)) {
1822    return node.arguments[1].expression;
1823  } else {
1824    return null;
1825  }
1826}
1827function processForEachBlock(node: ts.CallExpression, log: LogInfo[],
1828  arrowNode: ts.ArrowFunction, isBuilder: boolean = false, isGlobalBuilder: boolean = false,
1829  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): ts.NodeArray<ts.Statement> | ts.ArrowFunction {
1830  if (node.arguments.length > 1 && ts.isArrowFunction(arrowNode)) {
1831    const isLazy: boolean = node.expression.getText() === COMPONENT_LAZYFOREACH;
1832    const body: ts.ConciseBody = arrowNode.body;
1833    if (!ts.isBlock(body)) {
1834      const statement: ts.Statement = ts.factory.createExpressionStatement(body);
1835      const blockNode: ts.Block = ts.factory.createBlock([statement], true);
1836      // @ts-ignore
1837      statement.parent = blockNode;
1838      if (!partialUpdateConfig.partialUpdateMode) {
1839        return ts.factory.updateArrowFunction(
1840          arrowNode, ts.getModifiers(arrowNode), arrowNode.typeParameters, arrowNode.parameters,
1841          arrowNode.type, arrowNode.equalsGreaterThanToken,
1842          processComponentBlock(blockNode, isLazy, log, false, false, undefined,
1843            arrowNode.parameters, isGlobalBuilder));
1844      } else {
1845        return processComponentBlock(blockNode, isLazy, log, false, false, undefined,
1846          arrowNode.parameters, isGlobalBuilder, builderParamsResult, false, isInRepeatTemplate).statements;
1847      }
1848    } else {
1849      if (!partialUpdateConfig.partialUpdateMode) {
1850        return ts.factory.updateArrowFunction(
1851          arrowNode, ts.getModifiers(arrowNode), arrowNode.typeParameters, arrowNode.parameters,
1852          arrowNode.type, arrowNode.equalsGreaterThanToken,
1853          processComponentBlock(body, isLazy, log, false, isBuilder, undefined, arrowNode.parameters));
1854      } else {
1855        return processComponentBlock(body, isLazy, log, false, false, undefined, arrowNode.parameters,
1856          isGlobalBuilder, builderParamsResult, false, isInRepeatTemplate).statements;
1857      }
1858    }
1859  }
1860  return null;
1861}
1862
1863function createRenderingInProgress(isTrue: boolean): ts.ExpressionStatement {
1864  return ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(
1865    ts.factory.createPropertyAccessExpression(
1866      ts.factory.createThis(),
1867      ts.factory.createIdentifier(IS_RENDERING_IN_PROGRESS)
1868    ),
1869    ts.factory.createToken(ts.SyntaxKind.EqualsToken),
1870    isTrue ? ts.factory.createTrue() : ts.factory.createFalse()
1871  ));
1872}
1873
1874function addElmtIdNode(): boolean {
1875  return partialUpdateConfig.partialUpdateMode && projectConfig.optLazyForEach &&
1876    ((storedFileInfo.processLazyForEach && storedFileInfo.lazyForEachInfo.isDependItem) || storedFileInfo.processBuilder);
1877}
1878
1879function processIfStatement(node: ts.IfStatement, newStatements: ts.Statement[],
1880  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false,
1881  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): void {
1882  const ifStatements: ts.Statement[] = [];
1883  if (addElmtIdNode()) {
1884    ifStatements.push(createCollectElmtIdNode());
1885    storedFileInfo.lazyForEachInfo.isDependItem = false;
1886  }
1887  const ifCreate: ts.ExpressionStatement = createIfCreate();
1888  const newIfNode: ts.IfStatement = processInnerIfStatement(node, 0, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1889  ifStatements.push(ifCreate, newIfNode);
1890  const ifPop: ts.ExpressionStatement = createIfPop();
1891  if (!partialUpdateConfig.partialUpdateMode) {
1892    newStatements.push(ifCreate, newIfNode, ifPop);
1893  } else {
1894    newStatements.push(createComponentCreationStatement(node, ifStatements, COMPONENT_IF,
1895      isGlobalBuilder, false, undefined, null, builderParamsResult), ifPop);
1896  }
1897}
1898
1899function processInnerIfStatement(node: ts.IfStatement, id: number, log: LogInfo[],
1900  isBuilder: boolean = false, isGlobalBuilder: boolean = false,
1901  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): ts.IfStatement {
1902  if (ts.isIdentifier(node.expression) && node.expression.originalKeywordKind === undefined &&
1903    !node.expression.escapedText) {
1904    log.push({
1905      type: LogType.ERROR,
1906      message: 'Condition expression cannot be null in if statement.',
1907      pos: node.expression.getStart(),
1908      code: '10905208'
1909    });
1910    node = ts.factory.updateIfStatement(node, ts.factory.createIdentifier(COMPONENT_IF_UNDEFINED),
1911      node.thenStatement, node.elseStatement);
1912  }
1913  const newThenStatement: ts.Statement = processThenStatement(
1914    node.thenStatement, id, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1915  const newElseStatement: ts.Statement = processElseStatement(
1916    node.elseStatement, id, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1917  const newIfNode: ts.IfStatement = ts.factory.updateIfStatement(
1918    node, node.expression, newThenStatement, newElseStatement);
1919  return newIfNode;
1920}
1921
1922function processThenStatement(thenStatement: ts.Statement, id: number,
1923  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false,
1924  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): ts.Statement {
1925  if (ts.isExpressionStatement(thenStatement) && ts.isIdentifier(thenStatement.expression) &&
1926    thenStatement.expression.originalKeywordKind === undefined &&
1927    !thenStatement.expression.escapedText) {
1928    log.push({
1929      type: LogType.ERROR,
1930      message: 'Then statement cannot be null in if statement.',
1931      pos: thenStatement.expression.getStart(),
1932      code: '10905207'
1933    });
1934  }
1935  if (thenStatement) {
1936    if (ts.isBlock(thenStatement)) {
1937      thenStatement = processIfBlock(thenStatement, id, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1938    } else if (ts.isIfStatement(thenStatement)) {
1939      thenStatement = processInnerIfStatement(thenStatement, 0, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1940      thenStatement = ts.factory.createBlock(
1941        partialUpdateConfig.partialUpdateMode ?
1942          [createIfCreate(), createIfBranchFunc(id, [thenStatement], isGlobalBuilder), createIfPop()] :
1943          [createIfCreate(), createIfBranchId(id), thenStatement, createIfPop()],
1944        true
1945      );
1946    } else {
1947      thenStatement = ts.factory.createBlock([thenStatement], true);
1948      thenStatement = processIfBlock(thenStatement as ts.Block, id, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1949    }
1950  }
1951  return thenStatement;
1952}
1953
1954function processElseStatement(elseStatement: ts.Statement, id: number,
1955  log: LogInfo[], isBuilder: boolean = false, isGlobalBuilder: boolean = false,
1956  builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): ts.Statement {
1957  if (elseStatement) {
1958    if (ts.isBlock(elseStatement)) {
1959      elseStatement = processIfBlock(elseStatement, id + 1, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1960    } else if (ts.isIfStatement(elseStatement)) {
1961      elseStatement = processInnerIfStatement(elseStatement, id + 1, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1962    } else {
1963      elseStatement = ts.factory.createBlock([elseStatement], true);
1964      elseStatement = processIfBlock(elseStatement as ts.Block, id + 1, log, isBuilder, isGlobalBuilder, builderParamsResult, isInRepeatTemplate);
1965    }
1966  } else if (partialUpdateConfig.partialUpdateMode) {
1967    elseStatement = ts.factory.createBlock([
1968      ts.factory.createExpressionStatement(ts.factory.createCallExpression(
1969        ts.factory.createPropertyAccessExpression(
1970          ts.factory.createThis(),
1971          ts.factory.createIdentifier(IFELSEBRANCHUPDATEFUNCTION)
1972        ),
1973        undefined,
1974        [
1975          ts.factory.createNumericLiteral(++id),
1976          ts.factory.createArrowFunction(
1977            undefined,
1978            undefined,
1979            [],
1980            undefined,
1981            ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
1982            ts.factory.createBlock(
1983              [],
1984              true
1985            )
1986          )
1987        ]
1988      ))
1989    ], true);
1990  }
1991  return elseStatement;
1992}
1993
1994function processIfBlock(block: ts.Block, id: number, log: LogInfo[], isBuilder: boolean = false,
1995  isGlobalBuilder: boolean = false, builderParamsResult: BuilderParamsResult = null, isInRepeatTemplate: boolean = false): ts.Block {
1996  return addIfBranchId(id, isGlobalBuilder,
1997    processComponentBlock(block, false, log, false, isBuilder, COMPONENT_IF, undefined, isGlobalBuilder, builderParamsResult, false, isInRepeatTemplate));
1998}
1999
2000function addIfBranchId(id: number, isGlobalBuilder: boolean = false, container: ts.Block): ts.Block {
2001  let containerStatements: ts.Statement[];
2002  if (partialUpdateConfig.partialUpdateMode) {
2003    containerStatements = [createIfBranchFunc(id, [...container.statements], isGlobalBuilder)];
2004  } else {
2005    containerStatements = [createIfBranchId(id), ...container.statements];
2006  }
2007  return ts.factory.updateBlock(container, containerStatements);
2008}
2009
2010function createIf(): ts.Identifier {
2011  return ts.factory.createIdentifier(COMPONENT_IF);
2012}
2013
2014function createIfCreate(): ts.ExpressionStatement {
2015  return ts.factory.createExpressionStatement(createFunction(createIf(),
2016    ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), ts.factory.createNodeArray([])));
2017}
2018
2019function createIfPop(): ts.ExpressionStatement {
2020  return ts.factory.createExpressionStatement(createFunction(createIf(),
2021    ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null));
2022}
2023
2024function createIfBranchId(id: number): ts.ExpressionStatement {
2025  return ts.factory.createExpressionStatement(createFunction(createIf(),
2026    ts.factory.createIdentifier(COMPONENT_IF_BRANCH_ID_FUNCTION),
2027    ts.factory.createNodeArray([ts.factory.createNumericLiteral(id)])));
2028}
2029
2030function createIfBranchFunc(id: number, innerStatements: ts.Statement[],
2031  isGlobalBuilder: boolean = false): ts.ExpressionStatement {
2032  return ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(
2033    isGlobalBuilder ? parentConditionalExpression() : ts.factory.createThis(),
2034    ts.factory.createIdentifier(IFELSEBRANCHUPDATEFUNCTION)), undefined,
2035  [ts.factory.createNumericLiteral(id), ts.factory.createArrowFunction(undefined, undefined, [], undefined,
2036    ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock(innerStatements, true))]));
2037}
2038
2039interface CreateResult {
2040  newNode: ts.ExpressionStatement;
2041  identifierNode: ts.Identifier;
2042  isContainerComponent: boolean;
2043  isButton: boolean;
2044  needPop: boolean;
2045}
2046
2047function createComponent(node: ts.ExpressionStatement, type: string): CreateResult {
2048  const res: CreateResult = {
2049    newNode: node,
2050    identifierNode: null,
2051    isContainerComponent: false,
2052    isButton: false,
2053    needPop: false
2054  };
2055  let identifierNode: ts.Identifier = ts.factory.createIdentifier(type);
2056  let temp: any = node.expression;
2057  while (temp && !ts.isIdentifier(temp) && temp.expression) {
2058    temp = temp.expression;
2059  }
2060  if (temp && temp.parent && (ts.isCallExpression(temp.parent) ||
2061    ts.isEtsComponentExpression(temp.parent)) && ts.isIdentifier(temp)) {
2062    if (temp.getText() === COMPONENT_BUTTON && type !== COMPONENT_POP_FUNCTION) {
2063      res.isButton = true;
2064      identifierNode = type === COMPONENT_CREATE_CHILD_FUNCTION ?
2065        ts.factory.createIdentifier(COMPONENT_CREATE_CHILD_FUNCTION) :
2066        ts.factory.createIdentifier(COMPONENT_CREATE_LABEL_FUNCTION);
2067    }
2068    if (NEEDPOP_COMPONENT.has(temp.getText())) {
2069      res.needPop = true;
2070    }
2071    if (checkContainer(temp.getText(), temp.parent)) {
2072      res.isContainerComponent = true;
2073    }
2074    res.newNode = type === COMPONENT_POP_FUNCTION ?
2075      ts.factory.createExpressionStatement(createFunction(temp, identifierNode, null)) :
2076      ts.factory.createExpressionStatement(createFunction(temp, identifierNode, checkArguments(temp, type)));
2077    res.identifierNode = temp;
2078  }
2079  return res;
2080}
2081
2082function checkArguments(temp: ts.Identifier, type: string): ts.Expression[] {
2083  const newArguments: ts.Expression[] = [];
2084  if (CUSTOM_BUILDER_CONSTRUCTORS.has(temp.escapedText.toString())) {
2085    temp.parent.arguments.forEach(argument => {
2086      if (ts.isConditionalExpression(argument)) {
2087        newArguments.push(processConditionalBuilder(argument, temp, type));
2088      } else if (isBuilderChangeNode(argument, temp, type)) {
2089        newArguments.push(parseBuilderNode(argument, type));
2090      } else {
2091        newArguments.push(argument);
2092      }
2093    });
2094    return newArguments;
2095  }
2096  return temp.getText() === 'XComponent' && type === COMPONENT_CREATE_FUNCTION &&
2097    projectConfig.moduleName && projectConfig.bundleName ?
2098    // @ts-ignore
2099    temp.parent.arguments.concat([
2100      ts.factory.createStringLiteral(`${projectConfig.bundleName}/${projectConfig.moduleName}`)
2101    ]) : temp.parent.arguments;
2102}
2103
2104function checkContainer(name: string, node: ts.Node): boolean {
2105  return BUILDIN_CONTAINER_COMPONENT.has(name) && (name !== 'XComponent' ||
2106    (node && node.arguments && node.arguments.length &&
2107    ts.isObjectLiteralExpression(node.arguments[0]) && node.arguments[0].properties &&
2108    checkComponentType(node.arguments[0].properties)));
2109}
2110
2111function checkComponentType(properties: ts.PropertyAssignment[]): boolean {
2112  let flag: boolean = false;
2113  properties.forEach(item => {
2114    if (isXComponentContainer(item)) {
2115      flag = true;
2116    }
2117  });
2118  return flag;
2119}
2120
2121function isXComponentContainer(item: ts.PropertyAssignment): boolean {
2122  return item.name && ts.isIdentifier(item.name) && item.name.getText() === RESOURCE_NAME_TYPE &&
2123    item.initializer && ((ts.isStringLiteral(item.initializer) &&
2124    // value = 'component'
2125    (item.initializer.getText() === XCOMPONENT_SINGLE_QUOTATION ||
2126    item.initializer.getText() === XCOMPONENT_DOUBLE_QUOTATION)) ||
2127    // value = 1
2128    (ts.isNumericLiteral(item.initializer) && item.initializer.getText() === '1') ||
2129    // value = XComponentType.COMPONENT
2130    (ts.isPropertyAccessExpression(item.initializer) && item.initializer.expression &&
2131    ts.isIdentifier(item.initializer.expression) && item.initializer.name &&
2132    ts.isIdentifier(item.initializer.name) && item.initializer.expression.getText() === XCOMPONENTTYPE) &&
2133    item.initializer.name.getText() === XCOMPONENTTYPE_CONTAINER);
2134}
2135
2136interface AnimationInfo {
2137  statement: ts.Statement,
2138  kind: boolean,
2139  hasAnimationAttr: boolean,
2140}
2141
2142export interface ComponentAttrInfo {
2143  reuseId: ts.Node,
2144  hasIdAttr: boolean,
2145  attrCount: number,
2146  reuse: string,
2147}
2148
2149export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode: ts.Identifier,
2150  newStatements: ts.Statement[], log: LogInfo[], reverse: boolean = true,
2151  isStylesAttr: boolean = false, newImmutableStatements: ts.Statement[] = null,
2152  isStyleFunction: boolean = false, componentAttrInfo: ComponentAttrInfo = null,
2153  isReusableV2NodeAttr: boolean = false): void {
2154  const isStylesUIComponent: boolean = validateStylesUIComponent(node, isStylesAttr);
2155  let temp = node.expression;
2156  const statements: ts.Statement[] = [];
2157  const immutableStatements: ts.Statement[] = [];
2158  const updateStatements: ts.Statement[] = [];
2159  const lastStatement: AnimationInfo = {
2160    statement: null,
2161    kind: false,
2162    hasAnimationAttr: false
2163  };
2164  const isRecycleComponent: boolean = isRecycle(componentCollection.currentClassName);
2165  const isReuseComponentInV2: boolean = isReuseInV2(componentCollection.currentClassName);
2166  if (ts.isPropertyAccessExpression(temp) || isStylesUIComponent) {
2167    log.push({
2168      type: isStylesUIComponent ? LogType.WARN : LogType.ERROR,
2169      message: `'${node.getText()}' does not meet UI component syntax.`,
2170      pos: node.getStart(),
2171      code: '10905206'
2172    });
2173  }
2174  while (temp && ts.isCallExpression(temp) && temp.expression) {
2175    let flag: boolean = false;
2176    if (temp.expression && (validatePropertyAccessExpressionWithCustomBuilder(temp.expression) ||
2177      validateIdentifierWithCustomBuilder(temp.expression))) {
2178      let propertyName: string = '';
2179      if (ts.isIdentifier(temp.expression)) {
2180        propertyName = temp.expression.escapedText.toString();
2181      } else if (ts.isPropertyAccessExpression(temp.expression)) {
2182        propertyName = temp.expression.name.escapedText.toString();
2183      }
2184      switch (true) {
2185        case BIND_POPUP_SET.has(propertyName):
2186          temp = processBindPopupBuilder(temp);
2187          break;
2188        case BIND_DRAG_SET.has(propertyName):
2189          temp = processDragStartBuilder(temp, propertyName);
2190          break;
2191        default:
2192          temp = processCustomBuilderProperty(temp, identifierNode, propertyName);
2193      }
2194    }
2195    if (ts.isPropertyAccessExpression(temp.expression) &&
2196      temp.expression.name && ts.isIdentifier(temp.expression.name) &&
2197      (!componentCollection.customComponents.has(temp.expression.name.getText()) || STYLES_ATTRIBUTE.has(temp.expression.name.getText()))) {
2198      parseRecycleId(temp, temp.expression.name, componentAttrInfo, log, isReusableV2NodeAttr);
2199      addComponentAttr(temp, temp.expression.name, lastStatement, statements, identifierNode, log,
2200        isStylesAttr, immutableStatements, updateStatements, newImmutableStatements,
2201        isRecycleComponent, isReuseComponentInV2, isStyleFunction);
2202      temp = temp.expression.expression;
2203      flag = true;
2204    } else if (ts.isIdentifier(temp.expression)) {
2205      if (!INNER_COMPONENT_NAMES.has(temp.expression.getText()) &&
2206        !GESTURE_TYPE_NAMES.has(temp.expression.getText()) &&
2207        !componentCollection.customComponents.has(temp.expression.getText())) {
2208        parseRecycleId(temp, temp.expression.name, componentAttrInfo, log, isReusableV2NodeAttr);
2209        addComponentAttr(temp, temp.expression, lastStatement, statements, identifierNode, log,
2210          isStylesAttr, immutableStatements, updateStatements, newImmutableStatements,
2211          isRecycleComponent, isReuseComponentInV2, isStyleFunction);
2212      }
2213      break;
2214    }
2215    if (!flag) {
2216      temp = temp.expression;
2217    }
2218  }
2219  if (lastStatement.statement && lastStatement.kind) {
2220    statements.push(lastStatement.statement);
2221  }
2222  if ((!isRecycleComponent && !isReuseComponentInV2) || lastStatement.hasAnimationAttr) {
2223    if (statements.length) {
2224      reverse ? newStatements.push(...statements.reverse()) : newStatements.push(...statements);
2225    }
2226  } else {
2227    if (updateStatements.length) {
2228      reverse ? newStatements.push(...updateStatements.reverse()) : newStatements.push(...updateStatements);
2229    }
2230    if (newImmutableStatements && immutableStatements.length) {
2231      reverse ? newImmutableStatements.push(...immutableStatements.reverse()) : newImmutableStatements.push(...immutableStatements);
2232    }
2233  }
2234}
2235
2236function validateStylesUIComponent(node: ts.ExpressionStatement, isStylesAttr: boolean): boolean {
2237  return (ts.isIfStatement(node) || ts.isSwitchStatement(node)) && isStylesAttr;
2238}
2239
2240function parseRecycleId(node: ts.CallExpression, attr: ts.Identifier, componentAttrInfo: ComponentAttrInfo, log: LogInfo[],
2241  isReusableV2NodeAttr: boolean = false): void {
2242  if (componentAttrInfo) {
2243    const attrName: string = attr.escapedText.toString();
2244    if (attrName === RECYCLE_REUSE_ID) {
2245      logMessageCollection.checkUsageOfReuseIdAttribute(node, isReusableV2NodeAttr, log);
2246      componentAttrInfo.reuseId = node.arguments[0];
2247    } else if (attrName === ATTRIBUTE_ID) {
2248      componentAttrInfo.hasIdAttr = true;
2249    } else if (attrName === REUSE_ATTRIBUTE) {
2250      logMessageCollection.checkUsageOfReuseAttribute(node, isReusableV2NodeAttr, log);
2251      if (ts.isObjectLiteralExpression(node.arguments[0]) && !!getReuseIdInReuse(node.arguments[0])) {
2252        componentAttrInfo.reuse = getReuseIdInReuse(node.arguments[0]);
2253      } else {
2254        componentAttrInfo.reuse = '';
2255      }
2256    }
2257    componentAttrInfo.attrCount++;
2258  }
2259}
2260
2261function getReuseIdInReuse(node: ts.ObjectLiteralExpression): string {
2262  let reuse: string = '';
2263  if (node.properties && node.properties.length) {
2264    node.properties.forEach((item: ts.ObjectLiteralElementLike) => {
2265      if (ts.isPropertyAssignment(item) && item.name && ts.isIdentifier(item.name) &&
2266        item.name.getText() === RECYCLE_REUSE_ID && item.initializer &&
2267        ts.isArrowFunction(item.initializer) && item.initializer.body &&
2268        ts.isStringLiteral(item.initializer.body)) {
2269        reuse = item.initializer.body.text;
2270      }
2271    });
2272  }
2273  return reuse;
2274}
2275
2276function processCustomBuilderProperty(node: ts.CallExpression, identifierNode: ts.Identifier,
2277  propertyName: string): ts.CallExpression {
2278  const newArguments: ts.Expression[] = [];
2279  node.arguments.forEach((argument: ts.Expression | ts.Identifier, index: number) => {
2280    if (ts.isConditionalExpression(argument)) {
2281      newArguments.push(processConditionalBuilder(argument, identifierNode, propertyName));
2282    } else if (isBuilderChangeNode(argument, identifierNode, propertyName)) {
2283      newArguments.push(parseBuilderNode(argument, propertyName));
2284    } else {
2285      newArguments.push(argument);
2286    }
2287  });
2288  node = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, newArguments);
2289  return node;
2290}
2291
2292function isBuilderChangeNode(argument: ts.Node, identifierNode: ts.Identifier, propertyName: string): boolean {
2293  return ts.isPropertyAccessExpression(argument) && argument.name && ts.isIdentifier(argument.name) &&
2294    storedFileInfo.builderLikeCollection.has(argument.name.getText()) ||
2295    ts.isCallExpression(argument) && argument.expression && argument.expression.name &&
2296    ts.isIdentifier(argument.expression.name) &&
2297    storedFileInfo.builderLikeCollection.has(argument.expression.name.getText()) || ts.isIdentifier(argument) &&
2298    argument.escapedText && storedFileInfo.builderLikeCollection.has(argument.escapedText.toString()) ||
2299    ts.isObjectLiteralExpression(argument) && (BIND_OBJECT_PROPERTY.get(identifierNode.escapedText.toString()) &&
2300    BIND_OBJECT_PROPERTY.get(identifierNode.escapedText.toString()).has(propertyName) ||
2301    BIND_OBJECT_PROPERTY.get(ALL_COMPONENTS).has(propertyName)) ||
2302    ts.isCallExpression(argument) && argument.expression && ts.isIdentifier(argument.expression) &&
2303    storedFileInfo.builderLikeCollection.has(argument.expression.escapedText.toString()) ||
2304    isWrappedBuilder(argument as ts.PropertyAccessExpression) || isWrappedBuilderCallExpression(argument as ts.CallExpression);
2305}
2306
2307export function isWrappedBuilder(node: ts.PropertyAccessExpression): boolean {
2308  if (projectConfig.minAPIVersion >= 11 && ts.isPropertyAccessExpression(node) &&
2309    node.name && ts.isIdentifier(node.name) && node.name.escapedText.toString() === WRAPBUILDER_BUILDERPROP &&
2310    globalProgram.checker.getTypeAtLocation(node.expression) &&
2311    globalProgram.checker.getTypeAtLocation(node.expression).symbol &&
2312    globalProgram.checker.getTypeAtLocation(node.expression).symbol.escapedName === WRAPPEDBUILDER_CLASS) {
2313    return true;
2314  }
2315  return false;
2316}
2317
2318function isWrappedBuilderCallExpression(node: ts.CallExpression): boolean {
2319  if (projectConfig.minAPIVersion >= 11 && ts.isCallExpression(node) && node.expression &&
2320    isWrappedBuilder(node.expression as ts.PropertyAccessExpression)) {
2321    return true;
2322  }
2323  return false;
2324}
2325
2326function parseBuilderNode(node: ts.Node, propertyName: string):
2327  ts.ObjectLiteralExpression | ts.CallExpression | ts.ArrowFunction {
2328  if (isWrappedBuilder(node as ts.PropertyAccessExpression) || isPropertyAccessExpressionNode(node)) {
2329    if (CUSTOM_BUILDER_PROPERTIES_WITHOUTKEY.has(propertyName)) {
2330      return processPropertyBuilderWithoutKey(node as ts.PropertyAccessExpression);
2331    } else {
2332      return processPropertyBuilder(node as ts.PropertyAccessExpression);
2333    }
2334  } else if (ts.isIdentifier(node) && storedFileInfo.builderLikeCollection.has(node.escapedText.toString())) {
2335    if (CUSTOM_BUILDER_PROPERTIES_WITHOUTKEY.has(propertyName)) {
2336      return processIdentifierBuilderWithoutKey(node);
2337    } else {
2338      return processIdentifierBuilder(node);
2339    }
2340  } else if (isWrappedBuilderCallExpression(node as ts.CallExpression) || ts.isCallExpression(node)) {
2341    if (CUSTOM_BUILDER_PROPERTIES_WITHOUTKEY.has(propertyName)) {
2342      return getParsedBuilderAttrArgumentWithParamsWithoutKey(node);
2343    } else {
2344      return getParsedBuilderAttrArgumentWithParams(node);
2345    }
2346  } else if (ts.isObjectLiteralExpression(node)) {
2347    return processObjectPropertyBuilder(node);
2348  }
2349  return undefined;
2350}
2351
2352export function processObjectPropertyBuilder(node: ts.ObjectLiteralExpression): ts.ObjectLiteralExpression {
2353  const newProperties: ts.PropertyAssignment[] = [];
2354  node.properties.forEach((property: ts.PropertyAssignment) => {
2355    if (property.name && ts.isIdentifier(property.name) &&
2356      [CUSTOM_DIALOG_CONTROLLER_BUILDER, HEADER, INDICATORBUILDER, FOOTER, START, END, PREVIEW, TITLE].includes(
2357        property.name.escapedText.toString()) && property.initializer) {
2358      if (isPropertyAccessExpressionNode(property.initializer) || ts.isIdentifier(property.initializer) &&
2359        storedFileInfo.builderLikeCollection.has(property.initializer.escapedText.toString())) {
2360        newProperties.push(ts.factory.updatePropertyAssignment(property, property.name,
2361          ts.factory.createCallExpression(
2362            ts.factory.createPropertyAccessExpression(
2363              property.initializer,
2364              ts.factory.createIdentifier(BUILDER_ATTR_BIND)
2365            ),
2366            undefined,
2367            [ts.factory.createThis()]
2368          )));
2369      } else if (isGlobalBuilderCallExpressionNode(property.initializer) ||
2370        isInnerBuilderCallExpressionNode(property.initializer)) {
2371        newProperties.push(transformBuilderCallExpression(property));
2372      } else if (ts.isObjectLiteralExpression(property.initializer)) {
2373        newProperties.push(ts.factory.updatePropertyAssignment(property, property.name,
2374          processObjectPropertyBuilder(property.initializer)));
2375      } else {
2376        newProperties.push(property);
2377      }
2378    } else {
2379      newProperties.push(property);
2380    }
2381  });
2382  return ts.factory.updateObjectLiteralExpression(node, newProperties);
2383}
2384
2385function transDoubleDollarInCustomBuilder(node: ts.CallExpression): ts.Expression[] {
2386  let name: string = '';
2387  if (node.expression && ts.isIdentifier(node.expression)) {
2388    name = node.expression.escapedText.toString();
2389  } else if (node.expression && ts.isPropertyAccessExpression(node.expression) &&
2390    node.expression.name && ts.isIdentifier(node.expression.name)) {
2391    name = node.expression.name.escapedText.toString();
2392  }
2393  if (node.arguments.length === 1 && ts.isObjectLiteralExpression(node.arguments[0])) {
2394    return [ts.factory.createCallExpression(
2395      ts.factory.createIdentifier(BUILDER_PARAM_PROXY),
2396      undefined,
2397      [
2398        ts.factory.createStringLiteral(name),
2399        traverseBuilderParams(node.arguments[0], storedFileInfo.processBuilder)
2400      ]
2401    )];
2402  } else {
2403    return node.arguments;
2404  }
2405}
2406
2407function transformBuilderCallExpression(property: ts.PropertyAssignment): ts.PropertyAssignment {
2408  const newArguments: ts.Expression[] = transDoubleDollarInCustomBuilder(property.initializer as ts.CallExpression);
2409  return ts.factory.updatePropertyAssignment(property, property.name,
2410    ts.factory.createCallExpression(
2411      ts.factory.createPropertyAccessExpression(
2412        property.initializer.expression,
2413        ts.factory.createIdentifier(BUILDER_ATTR_BIND)
2414      ),
2415      undefined,
2416      [ts.factory.createThis(), ...(newArguments || [])]
2417    ));
2418}
2419
2420function isInnerBuilderCallExpressionNode(node: ts.Node): boolean {
2421  return ts.isCallExpression(node) && node.expression && isPropertyAccessExpressionNode(node.expression);
2422}
2423
2424function isGlobalBuilderCallExpressionNode(node: ts.Node): boolean {
2425  return ts.isCallExpression(node) && node.expression && ts.isIdentifier(node.expression) &&
2426    CUSTOM_BUILDER_METHOD.has(node.expression.escapedText.toString());
2427}
2428
2429function isPropertyAccessExpressionNode(node: ts.Node): boolean {
2430  return ts.isPropertyAccessExpression(node) && node.expression &&
2431    node.expression.kind === ts.SyntaxKind.ThisKeyword && node.name && ts.isIdentifier(node.name) &&
2432    storedFileInfo.builderLikeCollection.has(node.name.escapedText.toString());
2433}
2434
2435function processBindPopupBuilder(node: ts.CallExpression): ts.CallExpression {
2436  const newArguments: ts.Expression[] = [];
2437  node.arguments.forEach((argument: ts.ObjectLiteralExpression, index: number) => {
2438    if (index === 1 && ts.isObjectLiteralExpression(argument)) {
2439      // @ts-ignore
2440      newArguments.push(processBindPopupBuilderProperty(argument));
2441    } else {
2442      newArguments.push(argument);
2443    }
2444  });
2445  node = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, newArguments);
2446  return node;
2447}
2448
2449function processDragStartBuilder(node: ts.CallExpression, propertyName: string): ts.CallExpression {
2450  const newStatements: ts.Statement[] = [];
2451  if (isNodeFunction(node)) {
2452    // @ts-ignore
2453    for (let i = 0; i < node.arguments[0].body.statements.length; i++) {
2454      // @ts-ignore
2455      const statement: ts.Statement = node.arguments[0].body.statements[i];
2456      newStatements.push(checkStatement(statement, propertyName));
2457    }
2458    node = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [ts.factory.updateArrowFunction(
2459      // @ts-ignore
2460      node.arguments[0], undefined, undefined, node.arguments[0].parameters, node.arguments[0].type,
2461      // @ts-ignore
2462      node.arguments[0].equalsGreaterThanToken, ts.factory.updateBlock(node.arguments[0].body, newStatements))]);
2463  }
2464  return node;
2465}
2466
2467function isNodeFunction(node: ts.CallExpression): boolean {
2468  return node.arguments && node.arguments.length && ts.isArrowFunction(node.arguments[0]) && node.arguments[0].body &&
2469    ts.isBlock(node.arguments[0].body);
2470}
2471
2472function checkStatement(statement: ts.Statement, propertyName: string): ts.Statement {
2473  if (ts.isReturnStatement(statement)) {
2474    if (ts.isObjectLiteralExpression(statement.expression)) {
2475      const newProperties: ts.ObjectLiteralElementLike[] = [];
2476      for (let j = 0; j < statement.expression.properties.length; j++) {
2477        let property: ts.ObjectLiteralElementLike = statement.expression.properties[j];
2478        property = checkProperty(property, propertyName);
2479        newProperties.push(property);
2480      }
2481      return ts.factory.createReturnStatement(ts.factory.createObjectLiteralExpression(newProperties));
2482    } else {
2483      let initializer: ts.Expression = statement.expression;
2484      initializer = processInitializer(initializer, propertyName);
2485      return ts.factory.updateReturnStatement(statement, initializer);
2486    }
2487  } else {
2488    return statement;
2489  }
2490}
2491
2492function checkProperty(property: ts.ObjectLiteralElementLike, propertyName: string): ts.ObjectLiteralElementLike {
2493  if (isPropertyFunction(property)) {
2494    let initializer: ts.Expression = property.initializer;
2495    initializer = processInitializer(initializer, propertyName);
2496    property = ts.factory.createPropertyAssignment(property.name, initializer);
2497  }
2498  return property;
2499}
2500
2501function processInitializer(initializer: ts.Expression, propertyName: string): ts.Expression {
2502  if (initializer && ts.isConditionalExpression(initializer)) {
2503    return processConditionalBuilder(initializer, ts.factory.createIdentifier(CUSTOM_COMPONENT_DEFAULT),
2504      propertyName);
2505  } else if (isBuilderChangeNode(initializer, ts.factory.createIdentifier(CUSTOM_COMPONENT_DEFAULT),
2506    propertyName)) {
2507    return parseBuilderNode(initializer, propertyName);
2508  }
2509  return initializer;
2510}
2511
2512function isPropertyFunction(property: ts.ObjectLiteralElementLike): boolean {
2513  return ts.isPropertyAssignment(property) && property.name && ts.isIdentifier(property.name) &&
2514    property.name.escapedText.toString() === BUILDER_ATTR_NAME;
2515}
2516
2517function processBindPopupBuilderProperty(node: ts.ObjectLiteralExpression): ts.ObjectLiteralExpression {
2518  const newProperties: ts.PropertyAssignment[] = [];
2519  node.properties.forEach((property: ts.PropertyAssignment, index: number) => {
2520    if (property.name && ts.isIdentifier(property.name) && property.initializer &&
2521      property.name.escapedText.toString() === CUSTOM_DIALOG_CONTROLLER_BUILDER) {
2522      let initializer: ts.Expression = property.initializer;
2523      initializer = processInitializer(initializer, BIND_POPUP);
2524      newProperties.push(ts.factory.updatePropertyAssignment(property, property.name, initializer));
2525    } else {
2526      newProperties.push(property);
2527    }
2528  });
2529  return ts.factory.updateObjectLiteralExpression(node, newProperties);
2530}
2531
2532function processConditionalBuilder(initializer: ts.ConditionalExpression, identifierNode: ts.Identifier,
2533  propertyName: string): ts.ConditionalExpression {
2534  let whenTrue: ts.Expression = initializer.whenTrue;
2535  let whenFalse: ts.Expression = initializer.whenFalse;
2536  if (isBuilderChangeNode(initializer.whenTrue, identifierNode, propertyName)) {
2537    whenTrue = parseBuilderNode(initializer.whenTrue, propertyName);
2538  }
2539  if (isBuilderChangeNode(initializer.whenFalse, identifierNode, propertyName)) {
2540    whenFalse = parseBuilderNode(initializer.whenFalse, propertyName);
2541  }
2542  return ts.factory.createConditionalExpression(
2543    initializer.condition,
2544    initializer.questionToken,
2545    whenTrue,
2546    initializer.colonToken,
2547    whenFalse
2548  );
2549}
2550
2551function processPropertyBuilder(node: ts.PropertyAccessExpression): ts.ObjectLiteralExpression {
2552  return ts.factory.createObjectLiteralExpression([
2553    ts.factory.createPropertyAssignment(
2554      ts.factory.createIdentifier(BUILDER_ATTR_NAME),
2555      ts.factory.createCallExpression(
2556        ts.factory.createPropertyAccessExpression(
2557          node,
2558          ts.factory.createIdentifier(BUILDER_ATTR_BIND)
2559        ),
2560        undefined,
2561        [ts.factory.createThis()]
2562      )
2563    )
2564  ]);
2565}
2566
2567function processPropertyBuilderWithoutKey(node: ts.PropertyAccessExpression): ts.CallExpression {
2568  return ts.factory.createCallExpression(
2569    ts.factory.createPropertyAccessExpression(
2570      node,
2571      ts.factory.createIdentifier(BUILDER_ATTR_BIND)
2572    ),
2573    undefined,
2574    [ts.factory.createThis()]
2575  );
2576}
2577
2578function processIdentifierBuilder(node: ts.Identifier): ts.ObjectLiteralExpression {
2579  return ts.factory.createObjectLiteralExpression([
2580    ts.factory.createPropertyAssignment(
2581      ts.factory.createIdentifier(BUILDER_ATTR_NAME),
2582      ts.factory.createCallExpression(
2583        ts.factory.createPropertyAccessExpression(node, ts.factory.createIdentifier(BUILDER_ATTR_BIND)),
2584        undefined, [ts.factory.createThis()]
2585      )
2586    )
2587  ]);
2588}
2589
2590function processIdentifierBuilderWithoutKey(node: ts.Identifier): ts.CallExpression {
2591  return ts.factory.createCallExpression(
2592    ts.factory.createPropertyAccessExpression(node, ts.factory.createIdentifier(BUILDER_ATTR_BIND)),
2593    undefined, [ts.factory.createThis()]
2594  );
2595}
2596
2597function getParsedBuilderAttrArgumentWithParams(node: ts.CallExpression):
2598  ts.ObjectLiteralExpression {
2599  const newArguments: ts.Expression[] = transDoubleDollarInCustomBuilder(node);
2600  return ts.factory.createObjectLiteralExpression([
2601    ts.factory.createPropertyAssignment(
2602      ts.factory.createIdentifier(BUILDER_ATTR_NAME),
2603      ts.factory.createArrowFunction(
2604        undefined,
2605        undefined,
2606        [],
2607        undefined,
2608        ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
2609        ts.factory.createBlock(
2610          [ts.factory.createExpressionStatement(ts.factory.createCallExpression(
2611            ts.factory.createPropertyAccessExpression(node.expression, ts.factory.createIdentifier(CALL)
2612            ), undefined, [ts.factory.createThis(), ...newArguments]))],
2613          true
2614        )
2615      )
2616    )
2617  ]);
2618}
2619
2620function getParsedBuilderAttrArgumentWithParamsWithoutKey(node: ts.CallExpression):
2621  ts.ArrowFunction {
2622  const newArguments: ts.Expression[] = transDoubleDollarInCustomBuilder(node);
2623  return ts.factory.createArrowFunction(
2624    undefined,
2625    undefined,
2626    [],
2627    undefined,
2628    ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
2629    ts.factory.createBlock(
2630      [ts.factory.createExpressionStatement(ts.factory.createCallExpression(
2631        ts.factory.createPropertyAccessExpression(node.expression, ts.factory.createIdentifier(CALL)
2632        ), undefined, [ts.factory.createThis(), ...newArguments]))],
2633      true
2634    )
2635  );
2636}
2637
2638function validatePropertyAccessExpressionWithCustomBuilder(node: ts.Node): boolean {
2639  return ts.isPropertyAccessExpression(node) && node.name &&
2640    ts.isIdentifier(node.name) && CUSTOM_BUILDER_PROPERTIES.has(node.name.escapedText.toString());
2641}
2642
2643function validateIdentifierWithCustomBuilder(node: ts.Node): boolean {
2644  return ts.isIdentifier(node) && CUSTOM_BUILDER_PROPERTIES.has(node.escapedText.toString());
2645}
2646
2647function createArrowFunctionForDollar($$varExp: ts.Expression): ts.ArrowFunction {
2648  return ts.factory.createArrowFunction(
2649    undefined, undefined,
2650    [ts.factory.createParameterDeclaration(
2651      undefined, undefined,
2652      ts.factory.createIdentifier($$_NEW_VALUE),
2653      undefined, undefined, undefined
2654    )],
2655    undefined,
2656    ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
2657    ts.factory.createBlock(
2658      [ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(
2659        $$varExp,
2660        ts.factory.createToken(ts.SyntaxKind.EqualsToken),
2661        ts.factory.createIdentifier($$_NEW_VALUE)
2662      ))],
2663      false
2664    )
2665  );
2666}
2667
2668function updateArgumentForExclamation(argument): ts.Expression {
2669  if (ts.isNonNullExpression(argument) && ts.isNonNullExpression(argument.expression)) {
2670    return argument.expression.expression;
2671  }
2672  return argument;
2673}
2674
2675function updateArgumentForDollar(argument): ts.Expression {
2676  if (ts.isElementAccessExpression(argument)) {
2677    return ts.factory.updateElementAccessExpression(
2678      argument, updateArgumentForDollar(argument.expression), argument.argumentExpression);
2679  } else if (ts.isIdentifier(argument)) {
2680    if (argument.getText() === $$_THIS) {
2681      return ts.factory.createThis();
2682    } else if (argument.getText().match(/^\$\$(.|\n)+/)) {
2683      return ts.factory.createIdentifier(argument.getText().replace(/\$\$/, ''));
2684    }
2685  } else if (ts.isPropertyAccessExpression(argument)) {
2686    return ts.factory.updatePropertyAccessExpression(
2687      argument, updateArgumentForDollar(argument.expression), argument.name);
2688  }
2689  return argument;
2690}
2691
2692function verifyComponentId(temp: any, node: ts.Identifier, propName: string,
2693  log: LogInfo[]): void {
2694  if (!newsupplement.isAcceleratePreview && propName === ATTRIBUTE_ID &&
2695    ts.isStringLiteral(temp.arguments[0])) {
2696    const id: string = temp.arguments[0].text;
2697    const posOfNode: ts.LineAndCharacter = transformLog.sourceFile
2698      .getLineAndCharacterOfPosition(getRealNodePos(node));
2699    const curFileName: string = transformLog.sourceFile.fileName.replace(/\.ts$/, '');
2700    const rPath: string = path.resolve(projectConfig.projectPath, curFileName)
2701      .replace(/\\+/g, '/');
2702    const rLine: number = posOfNode.line + 1;
2703    const rCol: number = posOfNode.character + 1;
2704    if (ID_ATTRS.has(id)) {
2705      const idInfo: Map<string, string | number> = ID_ATTRS.get(id);
2706      if (!(idInfo.get('path') === rPath &&
2707        idInfo.get('line') === rLine &&
2708        idInfo.get('col') === rCol)) {
2709        log.push({
2710          type: LogType.WARN,
2711          message: `The current component id "${id}" is duplicate with ` +
2712            `${idInfo.get('path')}:${idInfo.get('line')}:${idInfo.get('col')}.`,
2713          pos: node.pos
2714        });
2715      }
2716    } else {
2717      ID_ATTRS.set(id, new Map().set('path', rPath)
2718        .set('line', rLine)
2719        .set('col', rCol));
2720    }
2721  }
2722}
2723
2724class StyleResult {
2725  doubleDollar: boolean = false;
2726  doubleExclamation: boolean = false;
2727}
2728
2729function isDoubleBind(styleResult: StyleResult, isStylesAttr: boolean, identifierNode: ts.Identifier,
2730  propName: string, temp: any): boolean {
2731  if (isDoubleDollarToChange(isStylesAttr, identifierNode, propName, temp)) {
2732    styleResult.doubleDollar = true;
2733    return true;
2734  } else if (isDoubleExclamationToChange(isStylesAttr, identifierNode, propName, temp)) {
2735    styleResult.doubleExclamation = true;
2736    return true;
2737  }
2738  return false;
2739}
2740
2741function addComponentAttr(temp, node: ts.Identifier, lastStatement,
2742  statements: ts.Statement[], identifierNode: ts.Identifier, log: LogInfo[],
2743  isStylesAttr: boolean, immutableStatements: ts.Statement[], updateStatements: ts.Statement[],
2744  newImmutableStatements: ts.Statement[] = null, isRecycleComponent: boolean = false,
2745  isReuseComponentInV2: boolean = false, isStyleFunction: boolean = false): void {
2746  const styleResult: StyleResult = new StyleResult();
2747  const propName: string = node.getText();
2748  verifyComponentId(temp, node, propName, log);
2749  const extendType: ExtendType = {type: ''};
2750  if (propName === ATTRIBUTE_ANIMATION) {
2751    const animationNullNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(
2752      createFunction(ts.factory.createIdentifier(GLOBAL_CONTEXT), node,
2753        // @ts-ignore
2754        [ts.factory.createNull()]));
2755    if (!lastStatement.statement) {
2756      if (!(temp.arguments.length === 1 &&
2757        temp.arguments[0].kind === ts.SyntaxKind.NullKeyword)) {
2758        statements.push(animationNullNode);
2759      }
2760    } else {
2761      statements.push(lastStatement.statement, animationNullNode);
2762    }
2763    lastStatement.statement = ts.factory.createExpressionStatement(createFunction(
2764      ts.factory.createIdentifier(GLOBAL_CONTEXT), node, temp.arguments));
2765    lastStatement.kind = false;
2766    lastStatement.hasAnimationAttr = true;
2767  } else if (GESTURE_ATTRS.has(propName)) {
2768    parseGesture(temp, propName, statements, log, updateStatements);
2769    lastStatement.kind = true;
2770  } else if (isExtendFunctionNode(identifierNode, propName, extendType)) {
2771    if (newsupplement.isAcceleratePreview) {
2772      log.push({
2773        type: LogType.ERROR,
2774        message: `Doesn't support '@Extend' function now.`,
2775        pos: temp.getStart(),
2776        code: '10906205'
2777      });
2778    }
2779    let functionName: string = '';
2780    if (extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR) {
2781      functionName = `__${identifierNode.escapedText.toString()}__${propName}`;
2782    } else {
2783      functionName = propName;
2784    }
2785    const extendNode: ts.Statement = ts.factory.createExpressionStatement(
2786      ts.factory.createCallExpression(ts.factory.createIdentifier(functionName), undefined,
2787        extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR ?
2788          temp.arguments :
2789          [
2790            ...temp.arguments, ts.factory.createIdentifier(ELMTID),
2791            ts.factory.createIdentifier(ISINITIALRENDER),
2792            ts.factory.createThis()
2793          ]
2794      ));
2795    statements.push(extendNode);
2796    updateStatements.push(extendNode);
2797    lastStatement.kind = true;
2798  } else if (propName === ATTRIBUTE_STATESTYLES) {
2799    if (temp.arguments.length === 1 && ts.isObjectLiteralExpression(temp.arguments[0])) {
2800      statements.push(createViewStackProcessor(temp, true));
2801      if (isRecycleComponent) {
2802        updateStatements.push(createViewStackProcessor(temp, true));
2803      }
2804      traverseStateStylesAttr(temp, statements, identifierNode, log, updateStatements,
2805        newImmutableStatements, isRecycleComponent);
2806      lastStatement.kind = true;
2807    } else {
2808      validateStateStyleSyntax(temp, log);
2809    }
2810  } else if (GLOBAL_STYLE_FUNCTION.has(propName) || INNER_STYLE_FUNCTION.has(propName)) {
2811    const styleBlock: ts.Block =
2812        INNER_STYLE_FUNCTION.get(propName) || GLOBAL_STYLE_FUNCTION.get(propName);
2813    if (styleBlock.statements.length > 0) {
2814      bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode,
2815        statements, log, false, true, newImmutableStatements);
2816      if (isRecycleComponent) {
2817        bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode,
2818          updateStatements, log, false, true, newImmutableStatements, true);
2819      }
2820    }
2821    lastStatement.kind = true;
2822  } else if (isDoubleBind(styleResult, isStylesAttr, identifierNode, propName, temp)) {
2823    const argumentsArr: ts.Expression[] = [];
2824    styleResult.doubleDollar ? classifyArgumentsNum(temp.arguments, argumentsArr, propName, identifierNode) :
2825      classifyArgumentsNumV2(temp.arguments, argumentsArr, propName, identifierNode);
2826    const doubleDollarNode: ts.Statement = ts.factory.createExpressionStatement(
2827      createFunction(identifierNode, node, argumentsArr));
2828    statements.push(doubleDollarNode);
2829    updateStatements.push(doubleDollarNode);
2830    lastStatement.kind = true;
2831  } else {
2832    temp = loopEtscomponent(temp, isStylesAttr);
2833    if (propName !== RECYCLE_REUSE_ID && propName !== REUSE_ATTRIBUTE) {
2834      let isAttributeModifier: boolean = false;
2835      if ([ATTRIBUTE_ATTRIBUTE_MODIFIER, ATTRIBUTE_CONTENT_MODIFIER,
2836        ATTRIBUTE_MENUITEM_CONTENT_MODIFIER].includes(propName)) {
2837        isAttributeModifier = true;
2838      }
2839      const attrStatement: ts.Statement = ts.factory.createExpressionStatement(
2840        createFunction(identifierNode, node, temp.arguments, isAttributeModifier));
2841      statements.push(attrStatement);
2842      if ((isRecycleComponent || isReuseComponentInV2) && (!isStylesAttr || isStyleFunction) &&
2843        !isGestureType(identifierNode) && filterRegularAttrNode(temp.arguments)) {
2844        immutableStatements.push(attrStatement);
2845      } else {
2846        updateStatements.push(attrStatement);
2847      }
2848    }
2849    lastStatement.kind = true;
2850  }
2851}
2852
2853function isGestureType(node: ts.Identifier): boolean {
2854  return GESTURE_TYPE_NAMES.has(node.escapedText.toString());
2855}
2856
2857function filterRegularAttrNode(argumentsNode: ts.NodeArray<ts.Expression>): boolean {
2858  return argumentsNode.every((argument: ts.Expression) => {
2859    return isRegularAttrNode(argument);
2860  });
2861}
2862
2863type AttrResult = { isRegularNode: boolean };
2864function isRegularAttrNode(node: ts.Expression): boolean {
2865  if (ts.isObjectLiteralExpression(node)) {
2866    return node.properties.every((propNode: ts.PropertyAssignment) => {
2867      if (propNode.initializer) {
2868        return isRegularAttrNode(propNode.initializer);
2869      }
2870      return false;
2871    });
2872  }
2873  if (ts.isArrayLiteralExpression(node)) {
2874    return node.elements.every((child: ts.Expression) => {
2875      return isRegularAttrNode(child);
2876    });
2877  }
2878  // literal e.g. 'hello', 1, true, false, () => {}
2879  if (isLiteralNode(node)) {
2880    return true;
2881  }
2882  // enum e.g. Color.Red
2883  if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) &&
2884    ts.isIdentifier(node.name)) {
2885    if (enumCollection.has(node.expression.escapedText.toString())) {
2886      return true;
2887    }
2888    if (globalProgram.checker) {
2889      const type: ts.Type = globalProgram.checker.getTypeAtLocation(node);
2890      /* Enum */
2891      if (type.flags & (32 | 1024)) {
2892        return true;
2893      }
2894    }
2895    return false;
2896  }
2897  // regular variable, e.g. this.regularValue
2898  const result: AttrResult = { isRegularNode: false };
2899  if (ts.isPropertyAccessExpression(node)) {
2900    traversePropNode(node, result);
2901  }
2902  return result.isRegularNode || false;
2903}
2904
2905function isLiteralNode(node: ts.Expression): boolean {
2906  return ts.isStringLiteral(node) || ts.isNumericLiteral(node) || ts.isArrowFunction(node) ||
2907    [ts.SyntaxKind.TrueKeyword, ts.SyntaxKind.FalseKeyword].includes(node.kind);
2908}
2909
2910function isSimpleType(node: ts.PropertyAccessExpression): boolean {
2911  const symbol: ts.Symbol = getSymbolIfAliased(node);
2912  const simpleTypeCollection: ts.SyntaxKind[] = [ts.SyntaxKind.StringKeyword, ts.SyntaxKind.NumberKeyword,
2913    ts.SyntaxKind.BooleanKeyword];
2914  if (symbol && symbol.declarations && symbol.declarations.length === 1 && ts.isPropertyDeclaration(symbol.declarations[0]) &&
2915    symbol.declarations[0].type && symbol.declarations[0].type.kind && simpleTypeCollection.includes(symbol.declarations[0].type.kind)) {
2916    return true;
2917  }
2918  return false;
2919}
2920
2921function traversePropNode(node: ts.PropertyAccessExpression, result: AttrResult): void {
2922  const structInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(componentCollection.currentClassName);
2923  if (structInfo.isComponentV2 && node.expression.kind === ts.SyntaxKind.ThisKeyword && ts.isIdentifier(node.name) &&
2924    structInfo.regularSet.has(node.name.escapedText.toString()) && isSimpleType(node)) {
2925    result.isRegularNode = true;
2926    return;
2927  }
2928  if (!structInfo.isComponentV2 && node.expression.kind === ts.SyntaxKind.ThisKeyword && ts.isIdentifier(node.name) &&
2929    regularCollection.get(componentCollection.currentClassName).has(node.name.escapedText.toString())) {
2930    result.isRegularNode = true;
2931    return;
2932  }
2933  if (ts.isPropertyAccessExpression(node.expression)) {
2934    traversePropNode(node.expression, result);
2935  }
2936}
2937
2938function isDoubleDollarToChange(isStylesAttr: boolean, identifierNode: ts.Identifier,
2939  propName: string, temp): boolean {
2940  return !isStylesAttr &&
2941    PROPERTIES_ADD_DOUBLE_DOLLAR.has(identifierNode.escapedText.toString()) &&
2942    PROPERTIES_ADD_DOUBLE_DOLLAR.get(identifierNode.escapedText.toString()).has(propName) ||
2943    STYLE_ADD_DOUBLE_DOLLAR.has(propName) && temp.arguments.length && temp.arguments[0] ?
2944    temp.arguments[0].getText().match(/^(?!\$\$\.)\$\$(.|\n)+/) !== null :
2945    false;
2946}
2947
2948function isDoubleExclamationToChange(isStylesAttr: boolean, identifierNode: ts.Identifier, propName: string, temp: ts.CallExpression): boolean {
2949  return !isStylesAttr &&
2950    (STYLE_ADD_DOUBLE_EXCLAMATION.has(propName) && temp.arguments.length && temp.arguments[0] ||
2951    PROPERTIES_ADD_DOUBLE_EXCLAMATION.has(identifierNode.escapedText.toString()) &&
2952    PROPERTIES_ADD_DOUBLE_EXCLAMATION.get(identifierNode.escapedText.toString()).has(propName)) &&
2953    ts.isNonNullExpression(temp.arguments[0]) && ts.isNonNullExpression(temp.arguments[0].expression) &&
2954    !ts.isNonNullExpression(temp.arguments[0].expression.expression);
2955}
2956
2957function isHaveDoubleDollar(param: ts.PropertyAssignment, name: string): boolean {
2958  return ts.isPropertyAssignment(param) && param.name && ts.isIdentifier(param.name) &&
2959    PROPERTIES_ADD_DOUBLE_DOLLAR.get(name).has(param.name.getText()) && param.initializer &&
2960    param.initializer.getText().match(/^(?!\$\$\.)\$\$(.|\n)+/) !== null;
2961}
2962
2963function isHaveDoubleExclamation(param: ts.PropertyAssignment, name: string): boolean {
2964  return ts.isPropertyAssignment(param) && param.name && ts.isIdentifier(param.name) &&
2965    PROPERTIES_ADD_DOUBLE_EXCLAMATION.has(name) && PROPERTIES_ADD_DOUBLE_EXCLAMATION.get(name).has(param.name.getText()) &&
2966    param.initializer && ts.isNonNullExpression(param.initializer) && ts.isNonNullExpression(param.initializer.expression) &&
2967    !ts.isNonNullExpression(param.initializer.expression.expression);
2968}
2969
2970function loopEtscomponent(node: any, isStylesAttr: boolean): ts.Node {
2971  node.arguments.forEach((item: ts.Node, index: number) => {
2972    if (ts.isEtsComponentExpression(item)) {
2973      node.arguments[index] = ts.factory.createCallExpression(
2974        item.expression, undefined, item.arguments);
2975    } else if ((ts.isCallExpression(item) || ts.isNewExpression(item)) &&
2976      !newsupplement.isAcceleratePreview) {
2977      node.arguments[index] = ts.visitEachChild(item,
2978        changeEtsComponentKind, contextGlobal);
2979    }
2980  });
2981  return node;
2982}
2983
2984function changeEtsComponentKind(node: ts.Node): ts.Node {
2985  if (ts.isEtsComponentExpression(node)) {
2986    node.kind = 204;
2987    return node;
2988  }
2989  return ts.visitEachChild(node, changeEtsComponentKind, contextGlobal);
2990}
2991
2992function classifyArgumentsNum(args, argumentsArr: ts.Expression[], propName: string,
2993  identifierNode: ts.Identifier): void {
2994  if (STYLE_ADD_DOUBLE_DOLLAR.has(propName) && args.length >= 2) {
2995    const varExp: ts.Expression = updateArgumentForDollar(args[0]);
2996    argumentsArr.push(generateObjectForDollar(varExp), ...args.slice(1));
2997  } else if (STYLE_ADD_DOUBLE_EXCLAMATION.has(propName) && args.length >= 2) {
2998    const varExp: ts.Expression = updateArgumentForExclamation(args[0]);
2999    argumentsArr.push(generateObjectForExclamation(varExp), ...args.slice(1));
3000  } else if (PROPERTIES_ADD_DOUBLE_DOLLAR.has(identifierNode.escapedText.toString()) && args.length === 1 &&
3001    PROPERTIES_ADD_DOUBLE_DOLLAR.get(identifierNode.escapedText.toString()).has(propName) ||
3002    STYLE_ADD_DOUBLE_DOLLAR.has(propName) && args.length === 1) {
3003    const varExp: ts.Expression = updateArgumentForDollar(args[0]);
3004    argumentsArr.push(varExp, createArrowFunctionForDollar(varExp));
3005  }
3006}
3007
3008function classifyArgumentsNumV2(args: any, argumentsArr: ts.Expression[], propName: string,
3009  identifierNode: ts.Identifier): void {
3010  const componentName: string = identifierNode.escapedText.toString();
3011  if (STYLE_ADD_DOUBLE_EXCLAMATION.has(propName) && args.length ||
3012  PROPERTIES_ADD_DOUBLE_EXCLAMATION.has(componentName) && args.length === 1 &&
3013  PROPERTIES_ADD_DOUBLE_EXCLAMATION.get(componentName).has(propName)) {
3014    const varExp: ts.Expression = updateArgumentForExclamation(args[0]);
3015    argumentsArr.push(generateObjectForExclamation(varExp), ...args.slice(1));
3016  }
3017}
3018
3019function generateObjectForExclamation(varExp: ts.Expression): ts.ObjectLiteralExpression {
3020  return ts.factory.createObjectLiteralExpression([
3021      ts.factory.createPropertyAssignment(
3022        ts.factory.createIdentifier($$_VALUE),
3023        varExp),
3024      ts.factory.createPropertyAssignment(
3025        ts.factory.createIdentifier($_VALUE),
3026        ts.factory.createArrowFunction(
3027          undefined, undefined,
3028          [ts.factory.createParameterDeclaration(
3029            undefined, undefined,
3030            ts.factory.createIdentifier($$_NEW_VALUE),
3031            undefined, undefined, undefined
3032          )],
3033          undefined,
3034          ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
3035          ts.factory.createBlock(
3036            [ts.factory.createExpressionStatement(ts.factory.createBinaryExpression(
3037              varExp,
3038              ts.factory.createToken(ts.SyntaxKind.EqualsToken),
3039              ts.factory.createIdentifier($$_NEW_VALUE)
3040            ))], false)
3041        ))], false);
3042}
3043
3044function generateObjectForDollar(varExp: ts.Expression): ts.ObjectLiteralExpression {
3045  return ts.factory.createObjectLiteralExpression(
3046    [
3047      ts.factory.createPropertyAssignment(
3048        ts.factory.createIdentifier($$_VALUE),
3049        varExp
3050      ),
3051      ts.factory.createPropertyAssignment(
3052        ts.factory.createIdentifier($$_CHANGE_EVENT),
3053        createArrowFunctionForDollar(varExp)
3054      )
3055    ],
3056    false
3057  );
3058}
3059
3060function generateFunctionPropertyAssignmentForExclamation(name: string, varExp: ts.Expression): ts.PropertyAssignment {
3061  return ts.factory.createPropertyAssignment(
3062    ts.factory.createIdentifier('$' + name),
3063    createArrowFunctionForDollar(varExp)
3064  );
3065}
3066
3067function createViewStackProcessor(item, endViewStack: boolean): ts.ExpressionStatement {
3068  const argument: ts.StringLiteral[] = [];
3069  if (!endViewStack && item.name) {
3070    argument.push(ts.factory.createStringLiteral(item.name.getText()));
3071  }
3072  return ts.factory.createExpressionStatement(ts.factory.createCallExpression(
3073    ts.factory.createPropertyAccessExpression(
3074      ts.factory.createIdentifier(VIEW_STACK_PROCESSOR),
3075      ts.factory.createIdentifier(VISUAL_STATE)
3076    ),
3077    undefined,
3078    argument
3079  ));
3080}
3081
3082function traverseStateStylesAttr(temp, statements: ts.Statement[],
3083  identifierNode: ts.Identifier, log: LogInfo[], updateStatements: ts.Statement[],
3084  newImmutableStatements: ts.Statement[] = null, isRecycleComponent: boolean = false): void {
3085  temp.arguments[0].properties.reverse().forEach((item: ts.PropertyAssignment) => {
3086    if (ts.isPropertyAccessExpression(item.initializer) &&
3087      item.initializer.expression.getText() === THIS &&
3088      INNER_STYLE_FUNCTION.get(item.initializer.name.getText())) {
3089      const name: string = item.initializer.name.getText();
3090      bindComponentAttr(INNER_STYLE_FUNCTION.get(name).statements[0] as ts.ExpressionStatement,
3091        identifierNode, statements, log, false, true, newImmutableStatements);
3092      if (isRecycleComponent) {
3093        bindComponentAttr(INNER_STYLE_FUNCTION.get(name).statements[0] as ts.ExpressionStatement,
3094          identifierNode, updateStatements, log, false, true, newImmutableStatements);
3095      }
3096    } else if (ts.isIdentifier(item.initializer) &&
3097      GLOBAL_STYLE_FUNCTION.get(item.initializer.getText())) {
3098      const name: string = item.initializer.getText();
3099      bindComponentAttr(GLOBAL_STYLE_FUNCTION.get(name).statements[0] as ts.ExpressionStatement,
3100        identifierNode, statements, log, false, true, newImmutableStatements);
3101      if (isRecycleComponent) {
3102        bindComponentAttr(GLOBAL_STYLE_FUNCTION.get(name).statements[0] as ts.ExpressionStatement,
3103          identifierNode, updateStatements, log, false, true, newImmutableStatements);
3104      }
3105    } else if (ts.isObjectLiteralExpression(item.initializer) &&
3106      item.initializer.properties.length === 1 &&
3107      ts.isPropertyAssignment(item.initializer.properties[0])) {
3108      bindComponentAttr(ts.factory.createExpressionStatement(
3109        item.initializer.properties[0].initializer), identifierNode, statements, log, false, true,
3110      newImmutableStatements);
3111      if (isRecycleComponent) {
3112        bindComponentAttr(ts.factory.createExpressionStatement(
3113          item.initializer.properties[0].initializer), identifierNode, updateStatements, log, false, true,
3114        newImmutableStatements);
3115      }
3116    } else {
3117      if (!(ts.isObjectLiteralExpression(item.initializer) && item.initializer.properties.length === 0)) {
3118        validateStateStyleSyntax(temp, log);
3119      }
3120    }
3121    if (item.name) {
3122      const viewNode: ts.Statement = createViewStackProcessor(item, false);
3123      statements.push(viewNode);
3124      if (isRecycleComponent) {
3125        updateStatements.push(viewNode);
3126      }
3127    }
3128  });
3129}
3130
3131interface ExtendType {
3132  type: string
3133}
3134
3135function isExtendFunctionNode(identifierNode: ts.Identifier, propName: string,
3136  extendType: ExtendType): boolean {
3137  const componentName: string = identifierNode.escapedText.toString();
3138  if (EXTEND_ATTRIBUTE.has(componentName) && [...EXTEND_ATTRIBUTE.get(componentName)].includes(propName)) {
3139    extendType.type = CHECK_COMPONENT_EXTEND_DECORATOR;
3140    return true;
3141  }
3142  const animatableExtendAttribute: Map<string, Set<string>> =
3143    storedFileInfo.getCurrentArkTsFile().animatableExtendAttribute;
3144  if (animatableExtendAttribute.has(componentName) &&
3145    [...animatableExtendAttribute.get(componentName)].includes(propName)) {
3146    extendType.type = CHECK_COMPONENT_ANIMATABLE_EXTEND_DECORATOR;
3147    return true;
3148  }
3149  return false;
3150}
3151
3152const gestureMap: Map<string, string> = new Map([
3153  [PRIORITY_GESTURE_ATTRIBUTE, GESTURE_ENUM_VALUE_HIGH],
3154  [PARALLEL_GESTURE_ATTRIBUTE, GESTURE_ENUM_VALUE_PARALLEL],
3155  [GESTURE_ATTRIBUTE, GESTURE_ENUM_VALUE_LOW]
3156]);
3157
3158function parseGesture(node: ts.CallExpression, propName: string, statements: ts.Statement[],
3159  log: LogInfo[], updateStatements: ts.Statement[]): void {
3160  const popNode: ts.Statement = ts.factory.createExpressionStatement(
3161    createFunction(ts.factory.createIdentifier(COMPONENT_GESTURE),
3162      ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null));
3163  statements.push(popNode);
3164  updateStatements.push(popNode);
3165  parseGestureInterface(node, statements, log, updateStatements);
3166  const argumentArr: ts.NodeArray<ts.PropertyAccessExpression> = ts.factory.createNodeArray(
3167    [ts.factory.createPropertyAccessExpression(
3168      ts.factory.createIdentifier(GESTURE_ENUM_KEY),
3169      ts.factory.createIdentifier(gestureMap.get(propName)))
3170    ]
3171  );
3172  if (node.arguments && node.arguments.length > 1 &&
3173    ts.isPropertyAccessExpression(node.arguments[1])) {
3174    // @ts-ignore
3175    argumentArr.push(node.arguments[1]);
3176  }
3177  const createNode: ts.Statement = ts.factory.createExpressionStatement(
3178    createFunction(ts.factory.createIdentifier(COMPONENT_GESTURE),
3179      ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), argumentArr));
3180  statements.push(createNode);
3181  updateStatements.push(createNode);
3182}
3183
3184function processGestureType(node: ts.CallExpression, statements: ts.Statement[], log: LogInfo[],
3185  updateStatements: ts.Statement[], reverse: boolean = false): void {
3186  const newStatements: ts.Statement[] = [];
3187  const newNode: ts.ExpressionStatement = ts.factory.createExpressionStatement(node);
3188  let temp = node.expression;
3189  while (temp && !ts.isIdentifier(temp) && temp.expression) {
3190    temp = temp.expression;
3191  }
3192  if (temp && temp.parent && ts.isCallExpression(temp.parent) && ts.isIdentifier(temp) &&
3193    GESTURE_TYPE_NAMES.has(temp.escapedText.toString())) {
3194    newStatements.push(ts.factory.createExpressionStatement(
3195      createFunction(temp, ts.factory.createIdentifier(COMPONENT_POP_FUNCTION), null)));
3196    if (temp.escapedText.toString() === COMPONENT_GESTURE_GROUP) {
3197      const gestureStatements: ts.Statement[] = [];
3198      parseGestureInterface(temp.parent, gestureStatements, log, [], true);
3199      newStatements.push(...gestureStatements.reverse());
3200      bindComponentAttr(newNode, temp, newStatements, log, false);
3201      let argumentArr: ts.NodeArray<ts.Expression> = null;
3202      if (temp.parent.arguments && temp.parent.arguments.length) {
3203        // @ts-ignore
3204        argumentArr = ts.factory.createNodeArray([temp.parent.arguments[0]]);
3205      }
3206      newStatements.push(ts.factory.createExpressionStatement(
3207        createFunction(temp, ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), argumentArr)));
3208    } else {
3209      bindComponentAttr(newNode, temp, newStatements, log, false);
3210      newStatements.push(ts.factory.createExpressionStatement(
3211        createFunction(temp, ts.factory.createIdentifier(COMPONENT_CREATE_FUNCTION), temp.parent.arguments)));
3212    }
3213  }
3214  if (newStatements.length) {
3215    reverse ? statements.push(...newStatements.reverse()) : statements.push(...newStatements);
3216    reverse ? updateStatements.push(...newStatements.reverse()) : updateStatements.push(...newStatements);
3217  }
3218}
3219
3220function parseGestureInterface(node: ts.CallExpression, statements: ts.Statement[], log: LogInfo[],
3221  updateStatements: ts.Statement[], reverse: boolean = false): void {
3222  if (node.arguments && node.arguments.length) {
3223    node.arguments.forEach((item: ts.Node) => {
3224      if (ts.isCallExpression(item)) {
3225        processGestureType(item, statements, log, updateStatements, reverse);
3226      }
3227    });
3228  }
3229}
3230
3231export function getName(node: ts.ExpressionStatement | ts.Expression): string {
3232  // @ts-ignore
3233  let temp = node.expression;
3234  let name: string;
3235  while (temp) {
3236    if (ts.isIdentifier(temp) && temp.parent && (ts.isCallExpression(temp.parent) ||
3237      ts.isEtsComponentExpression(temp.parent))) {
3238      name = temp.escapedText.toString();
3239      break;
3240    } else if (ts.isPropertyAccessExpression(temp) && temp.name && ts.isIdentifier(temp.name) &&
3241      isCustomAttributes(temp)) {
3242      name = temp.name.escapedText.toString();
3243      break;
3244    }
3245    temp = temp.expression;
3246  }
3247  return name;
3248}
3249
3250function isCustomAttributes(temp: ts.PropertyAccessExpression): boolean {
3251  if (temp.expression && temp.expression.getText() === THIS) {
3252    return true;
3253  } else if (temp.expression && ts.isIdentifier(temp.expression) && temp.expression.getText() === $$ &&
3254    builderTypeParameter.params.includes(temp.expression.getText())) {
3255    return true;
3256  } else {
3257    return !BUILDIN_STYLE_NAMES.has(temp.name.escapedText.toString());
3258  }
3259}
3260
3261export function isAttributeNode(node: ts.ExpressionStatement): boolean {
3262  let temp: any = node.expression;
3263  let name: string;
3264  while (temp) {
3265    if (ts.isCallExpression(temp) && temp.expression && ts.isIdentifier(temp.expression)) {
3266      name = temp.expression.escapedText.toString();
3267      break;
3268    }
3269    temp = temp.expression;
3270  }
3271  return BUILDIN_STYLE_NAMES.has(name);
3272}
3273
3274enum ComponentType {
3275  innerComponent,
3276  customComponent,
3277  forEachComponent,
3278  customBuilderMethod,
3279  builderParamMethod,
3280  function,
3281  builderTypeFunction,
3282  repeatComponent
3283}
3284
3285function isEtsComponent(node: ts.ExpressionStatement): boolean {
3286  let isEtsComponent: boolean = false;
3287  let temp: any = node.expression;
3288  while (temp) {
3289    if (ts.isEtsComponentExpression(temp)) {
3290      isEtsComponent = true;
3291    }
3292    temp = temp.expression;
3293  }
3294  return isEtsComponent;
3295}
3296
3297function isSomeName(forEachParameters: ts.NodeArray<ts.ParameterDeclaration>, name: string): boolean {
3298  return Array.isArray(forEachParameters) &&
3299    forEachParameters.some((item) => {
3300      return ts.isIdentifier(item.name) ? item.name.escapedText.toString() === name : false;
3301    });
3302}
3303
3304function isParamFunction(node: ts.ExpressionStatement): boolean {
3305  return node.expression && ts.isCallExpression(node.expression) &&
3306    node.expression.expression && ts.isIdentifier(node.expression.expression);
3307}
3308
3309function getComponentType(node: ts.ExpressionStatement, log: LogInfo[], name: string,
3310  parent: string, forEachParameters: ts.NodeArray<ts.ParameterDeclaration> = undefined): ComponentType {
3311  let isBuilderName: boolean = true;
3312  let isLocalBuilderName: boolean = true;
3313  if (forEachParameters && isSomeName(forEachParameters, name) && isParamFunction(node)) {
3314    isBuilderName = false;
3315    isLocalBuilderName = false;
3316  }
3317  if (isEtsComponent(node)) {
3318    if (componentCollection.customComponents.has(name)) {
3319      isCustomComponentAttributes(node, log);
3320      return ComponentType.customComponent;
3321    } else {
3322      return ComponentType.innerComponent;
3323    }
3324  } else if (!isPartMethod(node) && componentCollection.customComponents.has(name)) {
3325    isCustomComponentAttributes(node, log);
3326    return ComponentType.customComponent;
3327  } else if (name === COMPONENT_FOREACH || name === COMPONENT_LAZYFOREACH) {
3328    return ComponentType.forEachComponent;
3329  } else if (name === COMPONENT_REPEAT) {
3330    return ComponentType.repeatComponent;
3331  } else if (isLocalBuilderOrBuilderMethod(CUSTOM_BUILDER_METHOD, isBuilderName, name) || isWrappedBuilderExpression(node) ||
3332    isLocalBuilderOrBuilderMethod(INNER_CUSTOM_LOCALBUILDER_METHOD, isLocalBuilderName, name)) {
3333    return ComponentType.customBuilderMethod;
3334  } else if (builderParamObjectCollection.get(componentCollection.currentClassName) &&
3335    builderParamObjectCollection.get(componentCollection.currentClassName).has(name)) {
3336    return ComponentType.builderParamMethod;
3337  } else if (!partialUpdateConfig.builderCheck && builderTypeParameter.params.includes(name) &&
3338    judgeBuilderType(node)) {
3339    return ComponentType.builderTypeFunction;
3340  } else if ((['XComponent'].includes(parent) || CUSTOM_BUILDER_METHOD.has(parent)) &&
3341    ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression)) {
3342    return ComponentType.function;
3343  } else if (!isAttributeNode(node)) {
3344    log.push({
3345      type: LogType.ERROR,
3346      message: `'${node.getText()}' does not meet UI component syntax.`,
3347      pos: node.getStart(),
3348      code: '10905204'
3349    });
3350  }
3351  return null;
3352}
3353
3354function isCustomComponentAttributes(node: ts.ExpressionStatement, log: LogInfo[]): void {
3355  if (node.expression && ts.isCallExpression(node.expression) && ts.isPropertyAccessExpression(node.expression.expression) &&
3356    ts.isIdentifier(node.expression.expression.name) && !COMMON_ATTRS.has(node.expression.expression.name.escapedText.toString())) {
3357      log.push({
3358        type: LogType.ERROR,
3359        message: `'${node.getText()}' does not meet UI component syntax.`,
3360        pos: node.getStart()
3361      });
3362  }
3363}
3364
3365function isLocalBuilderOrBuilderMethod(LocalBuilderOrBuilderSet: Set<string>,
3366  isLocalBuilderOrBuilderName: boolean, name: string): boolean {
3367  return LocalBuilderOrBuilderSet.has(name) && isLocalBuilderOrBuilderName;
3368}
3369
3370function isPartMethod(node: ts.ExpressionStatement): boolean {
3371  if (ts.isCallExpression(node.expression) && ts.isPropertyAccessExpression(node.expression.expression) &&
3372    node.expression.expression.expression && node.expression.expression.expression.kind &&
3373    node.expression.expression.expression.kind === ts.SyntaxKind.ThisKeyword) {
3374    return true;
3375  } else {
3376    return false;
3377  }
3378}
3379
3380function isWrappedBuilderExpression(node: ts.ExpressionStatement): boolean {
3381  if (projectConfig.minAPIVersion >= 11 && node.expression &&
3382    isWrappedBuilderCallExpression(node.expression as ts.CallExpression)) {
3383    return true;
3384  }
3385  return false;
3386}
3387
3388function judgeBuilderType(node: ts.ExpressionStatement): boolean {
3389  let checker: ts.TypeChecker;
3390  if (globalProgram.program) {
3391    checker = globalProgram.program.getTypeChecker();
3392  } else if (globalProgram.watchProgram) {
3393    checker = globalProgram.watchProgram.getCurrentProgram().getProgram().getTypeChecker();
3394  }
3395  if (node.expression && node.expression.expression && checker) {
3396    const type: ts.Type = checker.getTypeAtLocation(node.expression.expression);
3397    if (type && type.aliasSymbol && type.aliasSymbol.escapedName === BUILDER_TYPE) {
3398      return true;
3399    }
3400  }
3401  return false;
3402}
3403
3404export function validateStateStyleSyntax(temp, log: LogInfo[]): void {
3405  log.push({
3406    type: LogType.ERROR,
3407    message: `'.stateStyles' doesn't conform standard.`,
3408    pos: temp.getStart(),
3409    code: '10905203'
3410  });
3411}
3412
3413function getEtsComponentExpression(node:ts.ExpressionStatement): ts.EtsComponentExpression {
3414  let current = node.expression;
3415  while (current) {
3416    if (ts.isEtsComponentExpression(current)) {
3417      return current;
3418    }
3419    current = current.expression;
3420  }
3421  return null;
3422}
3423
3424function checkEtsAndIdInIf(node:ts.ExpressionStatement, parent: string): [ts.EtsComponentExpression, ts.Expression] {
3425  let current = node.expression;
3426  let idName: ts.Expression;
3427  while (current) {
3428    if (ts.isEtsComponentExpression(current)) {
3429      break;
3430    }
3431    if (!idName && parent === COMPONENT_IF && ts.isPropertyAccessExpression(current) && current.name &&
3432      ts.isIdentifier(current.name) && current.name.escapedText.toString() === ATTRIBUTE_ID &&
3433      current.parent && current.parent.arguments && current.parent.arguments.length) {
3434      idName = current.parent.arguments[0];
3435    }
3436    current = current.expression;
3437  }
3438  return [current, idName];
3439}
3440
3441function checkIdInIf(node:ts.ExpressionStatement, parent: string): ts.Expression {
3442  let current: any = node.expression;
3443  let idName: ts.Expression;
3444  while (current) {
3445    if (parent === COMPONENT_IF && ts.isPropertyAccessExpression(current) && current.name &&
3446      ts.isIdentifier(current.name) && current.name.escapedText.toString() === ATTRIBUTE_ID &&
3447      current.parent && current.parent.arguments && current.parent.arguments.length) {
3448      idName = current.parent.arguments[0];
3449      break;
3450    }
3451    current = current.expression;
3452  }
3453  return idName;
3454}
3455
3456function checkEtsComponent(node: ts.ExpressionStatement, log: LogInfo[]): void {
3457  const etsComponentExpression: ts.EtsComponentExpression = getEtsComponentExpression(node);
3458  if (etsComponentExpression) {
3459    checkAllNode(
3460      etsComponentExpression,
3461      new Set([...INNER_COMPONENT_NAMES, ...componentCollection.customComponents]),
3462      transformLog.sourceFile,
3463      log
3464    );
3465  }
3466}
3467
3468function checkButtonParamHasLabel(node: ts.EtsComponentExpression, log: LogInfo[]): void {
3469  if (node.arguments && node.arguments.length !== 0) {
3470    for (let i = 0; i < node.arguments.length; i++) {
3471      const argument: ts.Expression = node.arguments[i];
3472      if (ts.isStringLiteral(argument) || (ts.isCallExpression(argument) && ts.isIdentifier(argument.expression) &&
3473        (argument.expression.escapedText.toString() === RESOURCE))) {
3474        log.push({
3475          type: LogType.ERROR,
3476          message: 'The Button component with a label parameter can not have any child.',
3477          pos: node.getStart(),
3478          code: '10905202'
3479        });
3480        return;
3481      }
3482    }
3483  }
3484}
3485
3486function isLazyForEachChild(node: ts.ExpressionStatement): boolean {
3487  let temp = node.parent;
3488  while (temp && !ts.isEtsComponentExpression(temp) && !ts.isCallExpression(temp)) {
3489    temp = temp.parent;
3490  }
3491  if (temp && temp.expression && (temp.expression as ts.Identifier).escapedText?.toString() === COMPONENT_LAZYFOREACH) {
3492    return true;
3493  }
3494  return false;
3495}
3496
3497function processDollarEtsComponent(argumentsArr: ts.NodeArray<ts.Expression>, name: string): ts.Expression[] {
3498  const arr: ts.Expression[] = [];
3499  argumentsArr.forEach((item: ts.Expression, index: number) => {
3500    if (ts.isObjectLiteralExpression(item) && item.properties && item.properties.length) {
3501      const properties: ts.PropertyAssignment[] = [];
3502      item.properties.forEach((param: ts.PropertyAssignment, paramIndex: number) => {
3503        if (isHaveDoubleDollar(param, name)) {
3504          const varExp: ts.Expression = updateArgumentForDollar(param.initializer);
3505          properties.push(ts.factory.updatePropertyAssignment(param, param.name, generateObjectForDollar(varExp)));
3506        } else {
3507          properties.push(param);
3508        }
3509      });
3510      arr.push(ts.factory.updateObjectLiteralExpression(item, properties));
3511    } else {
3512      arr.push(item);
3513    }
3514  });
3515  return arr;
3516}
3517
3518function processExclamationEtsComponent(argumentsArr: ts.NodeArray<ts.Expression>, name: string): ts.Expression[] {
3519  const arr: ts.Expression[] = [];
3520  argumentsArr.forEach((item: ts.Expression, index: number) => {
3521    if (ts.isObjectLiteralExpression(item) && item.properties && item.properties.length) {
3522      const properties: ts.PropertyAssignment[] = [];
3523      item.properties.forEach((param: ts.PropertyAssignment, paramIndex: number) => {
3524        if (isHaveDoubleExclamation(param, name) && param.initializer && param.name) {
3525          const varExp: ts.Expression = updateArgumentForExclamation(param.initializer);
3526          properties.push(ts.factory.updatePropertyAssignment(param, param.name, varExp));
3527          properties.push(generateFunctionPropertyAssignmentForExclamation(param.name.getText(), varExp));
3528        } else {
3529          properties.push(param);
3530        }
3531      });
3532      arr.push(ts.factory.updateObjectLiteralExpression(item, properties));
3533    } else {
3534      arr.push(item);
3535    }
3536  });
3537  return arr;
3538}
3539
3540export function createFunction(node: ts.Identifier, attrNode: ts.Identifier,
3541  argumentsArr: ts.NodeArray<ts.Expression>, isAttributeModifier: boolean = false): ts.CallExpression {
3542    const compName: string = node.escapedText.toString();
3543    const type: string = attrNode.escapedText.toString();
3544  if (argumentsArr && argumentsArr.length) {
3545    if (type === COMPONENT_CREATE_FUNCTION && PROPERTIES_ADD_DOUBLE_DOLLAR.has(compName)) {
3546      // @ts-ignore
3547      argumentsArr = processDollarEtsComponent(argumentsArr, compName);
3548    }
3549    if (type === COMPONENT_CREATE_FUNCTION && PROPERTIES_ADD_DOUBLE_EXCLAMATION.has(compName)) {
3550      argumentsArr = processExclamationEtsComponent(argumentsArr, compName) as unknown as ts.NodeArray<ts.Expression>;
3551    }
3552    if (checkCreateArgumentBuilder(node, attrNode)) {
3553      argumentsArr = transformBuilder(argumentsArr);
3554    }
3555    if (compName === NAVIGATION && type === COMPONENT_CREATE_FUNCTION && partialUpdateConfig.partialUpdateMode) {
3556      // @ts-ignore
3557      argumentsArr = navigationCreateParam(compName, type, argumentsArr);
3558    }
3559  } else {
3560    // @ts-ignore
3561    argumentsArr = navigationCreateParam(compName, type);
3562  }
3563  return ts.factory.createCallExpression(
3564    isAttributeModifier ? ts.factory.createCallExpression(
3565      ts.factory.createPropertyAccessExpression(
3566        ts.factory.createPropertyAccessExpression(
3567          node,
3568          attrNode
3569        ),
3570        ts.factory.createIdentifier(BUILDER_ATTR_BIND)
3571      ),
3572      undefined,
3573      [ts.factory.createThis()]
3574    ) :
3575      ts.factory.createPropertyAccessExpression(
3576        node,
3577        attrNode
3578      ),
3579    undefined,
3580    argumentsArr
3581  );
3582}
3583
3584function navigationCreateParam(compName: string, type: string,
3585  argumentsArr: ts.NodeArray<ts.Expression> = undefined, isNavDestinationCallback: boolean = false):
3586  (ts.ObjectLiteralExpression | ts.NewExpression | ts.ArrowFunction)[] | [] {
3587  const navigationOrNavDestination: (ts.ObjectLiteralExpression | ts.NewExpression | ts.ArrowFunction)[] = [];
3588  const isCreate: boolean = type === COMPONENT_CREATE_FUNCTION;
3589  const partialUpdateMode: boolean = partialUpdateConfig.partialUpdateMode;
3590  let isHaveParam: boolean = true;
3591  if (argumentsArr && argumentsArr.length) {
3592    // @ts-ignore
3593    navigationOrNavDestination.push(...argumentsArr);
3594  } else if (partialUpdateMode && isCreate) {
3595    if (compName === NAVIGATION) {
3596      isHaveParam = false;
3597      navigationOrNavDestination.push(ts.factory.createNewExpression(
3598        ts.factory.createIdentifier(NAV_PATH_STACK), undefined, []
3599      ));
3600    } else if (compName === NAV_DESTINATION && !isNavDestinationCallback) {
3601      navigationOrNavDestination.push(ts.factory.createArrowFunction(
3602        undefined, undefined, [], undefined,
3603        ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
3604        ts.factory.createBlock(
3605          [],
3606          false
3607        )
3608      ));
3609    }
3610  }
3611  if (CREATE_ROUTER_COMPONENT_COLLECT.has(compName) && isCreate && partialUpdateMode) {
3612    navigationOrNavDestination.push(ts.factory.createObjectLiteralExpression(
3613      navigationOrNavDestinationCreateContent(compName, isHaveParam),
3614      false
3615    ));
3616  }
3617  return navigationOrNavDestination;
3618}
3619
3620function navigationOrNavDestinationCreateContent(compName: string, isHaveParam: boolean): ts.PropertyAssignment[] {
3621  const navigationOrNavDestinationContent: ts.PropertyAssignment[] = [];
3622  navigationOrNavDestinationContent.push(ts.factory.createPropertyAssignment(
3623    ts.factory.createIdentifier(RESOURCE_NAME_MODULE),
3624    ts.factory.createStringLiteral(projectConfig.moduleName || '')
3625  ),
3626    ts.factory.createPropertyAssignment(
3627      ts.factory.createIdentifier(PAGE_PATH),
3628      ts.factory.createStringLiteral(
3629        projectConfig.compileHar ? '' :
3630          path.relative(projectConfig.projectRootPath || '', resourceFileName).replace(/\\/g, '/').replace(/\.ets$/, '')
3631      )
3632  ));
3633  if (compName === NAVIGATION) {
3634    navigationOrNavDestinationContent.push(ts.factory.createPropertyAssignment(
3635      ts.factory.createIdentifier(IS_USER_CREATE_STACK),
3636      isHaveParam ? ts.factory.createTrue() : ts.factory.createFalse()
3637    ));
3638  }
3639  return navigationOrNavDestinationContent;
3640}
3641
3642function checkCreateArgumentBuilder(node: ts.Identifier, attrNode: ts.Identifier): boolean {
3643  if (attrNode.escapedText.toString() === COMPONENT_CREATE_FUNCTION &&
3644    CREATE_BIND_COMPONENT.has(node.escapedText.toString())) {
3645    return true;
3646  }
3647  return false;
3648}
3649
3650function transformBuilder(argumentsArr: ts.NodeArray<ts.Expression>): ts.NodeArray<ts.Expression> {
3651  const newArguments: ts.Expression[] = [];
3652  argumentsArr.forEach((argument: ts.Expression) => {
3653    newArguments.push(parseCreateParameterBuilder(argument));
3654  });
3655  // @ts-ignore
3656  return newArguments;
3657}
3658
3659function parseCreateParameterBuilder(argument: ts.Expression):ts.Expression {
3660  if (ts.isObjectLiteralExpression(argument)) {
3661    return processObjectPropertyBuilder(argument);
3662  } else {
3663    return argument;
3664  }
3665}
3666
3667function checkNonspecificParents(node: ts.ExpressionStatement, name: string, savedParent: string, log: LogInfo[]): void {
3668  if (SPECIFIC_PARENT_COMPONENT.has(name)) {
3669    const specificParemtsSet: Set<string> = SPECIFIC_PARENT_COMPONENT.get(name);
3670    if (!specificParemtsSet.has(savedParent) && INNER_COMPONENT_NAMES.has(savedParent)) {
3671      const specificParentArray: string =
3672        Array.from(SPECIFIC_PARENT_COMPONENT.get(name)).join(',');
3673      log.push({
3674        type: LogType.ERROR,
3675        message: `The '${name}' component can only be nested in the '${specificParentArray}' parent component.`,
3676        pos: node.expression.getStart(),
3677        code: '10905201'
3678      });
3679    }
3680  }
3681}
3682