mirror of
https://github.com/openharmony/developtools_ace-ets2bundle.git
synced 2026-07-20 19:47:44 -04:00
Signed-off-by: puyajun <puyajun@huawei.com> Change-Id: I8b94648ddcf67eac2ceedcd188b9924ab0943c15
This commit is contained in:
@@ -91,6 +91,9 @@ export const JS_BIND_COMPONENTS: Set<string> = new Set([
|
||||
|
||||
export const NEEDPOP_COMPONENT: Set<string> = new Set(['Blank', 'Search']);
|
||||
|
||||
export const CUSTOM_BUILDER_PROPERTIES: Set<string> = new Set(['bindPopup', 'bindMenu', 'bindContextMenu', 'title',
|
||||
'menus', 'toolBar', 'tabBar']);
|
||||
|
||||
(function initComponent() {
|
||||
Object.keys(COMPONENT_MAP).forEach((componentName) => {
|
||||
INNER_COMPONENT_NAMES.add(componentName);
|
||||
|
||||
@@ -52,7 +52,10 @@ import {
|
||||
$$_VALUE,
|
||||
$$_CHANGE_EVENT,
|
||||
$$_THIS,
|
||||
$$_NEW_VALUE
|
||||
$$_NEW_VALUE,
|
||||
BUILDER_ATTR_NAME,
|
||||
BUILDER_ATTR_BIND,
|
||||
CUSTOM_DIALOG_CONTROLLER_BUILDER
|
||||
} from './pre_define';
|
||||
import {
|
||||
INNER_COMPONENT_NAMES,
|
||||
@@ -66,7 +69,8 @@ import {
|
||||
NEEDPOP_COMPONENT,
|
||||
INNER_STYLE_FUNCTION,
|
||||
GLOBAL_STYLE_FUNCTION,
|
||||
COMMON_ATTRS
|
||||
COMMON_ATTRS,
|
||||
CUSTOM_BUILDER_PROPERTIES
|
||||
} from './component_map';
|
||||
import { componentCollection } from './validate_ui_syntax';
|
||||
import { processCustomComponent } from './process_custom_component';
|
||||
@@ -516,6 +520,16 @@ export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode:
|
||||
const statements: ts.Statement[] = [];
|
||||
const lastStatement: AnimationInfo = { statement: null, kind: false };
|
||||
while (temp && ts.isCallExpression(temp) && temp.expression) {
|
||||
if (temp.expression && (validatePropertyAccessExpressionWithCustomBuilder(temp.expression) ||
|
||||
validateIdentifierWithCustomBuilder(temp.expression))) {
|
||||
let propertyName: string = '';
|
||||
if (ts.isIdentifier(temp.expression)) {
|
||||
propertyName = temp.expression.escapedText.toString();
|
||||
} else if (ts.isPropertyAccessExpression(temp.expression)) {
|
||||
propertyName = temp.expression.name.escapedText.toString();
|
||||
}
|
||||
temp = propertyName === BIND_POPUP ? processBindPopupBuilder(temp) : processCustomBuilderProperty(temp);
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(temp.expression) &&
|
||||
temp.expression.name && ts.isIdentifier(temp.expression.name)) {
|
||||
addComponentAttr(temp, temp.expression.name, lastStatement, statements, identifierNode, log,
|
||||
@@ -538,6 +552,122 @@ export function bindComponentAttr(node: ts.ExpressionStatement, identifierNode:
|
||||
}
|
||||
}
|
||||
|
||||
function processCustomBuilderProperty(node: ts.CallExpression): ts.CallExpression {
|
||||
const newArguments: ts.Expression[] = [];
|
||||
node.arguments.forEach((argument: ts.Expression | ts.Identifier, index: number) => {
|
||||
if (index === 0 && (ts.isPropertyAccessExpression(argument) || ts.isCallExpression(argument) ||
|
||||
ts.isIdentifier(argument))) {
|
||||
newArguments.push(parseBuilderNode(argument));
|
||||
} else {
|
||||
newArguments.push(argument);
|
||||
}
|
||||
});
|
||||
node = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, newArguments);
|
||||
return node;
|
||||
}
|
||||
|
||||
function parseBuilderNode(node: ts.Node): ts.ObjectLiteralExpression {
|
||||
if (isPropertyAccessExpressionNode(node)) {
|
||||
return processPropertyBuilder(node as ts.PropertyAccessExpression);
|
||||
} else if (ts.isIdentifier(node) && CUSTOM_BUILDER_METHOD.has(node.escapedText.toString())) {
|
||||
return processIdentifierBuilder(node);
|
||||
} else if (ts.isCallExpression(node)) {
|
||||
return getParsedBuilderAttrArgumentWithParams(node);
|
||||
}
|
||||
}
|
||||
|
||||
function isPropertyAccessExpressionNode(node: ts.Node): boolean {
|
||||
return ts.isPropertyAccessExpression(node) && node.expression &&
|
||||
node.expression.kind === ts.SyntaxKind.ThisKeyword && node.name && ts.isIdentifier(node.name) &&
|
||||
CUSTOM_BUILDER_METHOD.has(node.name.escapedText.toString());
|
||||
}
|
||||
|
||||
function processBindPopupBuilder(node: ts.CallExpression): ts.CallExpression {
|
||||
const newArguments: ts.Expression[] = [];
|
||||
node.arguments.forEach((argument: ts.ObjectLiteralExpression, index: number) => {
|
||||
if (index === 1) {
|
||||
// @ts-ignore
|
||||
newArguments.push(processBindPopupBuilderProperty(argument));
|
||||
} else {
|
||||
newArguments.push(argument);
|
||||
}
|
||||
});
|
||||
node = ts.factory.updateCallExpression(node, node.expression, node.typeArguments, newArguments);
|
||||
return node;
|
||||
}
|
||||
|
||||
function processBindPopupBuilderProperty(node: ts.ObjectLiteralExpression): ts.ObjectLiteralExpression {
|
||||
const newProperties: ts.PropertyAssignment[] = [];
|
||||
node.properties.forEach((property: ts.PropertyAssignment, index: number) => {
|
||||
if (index === 0) {
|
||||
if (property.name && ts.isIdentifier(property.name) &&
|
||||
property.name.escapedText.toString() === CUSTOM_DIALOG_CONTROLLER_BUILDER) {
|
||||
newProperties.push(ts.factory.updatePropertyAssignment(property, property.name,
|
||||
parseBuilderNode(property.initializer)));
|
||||
} else {
|
||||
newProperties.push(property);
|
||||
}
|
||||
} else {
|
||||
newProperties.push(property);
|
||||
}
|
||||
});
|
||||
return ts.factory.updateObjectLiteralExpression(node, newProperties);
|
||||
}
|
||||
|
||||
function processPropertyBuilder(node: ts.PropertyAccessExpression): ts.ObjectLiteralExpression {
|
||||
return ts.factory.createObjectLiteralExpression([
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_NAME),
|
||||
ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
node,
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_BIND)
|
||||
),
|
||||
undefined,
|
||||
[ts.factory.createThis()]
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
function processIdentifierBuilder(node: ts.Identifier): ts.ObjectLiteralExpression {
|
||||
return ts.factory.createObjectLiteralExpression([
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_NAME),
|
||||
node
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
function getParsedBuilderAttrArgumentWithParams(node: ts.CallExpression):
|
||||
ts.ObjectLiteralExpression {
|
||||
return ts.factory.createObjectLiteralExpression([
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_NAME),
|
||||
ts.factory.createArrowFunction(
|
||||
undefined,
|
||||
undefined,
|
||||
[],
|
||||
undefined,
|
||||
ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken),
|
||||
ts.factory.createBlock(
|
||||
[ts.factory.createExpressionStatement(node)],
|
||||
true
|
||||
)
|
||||
)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
function validatePropertyAccessExpressionWithCustomBuilder(node: ts.Node): boolean {
|
||||
return ts.isPropertyAccessExpression(node) && node.name &&
|
||||
ts.isIdentifier(node.name) && CUSTOM_BUILDER_PROPERTIES.has(node.name.escapedText.toString());
|
||||
}
|
||||
|
||||
function validateIdentifierWithCustomBuilder(node: ts.Node): boolean {
|
||||
return ts.isIdentifier(node) && CUSTOM_BUILDER_PROPERTIES.has(node.escapedText.toString());
|
||||
}
|
||||
|
||||
function createArrowFunctionFor$$($$varExp: ts.Expression): ts.ArrowFunction {
|
||||
return ts.factory.createArrowFunction(
|
||||
undefined, undefined,
|
||||
@@ -561,8 +691,8 @@ function createArrowFunctionFor$$($$varExp: ts.Expression): ts.ArrowFunction {
|
||||
|
||||
function updateArgumentFor$$(argument: any): ts.Expression {
|
||||
if (ts.isElementAccessExpression(argument)) {
|
||||
return ts.factory.updateElementAccessExpression
|
||||
(argument, updateArgumentFor$$(argument.expression), argument.argumentExpression);
|
||||
return ts.factory.updateElementAccessExpression(
|
||||
argument, updateArgumentFor$$(argument.expression), argument.argumentExpression);
|
||||
} else if (ts.isIdentifier(argument)) {
|
||||
props.push(argument.getText());
|
||||
if (argument.getText() === $$_THIS) {
|
||||
@@ -571,8 +701,8 @@ function updateArgumentFor$$(argument: any): ts.Expression {
|
||||
return ts.factory.createIdentifier(argument.getText().replace(/\$\$/, ''));
|
||||
}
|
||||
} else if (ts.isPropertyAccessExpression(argument)) {
|
||||
return ts.factory.updatePropertyAccessExpression
|
||||
(argument, updateArgumentFor$$(argument.expression), argument.name);
|
||||
return ts.factory.updatePropertyAccessExpression(
|
||||
argument, updateArgumentFor$$(argument.expression), argument.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,8 +836,8 @@ function traverseStateStylesAttr(temp: any, statements: ts.Statement[],
|
||||
} else if (ts.isObjectLiteralExpression(item.initializer) &&
|
||||
item.initializer.properties.length === 1 &&
|
||||
ts.isPropertyAssignment(item.initializer.properties[0])) {
|
||||
bindComponentAttr(ts.factory.createExpressionStatement
|
||||
(item.initializer.properties[0].initializer), identifierNode, statements, log, false, true);
|
||||
bindComponentAttr(ts.factory.createExpressionStatement(
|
||||
item.initializer.properties[0].initializer), identifierNode, statements, log, false, true);
|
||||
} else {
|
||||
validateStateStyleSyntax(temp, log);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,6 @@ import {
|
||||
COMPONENT_TRANSITION_FUNCTION,
|
||||
COMPONENT_CREATE_FUNCTION,
|
||||
GEOMETRY_VIEW,
|
||||
BUILDER_ATTR_NAME,
|
||||
BUILDER_ATTR_BIND,
|
||||
COMPONENT_STYLES_DECORATOR,
|
||||
STYLES,
|
||||
INTERFACE_NAME_SUFFIX,
|
||||
@@ -290,8 +288,7 @@ function processBuildMember(node: ts.MethodDeclaration, context: ts.Transformati
|
||||
});
|
||||
}
|
||||
const buildNode: ts.MethodDeclaration = processComponentBuild(node, log);
|
||||
const firstParseBuildNode = ts.visitNode(buildNode, visitBuild);
|
||||
return ts.visitNode(firstParseBuildNode, visitBuildSecond);
|
||||
return ts.visitNode(buildNode, visitBuild);
|
||||
function visitBuild(node: ts.Node): ts.Node {
|
||||
if (isGeometryView(node)) {
|
||||
node = processGeometryView(node as ts.ExpressionStatement, log);
|
||||
@@ -309,90 +306,6 @@ function processBuildMember(node: ts.MethodDeclaration, context: ts.Transformati
|
||||
}
|
||||
return ts.visitEachChild(node, visitBuild, context);
|
||||
}
|
||||
function visitBuildSecond(node: ts.Node): ts.Node {
|
||||
if (isCustomComponentNode(node) || isCustomBuilderNode(node)) {
|
||||
return node;
|
||||
}
|
||||
if ((ts.isIdentifier(node) || ts.isPropertyAccessExpression(node)) &&
|
||||
validateBuilderFunctionNode(node)) {
|
||||
return getParsedBuilderAttrArgument(node);
|
||||
}
|
||||
return ts.visitEachChild(node, visitBuildSecond, context);
|
||||
}
|
||||
}
|
||||
|
||||
function validateBuilderFunctionNode(node: ts.PropertyAccessExpression | ts.Identifier): boolean {
|
||||
if ((ts.isPropertyAccessExpression(node) && node.expression && node.name &&
|
||||
node.expression.kind === ts.SyntaxKind.ThisKeyword && ts.isIdentifier(node.name) &&
|
||||
CUSTOM_BUILDER_METHOD.has(node.name.escapedText.toString()) ||
|
||||
ts.isIdentifier(node) && CUSTOM_BUILDER_METHOD.has(node.escapedText.toString())) &&
|
||||
!(ts.isPropertyAccessExpression(node) && validateBuilderParam(node) ||
|
||||
ts.isIdentifier(node) && node.parent && ts.isPropertyAccessExpression(node.parent) &&
|
||||
validateBuilderParam(node.parent))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function validateBuilderParam(node: ts.PropertyAccessExpression): boolean {
|
||||
if (node.parent && ts.isCallExpression(node.parent) && node.parent.expression === node) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getParsedBuilderAttrArgument(node: ts.PropertyAccessExpression | ts.Identifier):
|
||||
ts.ObjectLiteralExpression {
|
||||
let newObjectNode: ts.ObjectLiteralExpression = null;
|
||||
if (ts.isPropertyAccessExpression(node)) {
|
||||
newObjectNode = ts.factory.createObjectLiteralExpression([
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_NAME),
|
||||
ts.factory.createCallExpression(
|
||||
ts.factory.createPropertyAccessExpression(
|
||||
node,
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_BIND)
|
||||
),
|
||||
undefined,
|
||||
[ts.factory.createThis()]
|
||||
)
|
||||
)
|
||||
]);
|
||||
} else if (ts.isIdentifier(node)) {
|
||||
newObjectNode = ts.factory.createObjectLiteralExpression([
|
||||
ts.factory.createPropertyAssignment(
|
||||
ts.factory.createIdentifier(BUILDER_ATTR_NAME),
|
||||
node
|
||||
)
|
||||
]);
|
||||
}
|
||||
return newObjectNode;
|
||||
}
|
||||
|
||||
function isCustomComponentNode(node:ts.NewExpression | ts.ExpressionStatement): boolean {
|
||||
if (ts.isNewExpression(node) && ts.isIdentifier(node.expression) && node.expression.escapedText
|
||||
&& componentCollection.customComponents.has(node.expression.escapedText.toString()) ||
|
||||
// @ts-ignore
|
||||
ts.isExpressionStatement(node) && node.expression && node.expression.expression &&
|
||||
// @ts-ignore
|
||||
node.expression.expression.expression && node.expression.expression.expression.escapedText &&
|
||||
// @ts-ignore
|
||||
node.expression.expression.expression.escapedText.toString().startsWith(
|
||||
CUSTOM_COMPONENT_EARLIER_CREATE_CHILD)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isCustomBuilderNode(node: ts.ExpressionStatement): boolean {
|
||||
return ts.isExpressionStatement(node) && node.expression &&
|
||||
// @ts-ignore
|
||||
node.expression.expression && node.expression.expression.escapedText &&
|
||||
// @ts-ignore
|
||||
CUSTOM_BUILDER_METHOD.has(node.expression.expression.escapedText.toString());
|
||||
}
|
||||
|
||||
function isGeometryView(node: ts.Node): boolean {
|
||||
|
||||
@@ -41,10 +41,10 @@ import {
|
||||
COMPONENT_CONSTRUCTOR_ID,
|
||||
COMPONENT_CONSTRUCTOR_PARENT,
|
||||
COMPONENT_CONSTRUCTOR_PARAMS,
|
||||
COMPONENT_EXTEND_DECORATOR,
|
||||
COMPONENT_OBSERVED_DECORATOR,
|
||||
STYLES,
|
||||
VALIDATE_MODULE
|
||||
VALIDATE_MODULE,
|
||||
COMPONENT_BUILDER_DECORATOR
|
||||
} from './pre_define';
|
||||
import {
|
||||
INNER_COMPONENT_NAMES,
|
||||
@@ -54,7 +54,8 @@ import {
|
||||
BUILDIN_STYLE_NAMES,
|
||||
EXTEND_ATTRIBUTE,
|
||||
GLOBAL_STYLE_FUNCTION,
|
||||
STYLES_ATTRIBUTE
|
||||
STYLES_ATTRIBUTE,
|
||||
CUSTOM_BUILDER_METHOD
|
||||
} from './component_map';
|
||||
import {
|
||||
LogType,
|
||||
@@ -324,6 +325,9 @@ function visitAllNode(node: ts.Node, sourceFileNode: ts.SourceFile, allComponent
|
||||
if (ts.isClassDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
|
||||
collectComponentProps(node);
|
||||
}
|
||||
if (ts.isMethodDeclaration(node) && hasDecorator(node, COMPONENT_BUILDER_DECORATOR)) {
|
||||
CUSTOM_BUILDER_METHOD.add(node.name.getText());
|
||||
}
|
||||
node.getChildren().forEach((item: ts.Node) => visitAllNode(item, sourceFileNode, allComponentNames, log));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
exports.source = `
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Banner {
|
||||
@Builder textBuilder() {
|
||||
Text("文本")
|
||||
.fontSize(30)
|
||||
}
|
||||
@Builder NavigationTitle(label:string) {
|
||||
Column() {
|
||||
Text(label)
|
||||
.width(10)
|
||||
.bindMenu(this.textBuilder)
|
||||
}
|
||||
}
|
||||
build() {
|
||||
Column() {
|
||||
Text("111")
|
||||
.bindMenu(this.NavigationTitle("111"))
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
exports.expectResult =
|
||||
`class Banner extends View {
|
||||
constructor(compilerAssignedUniqueChildId, parent, params) {
|
||||
super(compilerAssignedUniqueChildId, parent);
|
||||
this.updateWithValueParams(params);
|
||||
}
|
||||
updateWithValueParams(params) {
|
||||
}
|
||||
aboutToBeDeleted() {
|
||||
SubscriberManager.Get().delete(this.id());
|
||||
}
|
||||
textBuilder() {
|
||||
Text.create("文本");
|
||||
Text.fontSize(30);
|
||||
Text.pop();
|
||||
}
|
||||
NavigationTitle(label) {
|
||||
Column.create();
|
||||
Text.create(label);
|
||||
Text.width(10);
|
||||
Text.bindMenu({ builder: this.textBuilder.bind(this) });
|
||||
Text.pop();
|
||||
Column.pop();
|
||||
}
|
||||
render() {
|
||||
Column.create();
|
||||
Text.create("111");
|
||||
Text.bindMenu({ builder: () => {
|
||||
this.NavigationTitle("111");
|
||||
} });
|
||||
Text.pop();
|
||||
Column.pop();
|
||||
}
|
||||
}
|
||||
loadDocument(new Banner("1", undefined, {}));
|
||||
`
|
||||
Reference in New Issue
Block a user