Signed-off-by: BoJiang <jiangbo91@huawei.com>
Change-Id: Ia67bf7d6aa7f2dddd71939c777a06c33e623e77c
This commit is contained in:
BoJiang 2024-07-18 17:10:43 +08:00
parent a51310d173
commit 25b0bf0531
7 changed files with 253 additions and 3 deletions

View File

@ -549,7 +549,7 @@ export function processComponentMethod(node: ts.MethodDeclaration, context: ts.T
const builderCondition: builderConditionType = {
isBuilder: false,
isLocalBuilder: false
}
};
if (builderParamObjectCollection.get(componentCollection.currentClassName)) {
storedFileInfo.builderLikeCollection =
new Set([...builderParamObjectCollection.get(componentCollection.currentClassName), ...CUSTOM_BUILDER_METHOD]);
@ -603,6 +603,7 @@ export function processComponentMethod(node: ts.MethodDeclaration, context: ts.T
builderTypeParameter.params = [];
updateItem = processBuildMember(builderNode, context, log, true);
if (builderCondition.isLocalBuilder) {
checkDecoratorMethod(node, modifiers, log);
updateItem = localBuilderNode(node, updateItem.body);
}
storedFileInfo.processBuilder = false;
@ -628,6 +629,21 @@ export function processComponentMethod(node: ts.MethodDeclaration, context: ts.T
return updateItem;
}
function checkDecoratorMethod(node: ts.MethodDeclaration, modifiers: readonly ts.Modifier[], log: LogInfo[]): void {
if (modifiers && modifiers.length) {
for (let i = 0; i < modifiers.length; i++) {
if (modifiers[i].kind && modifiers[i].kind === ts.SyntaxKind.StaticKeyword) {
log.push({
type: LogType.ERROR,
message: `Static methods in custom components cannot be decorated by @LocalBuilder.`,
pos: node.getStart()
});
return;
}
}
}
}
function isBuilderOrLocalBuilder(node: ts.MethodDeclaration, builderCondition: builderConditionType, customBuilder: ts.Decorator[]): boolean {
const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node);
if (decorators && decorators.length) {

View File

@ -456,7 +456,7 @@ export function globalBuilderParamAssignment(): ts.VariableStatement {
ts.factory.createIdentifier(LENGTH)
),
ts.factory.createToken(ts.SyntaxKind.MinusToken),
ts.factory.createNumericLiteral("1")
ts.factory.createNumericLiteral('1')
)
),
ts.factory.createToken(ts.SyntaxKind.ColonToken),

View File

@ -717,6 +717,24 @@
"type": "ERROR"
}
],
"@localBuilder": [
{
"message": "'@LocalBuilder' can only decorate method.",
"type": "ERROR"
},
{
"message": "The member property or method can not be decorated by multiple built-in decorators.",
"type": "ERROR"
},
{
"message": "Static methods in custom components cannot be decorated by @LocalBuilder.",
"type": "ERROR"
},
{
"message": "'xx();' does not meet UI component syntax.",
"type": "ERROR"
}
],
"v1ToV2Component.ts": [],
"v1ToV2ComponentValidate": [],
"v2ToV1ComponentValidate": [],

View File

