mirror of
https://gitee.com/openharmony/developtools_ace_ets2bundle
synced 2024-11-23 00:19:53 +00:00
update validate for struct/@BuilderParam. Signed-off-by: lihong <lihong67@huawei.com> Change-Id: Ia9af1515366f7f49507d8fc9f6a6e5994f0d50f5
This commit is contained in:
parent
228411823f
commit
0affaba063
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,6 +6,7 @@ compiler/declarations/
|
||||
compiler/sample/build/
|
||||
compiler/component_config.json
|
||||
compiler/form_config.json
|
||||
compiler/build_config.json
|
||||
compiler/syntax_parser/dist/
|
||||
compiler/.nyc_output
|
||||
compiler/.test_output
|
||||
|
11
BUILD.gn
11
BUILD.gn
@ -31,6 +31,9 @@ ets_loader_component_config_file =
|
||||
ets_loader_form_config_file =
|
||||
get_label_info(":build_ets_loader_library", "target_out_dir") +
|
||||
"/form_config.json"
|
||||
ets_loader_build_config_file =
|
||||
get_label_info(":build_ets_loader_library", "target_out_dir") +
|
||||
"/build_config.json"
|
||||
ets_sysResource = get_label_info(":build_ets_sysResource", "target_out_dir") +
|
||||
"/sysResource.js"
|
||||
ets_loader_kit_configs_dir = get_label_info(":build_ets_loader_library",
|
||||
@ -51,6 +54,7 @@ action("build_ets_loader_library") {
|
||||
ets_loader_component_config_file,
|
||||
ets_loader_form_config_file,
|
||||
ets_loader_kit_configs_dir,
|
||||
ets_loader_build_config_file,
|
||||
]
|
||||
|
||||
_ets_loader_dir = "compiler"
|
||||
@ -114,6 +118,8 @@ action("build_ets_loader_library") {
|
||||
rebase_path(ets_loader_component_config_file, root_build_dir),
|
||||
"--output-form-config-file",
|
||||
rebase_path(ets_loader_form_config_file, root_build_dir),
|
||||
"--output-build-config-file",
|
||||
rebase_path(ets_loader_build_config_file, root_build_dir),
|
||||
"--kit-configs-file-dir",
|
||||
rebase_path(_kit_configs_file_dir, root_build_dir),
|
||||
"--build-kit-configs-file-js",
|
||||
@ -177,7 +183,10 @@ ohos_copy("ets_loader") {
|
||||
|
||||
ohos_copy("ets_loader_component_config") {
|
||||
deps = [ ":build_ets_loader_library" ]
|
||||
sources = [ ets_loader_component_config_file ]
|
||||
sources = [
|
||||
ets_loader_build_config_file,
|
||||
ets_loader_component_config_file,
|
||||
]
|
||||
|
||||
outputs = [ target_out_dir + "/$target_name/{{source_file_part}}" ]
|
||||
module_source_dir = target_out_dir + "/$target_name"
|
||||
|
@ -52,6 +52,8 @@ def parse_args():
|
||||
help='path component config file to output')
|
||||
parser.add_argument('--output-form-config-file',
|
||||
help='path form config file to output')
|
||||
parser.add_argument('--output-build-config-file',
|
||||
help='path form config file to output')
|
||||
parser.add_argument('--kit-configs-file-dir',
|
||||
help='path kit configs file')
|
||||
parser.add_argument('--build-kit-configs-file-js',
|
||||
@ -115,6 +117,7 @@ def main():
|
||||
options.output_declarations_dir,
|
||||
options.output_component_config_file,
|
||||
options.output_form_config_file,
|
||||
options.output_build_config_file,
|
||||
options.output_kit_configs_dir]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -221,11 +221,19 @@ generateComponentConfig(process.argv[4], process.argv[5]);
|
||||
function generateComponentConfig(dir, buildPublicSDK) {
|
||||
const configFile = path.resolve(dir, 'component_map.js');
|
||||
if (fs.existsSync(configFile)) {
|
||||
const { COMPONENT_MAP, FORM_MAP } = require(configFile);
|
||||
const { COMPONENT_MAP, FORM_MAP, forbiddenUseStateType } = require(configFile);
|
||||
const buildConfig = {
|
||||
forbiddenUseStateTypeForDecorators: [
|
||||
'@State', '@Prop', '@Link', '@Provide', '@Consume', '@ObjectLink', '@BuilderParam',
|
||||
'@LocalStorageLink', '@LocalStorageProp', '@StorageLink', '@StorageProp'
|
||||
],
|
||||
forbiddenUseStateType: [...forbiddenUseStateType]
|
||||
};
|
||||
try {
|
||||
removeSystemApiComp(buildPublicSDK, COMPONENT_MAP, FORM_MAP);
|
||||
fs.writeFileSync(path.resolve(dir, '../component_config.json'), JSON.stringify(COMPONENT_MAP));
|
||||
fs.writeFileSync(path.resolve(dir, '../form_config.json'), JSON.stringify(FORM_MAP));
|
||||
fs.writeFileSync(path.resolve(dir, '../build_config.json'), JSON.stringify(buildConfig));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
@ -122,7 +122,8 @@ export const XCOMPONENTTYPE: string = 'XComponentType';
|
||||
export const XCOMPONENTTYPE_CONTAINER: string = 'COMPONENT';
|
||||
export const COMPONENT_DECORATOR_NAME_CUSTOMDIALOG: string = 'CustomDialog';
|
||||
export const CUSTOM_DECORATOR_NAME: Set<string> = new Set([
|
||||
COMPONENT_DECORATOR_NAME_COMPONENT, COMPONENT_DECORATOR_NAME_CUSTOMDIALOG
|
||||
COMPONENT_DECORATOR_NAME_COMPONENT, COMPONENT_DECORATOR_NAME_CUSTOMDIALOG,
|
||||
DECORATOR_REUSEABLE, 'Entry', 'Preview'
|
||||
]);
|
||||
|
||||
export const EXTNAME_ETS: string = '.ets';
|
||||
|
@ -872,6 +872,7 @@ function setComponentCollectionInfo(name: string, componentSet: IComponentSet, i
|
||||
|
||||
function parseComponentInImportNode(originNode: ts.StructDeclaration, name: string,
|
||||
asComponentName: string, structDecorator: structDecoratorResult, originFile: string): void {
|
||||
componentCollection.customComponents.add(name);
|
||||
const structInfo: StructInfo = asComponentName ?
|
||||
processStructComponentV2.getOrCreateStructInfo(asComponentName) :
|
||||
processStructComponentV2.getOrCreateStructInfo(name);
|
||||
@ -900,7 +901,6 @@ function parseComponentInImportNode(originNode: ts.StructDeclaration, name: stri
|
||||
function parseComponentV2InImportNode(node: ts.StructDeclaration, name: string, originFile: string,
|
||||
structInfo: StructInfo): void {
|
||||
structInfo.isComponentV2 = true;
|
||||
componentCollection.customComponents.add(name);
|
||||
const isDETS: boolean = originFile && /\.d\.ets$/.test(originFile);
|
||||
if (isDETS) {
|
||||
storedFileInfo.getCurrentArkTsFile().compFromDETS.add(name);
|
||||
|
@ -240,12 +240,14 @@ function checkComponentDecorator(source: string, filePath: string,
|
||||
function validateStructSpec(item: ts.StructDeclaration, result: DecoratorResult, log: LogInfo[],
|
||||
sourceFile: ts.SourceFile | null): void {
|
||||
if (item.name && ts.isIdentifier(item.name)) {
|
||||
const componentName: string = item.name.getText();
|
||||
componentCollection.customComponents.add(componentName);
|
||||
const decorators: readonly ts.Decorator[] = ts.getAllDecorators(item);
|
||||
if (decorators && decorators.length) {
|
||||
checkDecorators(decorators, result, item.name, log, sourceFile, item);
|
||||
} else {
|
||||
const message: string = `A struct should use decorator '@Component' or '@ComponentV2'.`;
|
||||
addLog(LogType.WARN, message, item.getStart(), log, sourceFile);
|
||||
const message: string = `Decorator '@Component', '@ComponentV2', or '@CustomDialog' is missing for struct '${componentName}'.`;
|
||||
addLog(LogType.ERROR, message, item.getStart(), log, sourceFile);
|
||||
}
|
||||
} else {
|
||||
const message: string = `A struct must have a name.`;
|
||||
@ -309,16 +311,16 @@ interface DecoratorResult {
|
||||
|
||||
function checkDecorators(decorators: readonly ts.Decorator[], result: DecoratorResult,
|
||||
component: ts.Identifier, log: LogInfo[], sourceFile: ts.SourceFile, node: ts.StructDeclaration): void {
|
||||
let hasComponentDecorator: boolean = false;
|
||||
const componentName: string = component.getText();
|
||||
const structInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(componentName);
|
||||
let hasInnerComponentDecorator: boolean = false;
|
||||
decorators.forEach((element) => {
|
||||
let name: string = element.getText().replace(/\([^\(\)]*\)/, '').trim();
|
||||
if (element.expression && element.expression.expression && ts.isIdentifier(element.expression.expression)) {
|
||||
name = '@' + element.expression.expression.getText();
|
||||
}
|
||||
if (INNER_COMPONENT_DECORATORS.has(name)) {
|
||||
componentCollection.customComponents.add(componentName);
|
||||
hasInnerComponentDecorator = true;
|
||||
switch (name) {
|
||||
case COMPONENT_DECORATOR_ENTRY:
|
||||
checkEntryComponent(node, log, sourceFile);
|
||||
@ -332,21 +334,17 @@ function checkDecorators(decorators: readonly ts.Decorator[], result: DecoratorR
|
||||
componentCollection.previewComponent.push(componentName);
|
||||
break;
|
||||
case COMPONENT_DECORATOR_COMPONENT_V2:
|
||||
hasComponentDecorator = true;
|
||||
structInfo.isComponentV2 = true;
|
||||
break;
|
||||
case COMPONENT_DECORATOR_COMPONENT:
|
||||
hasComponentDecorator = true;
|
||||
structInfo.isComponentV1 = true;
|
||||
break;
|
||||
case COMPONENT_DECORATOR_CUSTOM_DIALOG:
|
||||
componentCollection.customDialogs.add(componentName);
|
||||
hasComponentDecorator = true;
|
||||
structInfo.isCustomDialog = true;
|
||||
break;
|
||||
case COMPONENT_DECORATOR_REUSEABLE:
|
||||
storedFileInfo.getCurrentArkTsFile().recycleComponents.add(componentName);
|
||||
hasComponentDecorator = true;
|
||||
structInfo.isReusable = true;
|
||||
break;
|
||||
}
|
||||
@ -354,7 +352,7 @@ function checkDecorators(decorators: readonly ts.Decorator[], result: DecoratorR
|
||||
validateInvalidStructDecorator(element, componentName, log, sourceFile);
|
||||
}
|
||||
});
|
||||
validateStruct(hasComponentDecorator, componentName, component, log, sourceFile, structInfo);
|
||||
validateStruct(hasInnerComponentDecorator, componentName, component, log, sourceFile, structInfo);
|
||||
}
|
||||
|
||||
function validateInvalidStructDecorator(element: ts.Decorator, componentName: string, log: LogInfo[],
|
||||
@ -364,11 +362,11 @@ function validateInvalidStructDecorator(element: ts.Decorator, componentName: st
|
||||
addLog(LogType.WARN, message, pos, log, sourceFile);
|
||||
}
|
||||
|
||||
function validateStruct(hasComponentDecorator: boolean, componentName: string, component: ts.Identifier,
|
||||
function validateStruct(hasInnerComponentDecorator: boolean, componentName: string, component: ts.Identifier,
|
||||
log: LogInfo[], sourceFile: ts.SourceFile, structInfo: StructInfo): void {
|
||||
if (!hasComponentDecorator) {
|
||||
const message: string = `The struct '${componentName}' should use decorator '@Component'.`;
|
||||
addLog(LogType.WARN, message, component.pos, log, sourceFile);
|
||||
if (!hasInnerComponentDecorator) {
|
||||
const message: string = `Decorator '@Component', '@ComponentV2', or '@CustomDialog' is missing for struct '${componentName}'.`;
|
||||
addLog(LogType.ERROR, message, component.pos, log, sourceFile);
|
||||
} else if (structInfo.isComponentV2 && (structInfo.isComponentV1 || structInfo.isReusable || structInfo.isCustomDialog) ) {
|
||||
const message: string = `The struct '${componentName}' can not be decorated with '@ComponentV2' ` +
|
||||
`and '@Component', '@Reusable', '@CustomDialog' at the same time.`;
|
||||
@ -437,10 +435,6 @@ function checkUISyntax(filePath: string, allComponentNames: Set<string>, content
|
||||
visitAllNode(sourceFile, sourceFile, allComponentNames, log, false, false, false, false, fileQuery);
|
||||
}
|
||||
|
||||
function propertyInitializeInEntry(fileQuery: string, name: string): boolean {
|
||||
return fileQuery === '?entry' && name === componentCollection.entryComponent;
|
||||
}
|
||||
|
||||
function visitAllNode(node: ts.Node, sourceFileNode: ts.SourceFile, allComponentNames: Set<string>,
|
||||
log: LogInfo[], structContext: boolean, classContext: boolean, isObservedClass: boolean,
|
||||
isComponentV2: boolean, fileQuery: string): void {
|
||||
@ -452,7 +446,7 @@ function visitAllNode(node: ts.Node, sourceFileNode: ts.SourceFile, allComponent
|
||||
processStructComponentV2.parseComponentProperty(node, structInfo, log, sourceFileNode);
|
||||
isComponentV2 = true;
|
||||
} else {
|
||||
collectComponentProps(node, propertyInitializeInEntry(fileQuery, structName), structInfo);
|
||||
collectComponentProps(node, structInfo);
|
||||
}
|
||||
}
|
||||
if (ts.isClassDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
|
||||
@ -1093,10 +1087,9 @@ function isNonspecificChildIfStatement(node: ts.Node, specificChildSet: Set<stri
|
||||
return false;
|
||||
}
|
||||
|
||||
function collectComponentProps(node: ts.StructDeclaration, judgeInitializeInEntry: boolean,
|
||||
structInfo: StructInfo): void {
|
||||
function collectComponentProps(node: ts.StructDeclaration, structInfo: StructInfo): void {
|
||||
const componentName: string = node.name.getText();
|
||||
const componentSet: IComponentSet = getComponentSet(node, judgeInitializeInEntry, true);
|
||||
const componentSet: IComponentSet = getComponentSet(node, true);
|
||||
propertyCollection.set(componentName, componentSet.properties);
|
||||
stateCollection.set(componentName, componentSet.states);
|
||||
linkCollection.set(componentName, componentSet.links);
|
||||
@ -1124,10 +1117,9 @@ function collectComponentProps(node: ts.StructDeclaration, judgeInitializeInEntr
|
||||
);
|
||||
}
|
||||
|
||||
export function getComponentSet(node: ts.StructDeclaration, judgeInitializeInEntry: boolean,
|
||||
uiCheck: boolean = false): IComponentSet {
|
||||
export function getComponentSet(node: ts.StructDeclaration, uiCheck: boolean = false): IComponentSet {
|
||||
const componentSet: IComponentSet = new IComponentSet();
|
||||
traversalComponentProps(node, judgeInitializeInEntry, componentSet, uiCheck);
|
||||
traversalComponentProps(node, componentSet, uiCheck);
|
||||
return componentSet;
|
||||
}
|
||||
|
||||
@ -1140,8 +1132,8 @@ class RecordRequire {
|
||||
hasProvide: boolean = false;
|
||||
}
|
||||
|
||||
function traversalComponentProps(node: ts.StructDeclaration, judgeInitializeInEntry: boolean,
|
||||
componentSet: IComponentSet, uiCheck: boolean = false): void {
|
||||
function traversalComponentProps(node: ts.StructDeclaration, componentSet: IComponentSet,
|
||||
uiCheck: boolean = false): void {
|
||||
let isStatic: boolean = true;
|
||||
if (node.members) {
|
||||
const currentMethodCollection: Set<string> = new Set();
|
||||
@ -1162,7 +1154,7 @@ function traversalComponentProps(node: ts.StructDeclaration, judgeInitializeInEn
|
||||
const decoratorName: string = decorators[i].getText().replace(/\(.*\)$/, '').trim();
|
||||
if (INNER_COMPONENT_MEMBER_DECORATORS.has(decoratorName)) {
|
||||
dollarCollection.add('$' + propertyName);
|
||||
collectionStates(decorators[i], judgeInitializeInEntry, decoratorName, propertyName,
|
||||
collectionStates(decorators[i], decoratorName, propertyName,
|
||||
componentSet, recordRequire);
|
||||
setPrivateCollection(componentSet, accessQualifierResult, propertyName, decoratorName);
|
||||
validateAccessQualifier(item, propertyName, decoratorName, accessQualifierResult,
|
||||
@ -1300,7 +1292,7 @@ function setInitValue(requirekey: string, initKey: string, name: string, compone
|
||||
}
|
||||
}
|
||||
|
||||
function collectionStates(node: ts.Decorator, judgeInitializeInEntry: boolean, decorator: string, name: string,
|
||||
function collectionStates(node: ts.Decorator, decorator: string, name: string,
|
||||
componentSet: IComponentSet, recordRequire: RecordRequire): void {
|
||||
switch (decorator) {
|
||||
case COMPONENT_STATE_DECORATOR:
|
||||
@ -1331,9 +1323,6 @@ function collectionStates(node: ts.Decorator, judgeInitializeInEntry: boolean, d
|
||||
componentSet.objectLinks.add(name);
|
||||
break;
|
||||
case COMPONENT_BUILDERPARAM_DECORATOR:
|
||||
if (judgeInitializeInEntry) {
|
||||
validateInitializeInEntry(node, name);
|
||||
}
|
||||
recordRequire.hasBuilderParam = true;
|
||||
componentSet.builderParams.add(name);
|
||||
break;
|
||||
@ -1349,14 +1338,6 @@ function collectionStates(node: ts.Decorator, judgeInitializeInEntry: boolean, d
|
||||
}
|
||||
}
|
||||
|
||||
function validateInitializeInEntry(node: ts.Decorator, name: string): void {
|
||||
transformLog.errors.push({
|
||||
type: LogType.WARN,
|
||||
message: `'${name}' should be initialized in @Entry Component`,
|
||||
pos: node.getStart()
|
||||
});
|
||||
}
|
||||
|
||||
function collectionlocalStorageParam(node: ts.Decorator, name: string,
|
||||
localStorage: Map<string, Set<string>>): void {
|
||||
const localStorageParam: Set<string> = new Set();
|
||||
|
@ -180,8 +180,8 @@
|
||||
"type": "ERROR"
|
||||
},
|
||||
"notComponent": {
|
||||
"message": "A struct should use decorator '@Component' or '@ComponentV2'.",
|
||||
"type": "WARN"
|
||||
"message": "Decorator '@Component', '@ComponentV2', or '@CustomDialog' is missing for struct 'EntryComponent'.",
|
||||
"type": "ERROR"
|
||||
},
|
||||
"notConcurrent": {
|
||||
"message": "The struct 'IndexDecorator' use invalid decorator.",
|
||||
@ -287,10 +287,6 @@
|
||||
"message": "'@State' can not decorate the method.",
|
||||
"type": "ERROR"
|
||||
},
|
||||
"BuilderParamNoInit": {
|
||||
"message": "'closer' should be initialized in @Entry Component",
|
||||
"type": "WARN"
|
||||
},
|
||||
"checkNonspecificParents": {
|
||||
"message": "The 'Blank' component can only be nested in the 'Row,Column,Flex' parent component.",
|
||||
"type": "ERROR"
|
||||
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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 sp {
|
||||
@BuilderParam closer:() => void;
|
||||
build() {
|
||||
}
|
||||
}
|
||||
`
|
Loading…
Reference in New Issue
Block a user