diff --git a/compiler/src/pre_define.ts b/compiler/src/pre_define.ts index 3d3a98fa36e4ae18a17cf0f04d54cfbe501745e4..fce34149d3a34a9c3e7a848ea836f950a82cb660 100644 --- a/compiler/src/pre_define.ts +++ b/compiler/src/pre_define.ts @@ -482,7 +482,7 @@ export const __LAZYFOREACHITEMIDFUNC: string = '__lazyForEachItemIdFunc'; export const FOREACHUPDATEFUNCTION: string = 'forEachUpdateFunction'; export const ALLOCATENEWELMETIDFORNEXTCOMPONENT: string = 'AllocateNewElmetIdForNextComponent'; export const STATE_OBJECTLINK_DECORATORS: string[] = [COMPONENT_STATE_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]; -export const COMPONENT_INITIAl_RENDER_FUNCTION: string = 'initialRender'; +export const COMPONENT_INITIAL_RENDER_FUNCTION: string = 'initialRender'; export const DECORATOR_COMPONENT_FREEZEWHENINACTIVE: string = 'freezeWhenInactive'; export const INIT_ALLOW_COMPONENT_FREEZE: string = 'initAllowComponentFreeze'; export const GRID_COMPONENT: string = 'Grid'; diff --git a/compiler/src/process_component_build.ts b/compiler/src/process_component_build.ts index b4974a1d2ca7357538bb875aff029aee60f78b27..75857e3ea9565b866a93a79b72d4b0ead5f29e9f 100644 --- a/compiler/src/process_component_build.ts +++ b/compiler/src/process_component_build.ts @@ -71,11 +71,9 @@ import { STARTGETACCESSRECORDINGFOR, OBSERVECOMPONENTCREATION, OBSERVECOMPONENTCREATION2, - ISLAZYCREATE, DEEPRENDERFUNCTION, ITEMCREATION, ITEMCREATION2, - OBSERVEDSHALLOWRENDER, OBSERVEDDEEPRENDER, ItemComponents, FOREACHITEMGENFUNCTION, @@ -84,7 +82,7 @@ import { FOREACHITEMIDFUNC, __LAZYFOREACHITEMIDFUNC, FOREACHUPDATEFUNCTION, - COMPONENT_INITIAl_RENDER_FUNCTION, + COMPONENT_INITIAL_RENDER_FUNCTION, LIST_ITEM, IFELSEBRANCHUPDATEFUNCTION, CARD_ENABLE_COMPONENTS, @@ -132,12 +130,9 @@ import { NEEDPOP_COMPONENT, INNER_STYLE_FUNCTION, GLOBAL_STYLE_FUNCTION, - COMMON_ATTRS, CUSTOM_BUILDER_PROPERTIES, CUSTOM_BUILDER_PROPERTIES_WITHOUTKEY, CUSTOM_BUILDER_CONSTRUCTORS, - INNER_CUSTOM_BUILDER_METHOD, - GLOBAL_CUSTOM_BUILDER_METHOD, ID_ATTRS, SPECIFIC_PARENT_COMPONENT } from './component_map'; @@ -145,12 +140,12 @@ import { componentCollection, builderParamObjectCollection, checkAllNode, - enumCollection, + enumCollection } from './validate_ui_syntax'; import { processCustomComponent, createConditionParent, - isRecycle, + isRecycle } from './process_custom_component'; import { LogType, @@ -172,10 +167,6 @@ import { import { props } from './compile_info'; import { regularCollection } from './validate_ui_syntax'; -const checkComponents: Set = new Set([ - "TextArea", "TextInput", "GridContainer" -]); - export function processComponentBuild(node: ts.MethodDeclaration, log: LogInfo[]): ts.MethodDeclaration { let newNode: ts.MethodDeclaration; @@ -183,7 +174,7 @@ export function processComponentBuild(node: ts.MethodDeclaration, if (!partialUpdateConfig.partialUpdateMode) { renderNode = ts.factory.createIdentifier(COMPONENT_RENDER_FUNCTION); } else { - renderNode = ts.factory.createIdentifier(COMPONENT_INITIAl_RENDER_FUNCTION); + renderNode = ts.factory.createIdentifier(COMPONENT_INITIAL_RENDER_FUNCTION); } if (node.body && node.body.statements && node.body.statements.length && validateRootNode(node, log)) { @@ -344,6 +335,96 @@ function validateEtsComponentNode(node: ts.CallExpression | ts.EtsComponentExpre let sourceNode: ts.SourceFile; +function handleCustomComponent(item: ts.ExpressionStatement, savedParent: string, + name:string, newStatements: ts.Statement[], log: LogInfo[], isBuilder: boolean, + isGlobalBuilder: boolean, builderParamsResult: BuilderParamsResult): void { + const idName: ts.Expression = checkIdInIf(item, savedParent); + if (!newsupplement.isAcceleratePreview) { + if (item.expression && ts.isEtsComponentExpression(item.expression) && item.expression.body) { + const expressionResult: ts.ExpressionStatement = + processExpressionStatementChange(item, item.expression.body, log); + if (expressionResult) { + item = expressionResult; + } + } + processCustomComponent(item as ts.ExpressionStatement, newStatements, log, name, + isBuilder, isGlobalBuilder, idName, builderParamsResult); + } +} + +function handleForeach(item: ts.ExpressionStatement, newStatements: ts.Statement[], log: LogInfo[], + isBuilder: boolean, isGlobalBuilder: boolean, builderParamsResult: BuilderParamsResult): void { + if (!partialUpdateConfig.partialUpdateMode) { + processForEachComponent(item, newStatements, log, isBuilder, isGlobalBuilder); + } else { + processForEachComponentNew(item, newStatements, log, isGlobalBuilder, builderParamsResult); + } +} + +function handleInnerComponent(item: ts.ExpressionStatement, newStatements: ts.Statement[], log: LogInfo[], + isBuilder: boolean, isGlobalBuilder: boolean, parent: string, savedParent: string, + isTransition: boolean, builderParamsResult: BuilderParamsResult): string { + const [etsExpression, idName]: [ts.EtsComponentExpression, ts.Expression] = + checkEtsAndIdInIf(item, savedParent); + if (ts.isIdentifier(etsExpression.expression)) { + parent = etsExpression.expression.escapedText.toString(); + } + processInnerComponent(item, newStatements, log, parent, isBuilder, isGlobalBuilder, + isTransition, idName, savedParent, builderParamsResult); + return parent; +} + +function handleComponent(item: ts.ExpressionStatement, newStatements: ts.Statement[], log: LogInfo[], + isBuilder: boolean, isGlobalBuilder: boolean, parent:string, savedParent:string, isTransition: boolean, + name: string, forEachParameters: ts.NodeArray, + builderParamsResult: BuilderParamsResult): string { + switch (getComponentType(item, log, name, parent, forEachParameters)) { + case ComponentType.innerComponent: { + parent = handleInnerComponent(item, newStatements, log, isBuilder, isGlobalBuilder, + parent, savedParent, isTransition, builderParamsResult); + break; + } + case ComponentType.customComponent: { + parent = undefined; + handleCustomComponent(item, savedParent, name, newStatements, log, isBuilder, isGlobalBuilder, builderParamsResult); + break; + } + case ComponentType.forEachComponent: + parent = undefined; + handleForeach(item, newStatements, log, isBuilder, isGlobalBuilder, builderParamsResult); + break; + case ComponentType.customBuilderMethod: + parent = undefined; + if (partialUpdateConfig.partialUpdateMode) { + newStatements.push(transferBuilderCall(item, name, isBuilder)); + } else { + newStatements.push(addInnerBuilderParameter(item, isGlobalBuilder)); + } + break; + case ComponentType.builderParamMethod: + parent = undefined; + if (partialUpdateConfig.partialUpdateMode) { + newStatements.push(transferBuilderCall(item, name, isBuilder)); + } else { + newStatements.push(addInnerBuilderParameter(item)); + } + break; + case ComponentType.builderTypeFunction: + parent = undefined; + if (partialUpdateConfig.partialUpdateMode) { + newStatements.push(transferBuilderCall(item, name, isBuilder)); + } else { + newStatements.push(addInnerBuilderParameter(item)); + } + break; + case ComponentType.function: + parent = undefined; + newStatements.push(item); + break; + } + return parent; +} + export function processComponentChild(node: ts.Block | ts.SourceFile, newStatements: ts.Statement[], log: LogInfo[], supplement: supplementType = {isAcceleratePreview: false, line: 0, column: 0, fileName: ''}, isBuilder: boolean = false, parent: string = undefined, @@ -368,70 +449,8 @@ export function processComponentChild(node: ts.Block | ts.SourceFile, newStateme if (CARD_ENABLE_COMPONENTS.has(name)) { validatorCard(log, CARD_LOG_TYPE_COMPONENTS, item.getStart(), name); } - switch (getComponentType(item, log, name, parent, forEachParameters)) { - case ComponentType.innerComponent: { - const [etsExpression, idName]: [ts.EtsComponentExpression, ts.Expression] = - checkEtsAndIdInIf(item, savedParent); - if (ts.isIdentifier(etsExpression.expression)) { - parent = etsExpression.expression.escapedText.toString(); - } - processInnerComponent(item, newStatements, log, parent, isBuilder, isGlobalBuilder, - isTransition, idName, savedParent, builderParamsResult); - break; - } - case ComponentType.customComponent: { - const idName: ts.Expression = checkIdInIf(item, savedParent); - parent = undefined; - if (!newsupplement.isAcceleratePreview) { - if (item.expression && ts.isEtsComponentExpression(item.expression) && item.expression.body) { - const expressionResult: ts.ExpressionStatement = - processExpressionStatementChange(item, item.expression.body, log); - if (expressionResult) { - item = expressionResult; - } - } - processCustomComponent(item as ts.ExpressionStatement, newStatements, log, name, - isBuilder, isGlobalBuilder, idName, builderParamsResult); - } - break; - } - case ComponentType.forEachComponent: - parent = undefined; - if (!partialUpdateConfig.partialUpdateMode) { - processForEachComponent(item, newStatements, log, isBuilder, isGlobalBuilder); - } else { - processForEachComponentNew(item, newStatements, log, isGlobalBuilder, builderParamsResult); - } - break; - case ComponentType.customBuilderMethod: - parent = undefined; - if (partialUpdateConfig.partialUpdateMode) { - newStatements.push(transferBuilderCall(item, name, isBuilder)); - } else { - newStatements.push(addInnerBuilderParameter(item, isGlobalBuilder)); - } - break; - case ComponentType.builderParamMethod: - parent = undefined; - if (partialUpdateConfig.partialUpdateMode) { - newStatements.push(transferBuilderCall(item, name, isBuilder)); - } else { - newStatements.push(addInnerBuilderParameter(item)); - } - break; - case ComponentType.builderTypeFunction: - parent = undefined; - if (partialUpdateConfig.partialUpdateMode) { - newStatements.push(transferBuilderCall(item, name, isBuilder)); - } else { - newStatements.push(addInnerBuilderParameter(item)); - } - break; - case ComponentType.function: - parent = undefined; - newStatements.push(item); - break; - } + parent = handleComponent(item, newStatements, log, isBuilder, isGlobalBuilder, parent, savedParent, + isTransition, name, forEachParameters, builderParamsResult); } else if (ts.isIfStatement(item)) { processIfStatement(item, newStatements, log, isBuilder, isGlobalBuilder, builderParamsResult); } else if (!ts.isBlock(item)) { @@ -590,8 +609,8 @@ function processExpressionStatementChange(node: ts.ExpressionStatement, nextNode } else { log.push({ type: LogType.ERROR, - message: `In the trailing lambda case, '${name}' must have one and only one property decorated with ` - + `@BuilderParam, and its @BuilderParam expects no parameter.`, + message: `In the trailing lambda case, '${name}' must have one and only one property decorated with ` + + `@BuilderParam, and its @BuilderParam expects no parameter.`, pos: node.getStart() }); return null; @@ -784,6 +803,7 @@ function processDebug(node: ts.Statement, nameResult: NameResult, newStatements: } newStatements.push(debugNode); } + return undefined; } function processInnerCompStatements(innerCompStatements: ts.Statement[], @@ -1038,7 +1058,7 @@ function createItemCreation(node: ts.ExpressionStatement, isGlobalBuilder: boole ts.factory.createBlock( [createComponent(node, COMPONENT_POP_FUNCTION).newNode], true - ), + ) ), createViewStackProcessorStatement(STOPGETACCESSRECORDING) ], @@ -1100,7 +1120,7 @@ function createDeepRenderFunction( node: ts.ExpressionStatement, deepItemRenderInnerStatements: ts.Statement[], isGlobalBuilder: boolean, - builderParamsResult: BuilderParamsResult, + builderParamsResult: BuilderParamsResult ): ts.VariableStatement { const blockNode: ts.Statement[] = [ ts.factory.createExpressionStatement(ts.factory.createCallExpression( @@ -1254,7 +1274,7 @@ function processForEachComponent(node: ts.ExpressionStatement, newStatements: ts argumentsArray.splice(0, 1, arrayObserveredObject); const newForEachArrowFunc: ts.ArrowFunction = processForEachFunctionBlock(node.expression); const newArrowNode: ts.ArrowFunction = - processForEachBlock(node.expression, log, newForEachArrowFunc, isBuilder, ) as ts.ArrowFunction; + processForEachBlock(node.expression, log, newForEachArrowFunc, isBuilder) as ts.ArrowFunction; if (newArrowNode) { argumentsArray.splice(1, 1, newArrowNode); } @@ -1330,6 +1350,7 @@ function createItemGenFunctionStatement( ) ); } + return undefined; } function isForEachItemGeneratorParam(argumentsArray: ts.Expression, newArrowNode: ts.NodeArray): ts.Statement[] { @@ -1379,6 +1400,7 @@ function createItemIdFuncStatement( ) ); } + return undefined; } function createUpdateFunctionStatement(argumentsArray: ts.Expression[], @@ -1582,9 +1604,9 @@ function processThenStatement(thenStatement: ts.Statement, id: number, } else if (ts.isIfStatement(thenStatement)) { thenStatement = processInnerIfStatement(thenStatement, 0, log, isBuilder, isGlobalBuilder, builderParamsResult); thenStatement = ts.factory.createBlock( - partialUpdateConfig.partialUpdateMode - ? [createIfCreate(), createIfBranchFunc(id, [thenStatement], isGlobalBuilder), createIfPop()] - : [createIfCreate(), createIfBranchId(id), thenStatement, createIfPop()], + partialUpdateConfig.partialUpdateMode ? + [createIfCreate(), createIfBranchFunc(id, [thenStatement], isGlobalBuilder), createIfPop()] : + [createIfCreate(), createIfBranchId(id), thenStatement, createIfPop()], true ); } else { @@ -1705,9 +1727,9 @@ function createComponent(node: ts.ExpressionStatement, type: string): CreateResu ts.isEtsComponentExpression(temp.parent)) && ts.isIdentifier(temp)) { if (temp.getText() === COMPONENT_BUTTON && type !== COMPONENT_POP_FUNCTION) { res.isButton = true; - identifierNode = type === COMPONENT_CREATE_CHILD_FUNCTION - ? ts.factory.createIdentifier(COMPONENT_CREATE_CHILD_FUNCTION) - : ts.factory.createIdentifier(COMPONENT_CREATE_LABEL_FUNCTION); + identifierNode = type === COMPONENT_CREATE_CHILD_FUNCTION ? + ts.factory.createIdentifier(COMPONENT_CREATE_CHILD_FUNCTION) : + ts.factory.createIdentifier(COMPONENT_CREATE_LABEL_FUNCTION); } if (NEEDPOP_COMPONENT.has(temp.getText())) { res.needPop = true; @@ -1715,9 +1737,9 @@ function createComponent(node: ts.ExpressionStatement, type: string): CreateResu if (checkContainer(temp.getText(), temp.parent)) { res.isContainerComponent = true; } - res.newNode = type === COMPONENT_POP_FUNCTION - ? ts.factory.createExpressionStatement(createFunction(temp, identifierNode, null)) - : ts.factory.createExpressionStatement(createFunction(temp, identifierNode, checkArguments(temp, type))); + res.newNode = type === COMPONENT_POP_FUNCTION ? + ts.factory.createExpressionStatement(createFunction(temp, identifierNode, null)) : + ts.factory.createExpressionStatement(createFunction(temp, identifierNode, checkArguments(temp, type))); res.identifierNode = temp; } return res; @@ -1742,7 +1764,7 @@ function checkArguments(temp: ts.Identifier, type: string): ts.Expression[] { // @ts-ignore temp.parent.arguments.concat([ ts.factory.createStringLiteral(`${projectConfig.bundleName}/${projectConfig.moduleName}`) - ]) : temp.parent.arguments + ]) : temp.parent.arguments; } function checkContainer(name: string, node: ts.Node): boolean { @@ -1787,27 +1809,10 @@ export interface ComponentAttrInfo { reuseId: ts.Node } -export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode: ts.Identifier, - newStatements: ts.Statement[], log: LogInfo[], reverse: boolean = true, - isStylesAttr: boolean = false, newImmutableStatements: ts.Statement[] = null, - isStyleFunction: boolean = false, componentAttrInfo: ComponentAttrInfo = null): void { - let temp: any = node.expression; - const statements: ts.Statement[] = []; - const immutableStatements: ts.Statement[] = []; - const updateStatements: ts.Statement[] = []; - const lastStatement: AnimationInfo = { - statement: null, - kind: false, - hasAnimationAttr: false, - }; - const isRecycleComponent: boolean = isRecycle(componentCollection.currentClassName); - if (ts.isPropertyAccessExpression(temp)) { - log.push({ - type: LogType.ERROR, - message: `'${node.getText()}' does not meet UI component syntax.`, - pos: node.getStart() - }); - } +function handleComponentAttr(temp: any, componentAttrInfo: ComponentAttrInfo, lastStatement: any, + statements: ts.Statement[], identifierNode: ts.Identifier, log: LogInfo[], isStylesAttr: boolean, + immutableStatements: ts.Statement[], updateStatements: ts.Statement[], + newImmutableStatements: ts.Statement[], isRecycleComponent: boolean, isStyleFunction: boolean): void { while (temp && ts.isCallExpression(temp) && temp.expression) { let flag: boolean = false; if (temp.expression && (validatePropertyAccessExpressionWithCustomBuilder(temp.expression) || @@ -1818,15 +1823,12 @@ export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode: } else if (ts.isPropertyAccessExpression(temp.expression)) { propertyName = temp.expression.name.escapedText.toString(); } - switch (true) { - case BIND_POPUP_SET.has(propertyName): - temp = processBindPopupBuilder(temp); - break; - case BIND_DRAG_SET.has(propertyName): - temp = processDragStartBuilder(temp, propertyName); - break; - default: - temp = processCustomBuilderProperty(temp, identifierNode, propertyName); + if (BIND_POPUP_SET.has(propertyName)) { + temp = processBindPopupBuilder(temp); + } else if (BIND_DRAG_SET.has(propertyName)) { + temp = processDragStartBuilder(temp, propertyName); + } else { + temp = processCustomBuilderProperty(temp, identifierNode, propertyName); } flag = true; } @@ -1854,6 +1856,31 @@ export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode: temp = temp.expression; } } +} + +export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode: ts.Identifier, + newStatements: ts.Statement[], log: LogInfo[], reverse: boolean = true, + isStylesAttr: boolean = false, newImmutableStatements: ts.Statement[] = null, + isStyleFunction: boolean = false, componentAttrInfo: ComponentAttrInfo = null): void { + const temp: any = node.expression; + const statements: ts.Statement[] = []; + const immutableStatements: ts.Statement[] = []; + const updateStatements: ts.Statement[] = []; + const lastStatement: AnimationInfo = { + statement: null, + kind: false, + hasAnimationAttr: false + }; + const isRecycleComponent: boolean = isRecycle(componentCollection.currentClassName); + if (ts.isPropertyAccessExpression(temp)) { + log.push({ + type: LogType.ERROR, + message: `'${node.getText()}' does not meet UI component syntax.`, + pos: node.getStart() + }); + } + handleComponentAttr(temp, componentAttrInfo, lastStatement, statements, identifierNode, log, isStylesAttr, + immutableStatements, updateStatements, newImmutableStatements, isRecycleComponent, isStyleFunction); if (lastStatement.statement && lastStatement.kind) { statements.push(lastStatement.statement); } @@ -1894,13 +1921,17 @@ function processCustomBuilderProperty(node: ts.CallExpression, identifierNode: t return node; } -function isBuilderChangeNode(argument: ts.Node, identifierNode: ts.Identifier, propertyName: string): boolean { +function isCustomBuilder(argument: ts.Node): boolean { return ts.isPropertyAccessExpression(argument) && argument.name && ts.isIdentifier(argument.name) && - storedFileInfo.builderLikeCollection.has(argument.name.getText()) || - ts.isCallExpression(argument) && argument.expression && argument.expression.name && - ts.isIdentifier(argument.expression.name) && - storedFileInfo.builderLikeCollection.has(argument.expression.name.getText()) || ts.isIdentifier(argument) && - argument.escapedText && storedFileInfo.builderLikeCollection.has(argument.escapedText.toString()) || + storedFileInfo.builderLikeCollection.has(argument.name.getText()) || + ts.isCallExpression(argument) && argument.expression && argument.expression.name && + ts.isIdentifier(argument.expression.name) && + storedFileInfo.builderLikeCollection.has(argument.expression.name.getText()) || ts.isIdentifier(argument) && + argument.escapedText && storedFileInfo.builderLikeCollection.has(argument.escapedText.toString()); +} + +function isBuilderChangeNode(argument: ts.Node, identifierNode: ts.Identifier, propertyName: string): boolean { + return isCustomBuilder(argument) || ts.isObjectLiteralExpression(argument) && (BIND_OBJECT_PROPERTY.get(identifierNode.escapedText.toString()) && BIND_OBJECT_PROPERTY.get(identifierNode.escapedText.toString()).has(propertyName) || BIND_OBJECT_PROPERTY.get(ALL_COMPONENTS).has(propertyName)) || @@ -1951,13 +1982,14 @@ function parseBuilderNode(node: ts.Node, propertyName: string): } else if (ts.isObjectLiteralExpression(node)) { return processObjectPropertyBuilder(node); } + return undefined; } export function processObjectPropertyBuilder(node: ts.ObjectLiteralExpression): ts.ObjectLiteralExpression { const newProperties: ts.PropertyAssignment[] = []; node.properties.forEach((property: ts.PropertyAssignment) => { if (property.name && ts.isIdentifier(property.name) && - [CUSTOM_DIALOG_CONTROLLER_BUILDER, HEADER, FOOTER, START, END, PREVIEW,TITLE].includes( + [CUSTOM_DIALOG_CONTROLLER_BUILDER, HEADER, FOOTER, START, END, PREVIEW, TITLE].includes( property.name.escapedText.toString()) && property.initializer) { if (isPropertyAccessExpressionNode(property.initializer) || ts.isIdentifier(property.initializer) && storedFileInfo.builderLikeCollection.has(property.initializer.escapedText.toString())) { @@ -2284,6 +2316,7 @@ function updateArgumentFor$$(argument: any): ts.Expression { return ts.factory.updatePropertyAccessExpression( argument, updateArgumentFor$$(argument.expression), argument.name); } + return undefined; } function verifyComponentId(temp: any, node: ts.Identifier, propName: string, @@ -2318,6 +2351,100 @@ function verifyComponentId(temp: any, node: ts.Identifier, propName: string, } } +function addAnimationAttr(temp: any, node: ts.Identifier, lastStatement: any, + statements: ts.Statement[]): void { + const animationNullNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( + createFunction(ts.factory.createIdentifier(GLOBAL_CONTEXT), node, + // @ts-ignore + [ts.factory.createNull()])); + if (!lastStatement.statement) { + if (!(temp.arguments.length === 1 && + temp.arguments[0].kind === ts.SyntaxKind.NullKeyword)) { + statements.push(animationNullNode); + } + } else { + statements.push(lastStatement.statement, animationNullNode); + } + lastStatement.statement = ts.factory.createExpressionStatement(createFunction( + ts.factory.createIdentifier(GLOBAL_CONTEXT), node, temp.arguments)); + lastStatement.kind = false; + lastStatement.hasAnimationAttr = true; +} + +function addAnimatableExtendAttr(temp: any, node: ts.Identifier, lastStatement: any, + statements: ts.Statement[], identifierNode: ts.Identifier, log: LogInfo[], + updateStatements: ts.Statement[], extendType: ExtendType, propName: string): void { + if (newsupplement.isAcceleratePreview) { + log.push({ + type: LogType.ERROR, + message: `Doesn't support Extend function now`, + pos: temp.getStart() + }); + } + let functionName: string = ''; + if (extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR) { + functionName = `__${identifierNode.escapedText.toString()}__${propName}`; + } else { + functionName = propName; + } + const extendNode: ts.Statement = ts.factory.createExpressionStatement( + ts.factory.createCallExpression(ts.factory.createIdentifier(functionName), undefined, + extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR ? + temp.arguments : + [ + ...temp.arguments, ts.factory.createIdentifier(ELMTID), + ts.factory.createIdentifier(ISINITIALRENDER), + ts.factory.createThis() + ] + )); + statements.push(extendNode); + updateStatements.push(extendNode); + lastStatement.kind = true; +} + +function addStateStylesAttr(temp: any, lastStatement: any, statements: ts.Statement[], + identifierNode: ts.Identifier, log: LogInfo[], updateStatements: ts.Statement[], + newImmutableStatements: ts.Statement[], isRecycleComponent: boolean): void { + if (temp.arguments.length === 1 && ts.isObjectLiteralExpression(temp.arguments[0])) { + statements.push(createViewStackProcessor(temp, true)); + if (isRecycleComponent) { + updateStatements.push(createViewStackProcessor(temp, true)); + } + traverseStateStylesAttr(temp, statements, identifierNode, log, updateStatements, + newImmutableStatements, isRecycleComponent); + lastStatement.kind = true; + } else { + validateStateStyleSyntax(temp, log); + } +} + +function addStyleFunctionAttr(lastStatement: any, statements: ts.Statement[], + identifierNode: ts.Identifier, log: LogInfo[], propName: string, updateStatements: ts.Statement[], + newImmutableStatements: ts.Statement[], isRecycleComponent: boolean): void { + const styleBlock: ts.Block = + INNER_STYLE_FUNCTION.get(propName) || GLOBAL_STYLE_FUNCTION.get(propName); + if (styleBlock.statements.length > 0) { + bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode, + statements, log, false, true, newImmutableStatements); + if (isRecycleComponent) { + bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode, + updateStatements, log, false, true, newImmutableStatements, true); + } + } + lastStatement.kind = true; +} + +function addDoubleDollarAttr(temp: any, propName: string, node: ts.Identifier, lastStatement: any, + statements: ts.Statement[], identifierNode: ts.Identifier, updateStatements: ts.Statement[]): void { + const argumentsArr: ts.Expression[] = []; + classifyArgumentsNum(temp.arguments, argumentsArr, propName, identifierNode); + const doubleDollarNode: ts.Statement = ts.factory.createExpressionStatement( + createFunction(identifierNode, node, argumentsArr)); + statements.push(doubleDollarNode); + updateStatements.push(doubleDollarNode); + lastStatement.kind = true; +} + function addComponentAttr(temp: any, node: ts.Identifier, lastStatement: any, statements: ts.Statement[], identifierNode: ts.Identifier, log: LogInfo[], isStylesAttr: boolean, immutableStatements: ts.Statement[], updateStatements: ts.Statement[], @@ -2327,84 +2454,21 @@ function addComponentAttr(temp: any, node: ts.Identifier, lastStatement: any, verifyComponentId(temp, node, propName, log); const extendType: ExtendType = {type: ''}; if (propName === ATTRIBUTE_ANIMATION) { - const animationNullNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( - createFunction(ts.factory.createIdentifier(GLOBAL_CONTEXT), node, - // @ts-ignore - [ts.factory.createNull()])); - if (!lastStatement.statement) { - if (!(temp.arguments.length === 1 && - temp.arguments[0].kind === ts.SyntaxKind.NullKeyword)) { - statements.push(animationNullNode); - } - } else { - statements.push(lastStatement.statement, animationNullNode); - } - lastStatement.statement = ts.factory.createExpressionStatement(createFunction( - ts.factory.createIdentifier(GLOBAL_CONTEXT), node, temp.arguments)); - lastStatement.kind = false; - lastStatement.hasAnimationAttr = true; + addAnimationAttr(temp, node, lastStatement, statements); } else if (GESTURE_ATTRS.has(propName)) { parseGesture(temp, propName, statements, log, updateStatements); lastStatement.kind = true; } else if (isExtendFunctionNode(identifierNode, propName, extendType)) { - if (newsupplement.isAcceleratePreview) { - log.push({ - type: LogType.ERROR, - message: `Doesn't support Extend function now`, - pos: temp.getStart() - }); - } - let functionName: string = ''; - if (extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR) { - functionName = `__${identifierNode.escapedText.toString()}__${propName}`; - } else { - functionName = propName; - } - const extendNode: ts.Statement = ts.factory.createExpressionStatement( - ts.factory.createCallExpression(ts.factory.createIdentifier(functionName), undefined, - extendType.type === CHECK_COMPONENT_EXTEND_DECORATOR - ? temp.arguments - : [ - ...temp.arguments, ts.factory.createIdentifier(ELMTID), - ts.factory.createIdentifier(ISINITIALRENDER), - ts.factory.createThis() - ] - )); - statements.push(extendNode); - updateStatements.push(extendNode); - lastStatement.kind = true; + addAnimatableExtendAttr(temp, node, lastStatement, statements, identifierNode, log, + updateStatements, extendType, propName); } else if (propName === ATTRIBUTE_STATESTYLES) { - if (temp.arguments.length === 1 && ts.isObjectLiteralExpression(temp.arguments[0])) { - statements.push(createViewStackProcessor(temp, true)); - if (isRecycleComponent) { - updateStatements.push(createViewStackProcessor(temp, true)); - } - traverseStateStylesAttr(temp, statements, identifierNode, log, updateStatements, - newImmutableStatements, isRecycleComponent); - lastStatement.kind = true; - } else { - validateStateStyleSyntax(temp, log); - } + addStateStylesAttr(temp, lastStatement, statements, identifierNode, log, updateStatements, + newImmutableStatements, isRecycleComponent); } else if (GLOBAL_STYLE_FUNCTION.has(propName) || INNER_STYLE_FUNCTION.has(propName)) { - const styleBlock: ts.Block = - INNER_STYLE_FUNCTION.get(propName) || GLOBAL_STYLE_FUNCTION.get(propName); - if (styleBlock.statements.length > 0) { - bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode, - statements, log, false, true, newImmutableStatements); - if (isRecycleComponent) { - bindComponentAttr(styleBlock.statements[0] as ts.ExpressionStatement, identifierNode, - updateStatements, log, false, true, newImmutableStatements, true); - } - } - lastStatement.kind = true; + addStyleFunctionAttr(lastStatement, statements, identifierNode, log, propName, updateStatements, + newImmutableStatements, isRecycleComponent); } else if (isDoubleDollarToChange(isStylesAttr, identifierNode, propName, temp)) { - const argumentsArr: ts.Expression[] = []; - classifyArgumentsNum(temp.arguments, argumentsArr, propName, identifierNode); - const doubleDollarNode: ts.Statement = ts.factory.createExpressionStatement( - createFunction(identifierNode, node, argumentsArr)); - statements.push(doubleDollarNode); - updateStatements.push(doubleDollarNode); - lastStatement.kind = true; + addDoubleDollarAttr(temp, propName, node, lastStatement, statements, identifierNode, updateStatements); } else { temp = loopEtscomponent(temp, isStylesAttr); if (propName !== RECYCLE_REUSE_ID) { @@ -2500,8 +2564,8 @@ function isDoubleDollarToChange(isStylesAttr: boolean, identifierNode: ts.Identi PROPERTIES_ADD_DOUBLE_DOLLAR.has(identifierNode.escapedText.toString()) && PROPERTIES_ADD_DOUBLE_DOLLAR.get(identifierNode.escapedText.toString()).has(propName) || STYLE_ADD_DOUBLE_DOLLAR.has(propName) && temp.arguments.length && temp.arguments[0] ? - temp.arguments[0].getText().match(/^\$\$(.|\n)+/) !== null - : false; + temp.arguments[0].getText().match(/^\$\$(.|\n)+/) !== null : + false; } function processDollarEtsComponent(node: ts.EtsComponentExpression, name: string @@ -2619,11 +2683,11 @@ function traverseStateStylesAttr(temp: any, statements: ts.Statement[], ts.isPropertyAssignment(item.initializer.properties[0])) { bindComponentAttr(ts.factory.createExpressionStatement( item.initializer.properties[0].initializer), identifierNode, statements, log, false, true, - newImmutableStatements); + newImmutableStatements); if (isRecycleComponent) { bindComponentAttr(ts.factory.createExpressionStatement( item.initializer.properties[0].initializer), identifierNode, updateStatements, log, false, true, - newImmutableStatements); + newImmutableStatements); } } else { if (!(ts.isObjectLiteralExpression(item.initializer) && item.initializer.properties.length === 0)) { @@ -2806,23 +2870,25 @@ function isEtsComponent(node: ts.ExpressionStatement): boolean { } function isSomeName(forEachParameters: ts.NodeArray, name: string): boolean { - return Array.isArray(forEachParameters) && - forEachParameters.some((item)=>{ + return Array.isArray(forEachParameters) && + forEachParameters.some((item) => { return ts.isIdentifier(item.name) ? item.name.escapedText.toString() === name : false; }); } function isParamFunction(node: ts.ExpressionStatement): boolean { - return node.expression && ts.isCallExpression(node.expression) && + return node.expression && ts.isCallExpression(node.expression) && node.expression.expression && ts.isIdentifier(node.expression.expression); } +function judgeBuilderName(node: ts.ExpressionStatement, name: string, + forEachParameters: ts.NodeArray): boolean { + return !(forEachParameters && isSomeName(forEachParameters, name) && isParamFunction(node)); +} + function getComponentType(node: ts.ExpressionStatement, log: LogInfo[], name: string, parent: string, forEachParameters: ts.NodeArray = undefined): ComponentType { - let isBuilderName: boolean = true; - if (forEachParameters && isSomeName(forEachParameters, name) && isParamFunction(node)) { - isBuilderName = false; - } + const isBuilderName: boolean = judgeBuilderName(node, name, forEachParameters); if (isEtsComponent(node)) { if (componentCollection.customComponents.has(name)) { return ComponentType.customComponent; @@ -2944,7 +3010,7 @@ function checkEtsComponent(node: ts.ExpressionStatement, log: LogInfo[]): void { function checkButtonParamHasLabel(node: ts.EtsComponentExpression, log: LogInfo[]): void { if (node.arguments && node.arguments.length !== 0) { for (let i = 0; i < node.arguments.length; i++) { - let argument: ts.Expression = node.arguments[i]; + const argument: ts.Expression = node.arguments[i]; if (ts.isStringLiteral(argument) || (ts.isCallExpression(argument) && ts.isIdentifier(argument.expression) && (argument.expression.escapedText.toString() === RESOURCE))) { log.push({