@ -46,6 +46,9 @@ exports.expectResult =
if (!("finalizeConstruction" in ViewPU.prototype)) {
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
if (PUV2ViewBase.contextStack === undefined) {
Reflect.set(PUV2ViewBase, "contextStack", []);
}
const test_value = "hello";
class testDemo extends ViewPU {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
@ -67,6 +70,7 @@ class testDemo extends ViewPU {
this.aboutToBeDeletedInternal();
}
initialRender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
@ -76,11 +80,14 @@ class testDemo extends ViewPU {
Text.fontWeight(FontWeight.Bold);
}, Text);
Text.pop();
overBuilder.bind(this)(makeBuilderParameterProxy("overBuilder", { test_value: () => test_value }), this);
overBuilder.bind(this)(makeBuilderParameterProxy("overBuilder", { test_value: () => test_value }));
Column.pop();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
rerender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.updateDirtyElements();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
}
function overBuilder($$, parent = null) {

View File

@ -0,0 +1,163 @@
/*
* Copyright (c) 2022 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 = `
class Tmp {
paramA1: string = ''
}
@Entry
@Component
struct HomeComponent {
@State label: string = 'Hello';
@LocalBuilder xx($$: Tmp, aa: string = '1') {
Chind({message: $$.paramA1})
}
build() {
Column() {
this.xx({paramA1: this.label});
}
.height(500)
}
}
@Component
struct Chind {
@Link message: string;
build() {
}
}
`
exports.expectResult =
`"use strict";
if (!("finalizeConstruction" in ViewPU.prototype)) {
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
if (PUV2ViewBase.contextStack === undefined) {
Reflect.set(PUV2ViewBase, "contextStack", []);
}
class Tmp {
constructor() {
this.paramA1 = '';
}
}
class HomeComponent extends ViewPU {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
super(parent, __localStorage, elmtId, extraInfo);
this.xx = ($$, aa = '1') => {
const parent = PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.length ? PUV2ViewBase.contextStack[PUV2ViewBase.contextStack.length - 1] : null;
{
this.observeComponentCreation2((elmtId, isInitialRender) => {
if (isInitialRender) {
let componentCall = new Chind(parent ? parent : this, { message: $$.__paramA1 }, undefined, elmtId, () => { }, { page: "@localBuilder.ets", line: 11, col: 5 });
ViewPU.create(componentCall);
let paramsLambda = () => {
return {
message: $$.paramA1
};
};
componentCall.paramsGenerator_ = paramsLambda;
}
else {
this.updateStateVarsOfChildByElmtId(elmtId, {});
}
}, { name: "Chind" });
}
};
if (typeof paramsLambda === "function") {
this.paramsGenerator_ = paramsLambda;
}
this.__label = new ObservedPropertySimplePU('Hello', this, "label");
this.setInitiallyProvidedValue(params);
this.finalizeConstruction();
}
setInitiallyProvidedValue(params) {
if (params.label !== undefined) {
this.label = params.label;
}
}
updateStateVars(params) {
}
purgeVariableDependenciesOnElmtId(rmElmtId) {
this.__label.purgeDependencyOnElmtId(rmElmtId);
}
aboutToBeDeleted() {
this.__label.aboutToBeDeleted();
SubscriberManager.Get().delete(this.id__());
this.aboutToBeDeletedInternal();
}
get label() {
return this.__label.get();
}
set label(newValue) {
this.__label.set(newValue);
}
initialRender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
Column.height(500);
}, Column);
this.xx.bind(this)(makeBuilderParameterProxy("xx", { paramA1: () => (this["__label"] ? this["__label"] : this["label"]) }));
Column.pop();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
rerender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.updateDirtyElements();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
}
class Chind extends ViewPU {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
super(parent, __localStorage, elmtId, extraInfo);
if (typeof paramsLambda === "function") {
this.paramsGenerator_ = paramsLambda;
}
this.__message = new SynchedPropertySimpleTwoWayPU(params.message, this, "message");
this.setInitiallyProvidedValue(params);
this.finalizeConstruction();
}
setInitiallyProvidedValue(params) {
}
updateStateVars(params) {
}
purgeVariableDependenciesOnElmtId(rmElmtId) {
this.__message.purgeDependencyOnElmtId(rmElmtId);
}
aboutToBeDeleted() {
this.__message.aboutToBeDeleted();
SubscriberManager.Get().delete(this.id__());
this.aboutToBeDeletedInternal();
}
get message() {
return this.__message.get();
}
set message(newValue) {
this.__message.set(newValue);
}
initialRender() {
}
rerender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.updateDirtyElements();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
}
ViewStackProcessor.StartGetAccessRecordingFor(ViewStackProcessor.AllocateNewElmetIdForNextComponent());
loadDocument(new HomeComponent(undefined, {}));
ViewStackProcessor.StopGetAccessRecording();
`

View File

@ -61,19 +61,26 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
if (!("finalizeConstruction" in ViewPU.prototype)) {
Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
if (PUV2ViewBase.contextStack === undefined) {
Reflect.set(PUV2ViewBase, "contextStack", []);
}
class HomeComponent extends ViewV2 {
constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
super(parent, elmtId, extraInfo);
this.finalizeConstruction();
}
initialRender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
Column.pop();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
rerender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.updateDirtyElements();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
static getEntryName() {
return "HomeComponent";
@ -95,13 +102,17 @@ class ChildComponent extends ViewV2 {
return ChildComponent.param_value;
}
initialRender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.observeComponentCreation2((elmtId, isInitialRender) => {
Column.create();
}, Column);
Column.pop();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
rerender() {
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.push(this);
this.updateDirtyElements();
PUV2ViewBase.contextStack && PUV2ViewBase.contextStack.pop();
}
}
ChildComponent.local_value = "hello";

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2024 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 = `
@LocalBuilder function xx() {
}
@Entry
@Component
struct HomeComponent {
@LocalBuilder static bb() {
}
@Builder @LocalBuilder dd() {
}
build() {
Column() {
xx();
}
.height(500)
}
}`