107ac75b1Sopenharmony_ci/* 207ac75b1Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License. 507ac75b1Sopenharmony_ci * You may obtain a copy of the License at 607ac75b1Sopenharmony_ci * 707ac75b1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 807ac75b1Sopenharmony_ci * 907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and 1307ac75b1Sopenharmony_ci * limitations under the License. 1407ac75b1Sopenharmony_ci */ 1507ac75b1Sopenharmony_ci 1607ac75b1Sopenharmony_ciimport ts from 'typescript'; 1707ac75b1Sopenharmony_ciimport path from 'path'; 1807ac75b1Sopenharmony_ci 1907ac75b1Sopenharmony_ciimport { 2007ac75b1Sopenharmony_ci INNER_COMPONENT_DECORATORS, 2107ac75b1Sopenharmony_ci COMPONENT_DECORATOR_ENTRY, 2207ac75b1Sopenharmony_ci COMPONENT_DECORATOR_PREVIEW, 2307ac75b1Sopenharmony_ci COMPONENT_DECORATOR_COMPONENT, 2407ac75b1Sopenharmony_ci COMPONENT_DECORATOR_CUSTOM_DIALOG, 2507ac75b1Sopenharmony_ci NATIVE_MODULE, 2607ac75b1Sopenharmony_ci SYSTEM_PLUGIN, 2707ac75b1Sopenharmony_ci OHOS_PLUGIN, 2807ac75b1Sopenharmony_ci INNER_COMPONENT_MEMBER_DECORATORS, 2907ac75b1Sopenharmony_ci COMPONENT_FOREACH, 3007ac75b1Sopenharmony_ci COMPONENT_LAZYFOREACH, 3107ac75b1Sopenharmony_ci COMPONENT_STATE_DECORATOR, 3207ac75b1Sopenharmony_ci COMPONENT_LINK_DECORATOR, 3307ac75b1Sopenharmony_ci COMPONENT_PROP_DECORATOR, 3407ac75b1Sopenharmony_ci COMPONENT_STORAGE_PROP_DECORATOR, 3507ac75b1Sopenharmony_ci COMPONENT_STORAGE_LINK_DECORATOR, 3607ac75b1Sopenharmony_ci COMPONENT_PROVIDE_DECORATOR, 3707ac75b1Sopenharmony_ci COMPONENT_CONSUME_DECORATOR, 3807ac75b1Sopenharmony_ci COMPONENT_OBJECT_LINK_DECORATOR, 3907ac75b1Sopenharmony_ci COMPONENT_OBSERVED_DECORATOR, 4007ac75b1Sopenharmony_ci COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, 4107ac75b1Sopenharmony_ci COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, 4207ac75b1Sopenharmony_ci COMPONENT_CONCURRENT_DECORATOR, 4307ac75b1Sopenharmony_ci CHECK_EXTEND_DECORATORS, 4407ac75b1Sopenharmony_ci COMPONENT_STYLES_DECORATOR, 4507ac75b1Sopenharmony_ci RESOURCE_NAME_TYPE, 4607ac75b1Sopenharmony_ci COMPONENT_BUTTON, 4707ac75b1Sopenharmony_ci COMPONENT_TOGGLE, 4807ac75b1Sopenharmony_ci COMPONENT_BUILDERPARAM_DECORATOR, 4907ac75b1Sopenharmony_ci ESMODULE, 5007ac75b1Sopenharmony_ci CARD_ENABLE_DECORATORS, 5107ac75b1Sopenharmony_ci CARD_LOG_TYPE_DECORATORS, 5207ac75b1Sopenharmony_ci JSBUNDLE, 5307ac75b1Sopenharmony_ci COMPONENT_DECORATOR_REUSEABLE, 5407ac75b1Sopenharmony_ci STRUCT_DECORATORS, 5507ac75b1Sopenharmony_ci STRUCT_CONTEXT_METHOD_DECORATORS, 5607ac75b1Sopenharmony_ci CHECK_COMPONENT_EXTEND_DECORATOR, 5707ac75b1Sopenharmony_ci CHECK_COMPONENT_ANIMATABLE_EXTEND_DECORATOR, 5807ac75b1Sopenharmony_ci CLASS_TRACK_DECORATOR, 5907ac75b1Sopenharmony_ci COMPONENT_REQUIRE_DECORATOR, 6007ac75b1Sopenharmony_ci COMPONENT_SENDABLE_DECORATOR, 6107ac75b1Sopenharmony_ci CLASS_MIN_TRACK_DECORATOR, 6207ac75b1Sopenharmony_ci MIN_OBSERVED, 6307ac75b1Sopenharmony_ci COMPONENT_NON_DECORATOR, 6407ac75b1Sopenharmony_ci COMPONENT_DECORATOR_COMPONENT_V2, 6507ac75b1Sopenharmony_ci OBSERVED, 6607ac75b1Sopenharmony_ci SENDABLE, 6707ac75b1Sopenharmony_ci TYPE, 6807ac75b1Sopenharmony_ci COMPONENT_LOCAL_BUILDER_DECORATOR 6907ac75b1Sopenharmony_ci} from './pre_define'; 7007ac75b1Sopenharmony_ciimport { 7107ac75b1Sopenharmony_ci INNER_COMPONENT_NAMES, 7207ac75b1Sopenharmony_ci AUTOMIC_COMPONENT, 7307ac75b1Sopenharmony_ci SINGLE_CHILD_COMPONENT, 7407ac75b1Sopenharmony_ci SPECIFIC_CHILD_COMPONENT, 7507ac75b1Sopenharmony_ci BUILDIN_STYLE_NAMES, 7607ac75b1Sopenharmony_ci EXTEND_ATTRIBUTE, 7707ac75b1Sopenharmony_ci GLOBAL_STYLE_FUNCTION, 7807ac75b1Sopenharmony_ci STYLES_ATTRIBUTE, 7907ac75b1Sopenharmony_ci CUSTOM_BUILDER_METHOD, 8007ac75b1Sopenharmony_ci GLOBAL_CUSTOM_BUILDER_METHOD, 8107ac75b1Sopenharmony_ci INNER_CUSTOM_BUILDER_METHOD, 8207ac75b1Sopenharmony_ci INNER_STYLE_FUNCTION, 8307ac75b1Sopenharmony_ci INNER_CUSTOM_LOCALBUILDER_METHOD 8407ac75b1Sopenharmony_ci} from './component_map'; 8507ac75b1Sopenharmony_ciimport { 8607ac75b1Sopenharmony_ci LogType, 8707ac75b1Sopenharmony_ci LogInfo, 8807ac75b1Sopenharmony_ci componentInfo, 8907ac75b1Sopenharmony_ci addLog, 9007ac75b1Sopenharmony_ci hasDecorator, 9107ac75b1Sopenharmony_ci storedFileInfo, 9207ac75b1Sopenharmony_ci ExtendResult 9307ac75b1Sopenharmony_ci} from './utils'; 9407ac75b1Sopenharmony_ciimport { globalProgram, projectConfig, abilityPagesFullPath } from '../main'; 9507ac75b1Sopenharmony_ciimport { 9607ac75b1Sopenharmony_ci collectExtend, 9707ac75b1Sopenharmony_ci isExtendFunction, 9807ac75b1Sopenharmony_ci transformLog, 9907ac75b1Sopenharmony_ci validatorCard 10007ac75b1Sopenharmony_ci} from './process_ui_syntax'; 10107ac75b1Sopenharmony_ciimport { 10207ac75b1Sopenharmony_ci isBuilderOrLocalBuilder, 10307ac75b1Sopenharmony_ci builderConditionType 10407ac75b1Sopenharmony_ci} from './process_component_class'; 10507ac75b1Sopenharmony_ciimport { stateObjectCollection } from './process_component_member'; 10607ac75b1Sopenharmony_ciimport { collectSharedModule } from './fast_build/ark_compiler/check_shared_module'; 10707ac75b1Sopenharmony_ciimport constantDefine from './constant_define'; 10807ac75b1Sopenharmony_ciimport processStructComponentV2, { StructInfo } from './process_struct_componentV2'; 10907ac75b1Sopenharmony_ciimport { getMessageCollection } from './log_message_collection'; 11007ac75b1Sopenharmony_ci 11107ac75b1Sopenharmony_ciexport class ComponentCollection { 11207ac75b1Sopenharmony_ci localStorageName: string = null; 11307ac75b1Sopenharmony_ci localStorageNode: ts.Identifier | ts.ObjectLiteralExpression = null; 11407ac75b1Sopenharmony_ci localSharedStorage: ts.Node = null; 11507ac75b1Sopenharmony_ci entryComponentPos: number = null; 11607ac75b1Sopenharmony_ci entryComponent: string = null; 11707ac75b1Sopenharmony_ci previewComponent: Array<string> = []; 11807ac75b1Sopenharmony_ci customDialogs: Set<string> = new Set([]); 11907ac75b1Sopenharmony_ci customComponents: Set<string> = new Set([]); 12007ac75b1Sopenharmony_ci currentClassName: string = null; 12107ac75b1Sopenharmony_ci} 12207ac75b1Sopenharmony_ci 12307ac75b1Sopenharmony_ciexport class IComponentSet { 12407ac75b1Sopenharmony_ci properties: Set<string> = new Set(); 12507ac75b1Sopenharmony_ci regulars: Set<string> = new Set(); 12607ac75b1Sopenharmony_ci states: Set<string> = new Set(); 12707ac75b1Sopenharmony_ci links: Set<string> = new Set(); 12807ac75b1Sopenharmony_ci props: Set<string> = new Set(); 12907ac75b1Sopenharmony_ci storageProps: Set<string> = new Set(); 13007ac75b1Sopenharmony_ci storageLinks: Set<string> = new Set(); 13107ac75b1Sopenharmony_ci provides: Set<string> = new Set(); 13207ac75b1Sopenharmony_ci consumes: Set<string> = new Set(); 13307ac75b1Sopenharmony_ci objectLinks: Set<string> = new Set(); 13407ac75b1Sopenharmony_ci localStorageLink: Map<string, Set<string>> = new Map(); 13507ac75b1Sopenharmony_ci localStorageProp: Map<string, Set<string>> = new Map(); 13607ac75b1Sopenharmony_ci builderParams: Set<string> = new Set(); 13707ac75b1Sopenharmony_ci builderParamData: Set<string> = new Set(); 13807ac75b1Sopenharmony_ci propData: Set<string> = new Set(); 13907ac75b1Sopenharmony_ci regularInit: Set<string> = new Set(); 14007ac75b1Sopenharmony_ci stateInit: Set<string> = new Set(); 14107ac75b1Sopenharmony_ci provideInit: Set<string> = new Set(); 14207ac75b1Sopenharmony_ci privateCollection: Set<string> = new Set(); 14307ac75b1Sopenharmony_ci} 14407ac75b1Sopenharmony_ci 14507ac75b1Sopenharmony_ciexport let componentCollection: ComponentCollection = new ComponentCollection(); 14607ac75b1Sopenharmony_ci 14707ac75b1Sopenharmony_ciexport const observedClassCollection: Set<string> = new Set(); 14807ac75b1Sopenharmony_ciexport const enumCollection: Set<string> = new Set(); 14907ac75b1Sopenharmony_ciexport const classMethodCollection: Map<string, Map<string, Set<string>>> = new Map(); 15007ac75b1Sopenharmony_ciexport const dollarCollection: Set<string> = new Set(); 15107ac75b1Sopenharmony_ci 15207ac75b1Sopenharmony_ciexport const propertyCollection: Map<string, Set<string>> = new Map(); 15307ac75b1Sopenharmony_ciexport const stateCollection: Map<string, Set<string>> = new Map(); 15407ac75b1Sopenharmony_ciexport const linkCollection: Map<string, Set<string>> = new Map(); 15507ac75b1Sopenharmony_ciexport const propCollection: Map<string, Set<string>> = new Map(); 15607ac75b1Sopenharmony_ciexport const regularCollection: Map<string, Set<string>> = new Map(); 15707ac75b1Sopenharmony_ciexport const storagePropCollection: Map<string, Set<string>> = new Map(); 15807ac75b1Sopenharmony_ciexport const storageLinkCollection: Map<string, Set<string>> = new Map(); 15907ac75b1Sopenharmony_ciexport const provideCollection: Map<string, Set<string>> = new Map(); 16007ac75b1Sopenharmony_ciexport const consumeCollection: Map<string, Set<string>> = new Map(); 16107ac75b1Sopenharmony_ciexport const objectLinkCollection: Map<string, Set<string>> = new Map(); 16207ac75b1Sopenharmony_ciexport const builderParamObjectCollection: Map<string, Set<string>> = new Map(); 16307ac75b1Sopenharmony_ciexport const localStorageLinkCollection: Map<string, Map<string, Set<string>>> = new Map(); 16407ac75b1Sopenharmony_ciexport const localStoragePropCollection: Map<string, Map<string, Set<string>>> = new Map(); 16507ac75b1Sopenharmony_ciexport const builderParamInitialization: Map<string, Set<string>> = new Map(); 16607ac75b1Sopenharmony_ciexport const propInitialization: Map<string, Set<string>> = new Map(); 16707ac75b1Sopenharmony_ciexport const regularInitialization: Map<string, Set<string>> = new Map(); 16807ac75b1Sopenharmony_ciexport const stateInitialization: Map<string, Set<string>> = new Map(); 16907ac75b1Sopenharmony_ciexport const provideInitialization: Map<string, Set<string>> = new Map(); 17007ac75b1Sopenharmony_ciexport const privateCollection: Map<string, Set<string>> = new Map(); 17107ac75b1Sopenharmony_ci 17207ac75b1Sopenharmony_ciexport const isStaticViewCollection: Map<string, boolean> = new Map(); 17307ac75b1Sopenharmony_ci 17407ac75b1Sopenharmony_ciexport const useOSFiles: Set<string> = new Set(); 17507ac75b1Sopenharmony_ciexport const sourcemapNamesCollection: Map<string, Map<string, string>> = new Map(); 17607ac75b1Sopenharmony_ciexport const originalImportNamesMap: Map<string, string> = new Map(); 17707ac75b1Sopenharmony_ci 17807ac75b1Sopenharmony_ciexport function validateUISyntax(source: string, content: string, filePath: string, 17907ac75b1Sopenharmony_ci fileQuery: string, sourceFile: ts.SourceFile = null): LogInfo[] { 18007ac75b1Sopenharmony_ci let log: LogInfo[] = []; 18107ac75b1Sopenharmony_ci if (process.env.compileMode === 'moduleJson' || 18207ac75b1Sopenharmony_ci path.resolve(filePath) !== path.resolve(projectConfig.projectPath || '', 'app.ets')) { 18307ac75b1Sopenharmony_ci componentCollection = new ComponentCollection(); 18407ac75b1Sopenharmony_ci const res: LogInfo[] = checkComponentDecorator(source, filePath, fileQuery, sourceFile); 18507ac75b1Sopenharmony_ci if (res) { 18607ac75b1Sopenharmony_ci log = log.concat(res); 18707ac75b1Sopenharmony_ci } 18807ac75b1Sopenharmony_ci const allComponentNames: Set<string> = 18907ac75b1Sopenharmony_ci new Set([...INNER_COMPONENT_NAMES, ...componentCollection.customComponents]); 19007ac75b1Sopenharmony_ci checkUISyntax(filePath, allComponentNames, content, log, sourceFile, fileQuery); 19107ac75b1Sopenharmony_ci componentCollection.customComponents.forEach(item => componentInfo.componentNames.add(item)); 19207ac75b1Sopenharmony_ci } 19307ac75b1Sopenharmony_ci 19407ac75b1Sopenharmony_ci if (projectConfig.compileMode === ESMODULE) { 19507ac75b1Sopenharmony_ci collectSharedModule(source, filePath, sourceFile); 19607ac75b1Sopenharmony_ci } 19707ac75b1Sopenharmony_ci 19807ac75b1Sopenharmony_ci return log; 19907ac75b1Sopenharmony_ci} 20007ac75b1Sopenharmony_ci 20107ac75b1Sopenharmony_cifunction checkComponentDecorator(source: string, filePath: string, 20207ac75b1Sopenharmony_ci fileQuery: string, sourceFile: ts.SourceFile | null): LogInfo[] | null { 20307ac75b1Sopenharmony_ci const log: LogInfo[] = []; 20407ac75b1Sopenharmony_ci if (!sourceFile) { 20507ac75b1Sopenharmony_ci sourceFile = ts.createSourceFile(filePath, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.ETS); 20607ac75b1Sopenharmony_ci } 20707ac75b1Sopenharmony_ci if (sourceFile && sourceFile.statements && sourceFile.statements.length) { 20807ac75b1Sopenharmony_ci const result: DecoratorResult = { 20907ac75b1Sopenharmony_ci entryCount: 0, 21007ac75b1Sopenharmony_ci previewCount: 0 21107ac75b1Sopenharmony_ci }; 21207ac75b1Sopenharmony_ci sourceFile.statements.forEach((item, index, arr) => { 21307ac75b1Sopenharmony_ci if (isObservedClass(item)) { 21407ac75b1Sopenharmony_ci // @ts-ignore 21507ac75b1Sopenharmony_ci observedClassCollection.add(item.name.getText()); 21607ac75b1Sopenharmony_ci } 21707ac75b1Sopenharmony_ci if (ts.isEnumDeclaration(item) && item.name) { 21807ac75b1Sopenharmony_ci enumCollection.add(item.name.getText()); 21907ac75b1Sopenharmony_ci } 22007ac75b1Sopenharmony_ci if (ts.isStructDeclaration(item)) { 22107ac75b1Sopenharmony_ci validateStructSpec(item, result, log, sourceFile); 22207ac75b1Sopenharmony_ci } 22307ac75b1Sopenharmony_ci if (ts.isMissingDeclaration(item)) { 22407ac75b1Sopenharmony_ci const decorators = ts.getAllDecorators(item); 22507ac75b1Sopenharmony_ci for (let i = 0; i < decorators.length; i++) { 22607ac75b1Sopenharmony_ci if (decorators[i] && /struct/.test(decorators[i].getText())) { 22707ac75b1Sopenharmony_ci const message: string = `Please use a valid decorator.`; 22807ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, item.getStart(), log, sourceFile); 22907ac75b1Sopenharmony_ci break; 23007ac75b1Sopenharmony_ci } 23107ac75b1Sopenharmony_ci } 23207ac75b1Sopenharmony_ci } 23307ac75b1Sopenharmony_ci }); 23407ac75b1Sopenharmony_ci if (process.env.compileTool === 'rollup') { 23507ac75b1Sopenharmony_ci if (result.entryCount > 0) { 23607ac75b1Sopenharmony_ci storedFileInfo.wholeFileInfo[filePath].hasEntry = true; 23707ac75b1Sopenharmony_ci } else { 23807ac75b1Sopenharmony_ci storedFileInfo.wholeFileInfo[filePath].hasEntry = false; 23907ac75b1Sopenharmony_ci } 24007ac75b1Sopenharmony_ci } 24107ac75b1Sopenharmony_ci validateEntryAndPreviewCount(result, fileQuery, sourceFile.fileName, projectConfig.isPreview, 24207ac75b1Sopenharmony_ci !!projectConfig.checkEntry, log); 24307ac75b1Sopenharmony_ci } 24407ac75b1Sopenharmony_ci 24507ac75b1Sopenharmony_ci return log.length ? log : null; 24607ac75b1Sopenharmony_ci} 24707ac75b1Sopenharmony_ci 24807ac75b1Sopenharmony_cifunction validateStructSpec(item: ts.StructDeclaration, result: DecoratorResult, log: LogInfo[], 24907ac75b1Sopenharmony_ci sourceFile: ts.SourceFile | null): void { 25007ac75b1Sopenharmony_ci if (item.name && ts.isIdentifier(item.name)) { 25107ac75b1Sopenharmony_ci const componentName: string = item.name.getText(); 25207ac75b1Sopenharmony_ci componentCollection.customComponents.add(componentName); 25307ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(item); 25407ac75b1Sopenharmony_ci if (decorators && decorators.length) { 25507ac75b1Sopenharmony_ci checkDecorators(decorators, result, item.name, log, sourceFile, item); 25607ac75b1Sopenharmony_ci } else { 25707ac75b1Sopenharmony_ci const message: string = `Decorator '@Component', '@ComponentV2', or '@CustomDialog' is missing for struct '${componentName}'.`; 25807ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, item.getStart(), log, sourceFile); 25907ac75b1Sopenharmony_ci } 26007ac75b1Sopenharmony_ci } else { 26107ac75b1Sopenharmony_ci const message: string = `A struct must have a name.`; 26207ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, item.getStart(), log, sourceFile); 26307ac75b1Sopenharmony_ci } 26407ac75b1Sopenharmony_ci} 26507ac75b1Sopenharmony_ci 26607ac75b1Sopenharmony_cifunction validateEntryAndPreviewCount(result: DecoratorResult, fileQuery: string, 26707ac75b1Sopenharmony_ci fileName: string, isPreview: boolean, checkEntry: boolean, log: LogInfo[]): void { 26807ac75b1Sopenharmony_ci if (result.previewCount > 10 && (fileQuery === '?entry' || process.env.watchMode === 'true')) { 26907ac75b1Sopenharmony_ci log.push({ 27007ac75b1Sopenharmony_ci type: LogType.ERROR, 27107ac75b1Sopenharmony_ci message: `A page can contain at most 10 '@Preview' decorators.`, 27207ac75b1Sopenharmony_ci fileName: fileName 27307ac75b1Sopenharmony_ci }); 27407ac75b1Sopenharmony_ci } 27507ac75b1Sopenharmony_ci if (result.entryCount > 1 && fileQuery === '?entry') { 27607ac75b1Sopenharmony_ci log.push({ 27707ac75b1Sopenharmony_ci type: LogType.ERROR, 27807ac75b1Sopenharmony_ci message: `A page can't contain more than one '@Entry' decorator`, 27907ac75b1Sopenharmony_ci fileName: fileName 28007ac75b1Sopenharmony_ci }); 28107ac75b1Sopenharmony_ci } 28207ac75b1Sopenharmony_ci if (isPreview && !checkEntry && result.previewCount < 1 && result.entryCount !== 1 && 28307ac75b1Sopenharmony_ci fileQuery === '?entry') { 28407ac75b1Sopenharmony_ci log.push({ 28507ac75b1Sopenharmony_ci type: LogType.ERROR, 28607ac75b1Sopenharmony_ci message: `A page which is being previewed must have one and only one '@Entry' ` + 28707ac75b1Sopenharmony_ci `decorator, or at least one '@Preview' decorator.`, 28807ac75b1Sopenharmony_ci fileName: fileName 28907ac75b1Sopenharmony_ci }); 29007ac75b1Sopenharmony_ci } else if ((!isPreview || isPreview && checkEntry) && result.entryCount !== 1 && fileQuery === '?entry' && 29107ac75b1Sopenharmony_ci !abilityPagesFullPath.has(path.resolve(fileName).toLowerCase())) { 29207ac75b1Sopenharmony_ci log.push({ 29307ac75b1Sopenharmony_ci type: LogType.ERROR, 29407ac75b1Sopenharmony_ci message: `A page configured in '${projectConfig.pagesJsonFileName} or build-profile.json5' must have one and only one '@Entry' decorator.` + 29507ac75b1Sopenharmony_ci `Solutions:>Please make sure that the splash page has one and only one '@Entry' decorator.`, 29607ac75b1Sopenharmony_ci fileName: fileName 29707ac75b1Sopenharmony_ci }); 29807ac75b1Sopenharmony_ci } 29907ac75b1Sopenharmony_ci} 30007ac75b1Sopenharmony_ci 30107ac75b1Sopenharmony_ciexport function isObservedClass(node: ts.Node): boolean { 30207ac75b1Sopenharmony_ci if (ts.isClassDeclaration(node) && hasDecorator(node, COMPONENT_OBSERVED_DECORATOR)) { 30307ac75b1Sopenharmony_ci return true; 30407ac75b1Sopenharmony_ci } 30507ac75b1Sopenharmony_ci return false; 30607ac75b1Sopenharmony_ci} 30707ac75b1Sopenharmony_ci 30807ac75b1Sopenharmony_ciexport function isCustomDialogClass(node: ts.Node): boolean { 30907ac75b1Sopenharmony_ci if (ts.isStructDeclaration(node) && hasDecorator(node, COMPONENT_DECORATOR_CUSTOM_DIALOG)) { 31007ac75b1Sopenharmony_ci return true; 31107ac75b1Sopenharmony_ci } 31207ac75b1Sopenharmony_ci return false; 31307ac75b1Sopenharmony_ci} 31407ac75b1Sopenharmony_ci 31507ac75b1Sopenharmony_ciinterface DecoratorResult { 31607ac75b1Sopenharmony_ci entryCount: number; 31707ac75b1Sopenharmony_ci previewCount: number; 31807ac75b1Sopenharmony_ci} 31907ac75b1Sopenharmony_ci 32007ac75b1Sopenharmony_cifunction checkDecorators(decorators: readonly ts.Decorator[], result: DecoratorResult, 32107ac75b1Sopenharmony_ci component: ts.Identifier, log: LogInfo[], sourceFile: ts.SourceFile, node: ts.StructDeclaration): void { 32207ac75b1Sopenharmony_ci const componentName: string = component.getText(); 32307ac75b1Sopenharmony_ci const structInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(componentName); 32407ac75b1Sopenharmony_ci let hasInnerComponentDecorator: boolean = false; 32507ac75b1Sopenharmony_ci decorators.forEach((element) => { 32607ac75b1Sopenharmony_ci let name: string = element.getText().replace(/\([^\(\)]*\)/, '').trim(); 32707ac75b1Sopenharmony_ci if (element.expression && element.expression.expression && ts.isIdentifier(element.expression.expression)) { 32807ac75b1Sopenharmony_ci name = '@' + element.expression.expression.getText(); 32907ac75b1Sopenharmony_ci } 33007ac75b1Sopenharmony_ci if (INNER_COMPONENT_DECORATORS.has(name)) { 33107ac75b1Sopenharmony_ci hasInnerComponentDecorator = true; 33207ac75b1Sopenharmony_ci switch (name) { 33307ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_ENTRY: 33407ac75b1Sopenharmony_ci checkEntryComponent(node, log, sourceFile); 33507ac75b1Sopenharmony_ci result.entryCount++; 33607ac75b1Sopenharmony_ci componentCollection.entryComponent = componentName; 33707ac75b1Sopenharmony_ci componentCollection.entryComponentPos = node.getStart(); 33807ac75b1Sopenharmony_ci collectLocalStorageName(element); 33907ac75b1Sopenharmony_ci break; 34007ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_PREVIEW: 34107ac75b1Sopenharmony_ci result.previewCount++; 34207ac75b1Sopenharmony_ci componentCollection.previewComponent.push(componentName); 34307ac75b1Sopenharmony_ci break; 34407ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_COMPONENT_V2: 34507ac75b1Sopenharmony_ci structInfo.isComponentV2 = true; 34607ac75b1Sopenharmony_ci break; 34707ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_COMPONENT: 34807ac75b1Sopenharmony_ci structInfo.isComponentV1 = true; 34907ac75b1Sopenharmony_ci break; 35007ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_CUSTOM_DIALOG: 35107ac75b1Sopenharmony_ci componentCollection.customDialogs.add(componentName); 35207ac75b1Sopenharmony_ci structInfo.isCustomDialog = true; 35307ac75b1Sopenharmony_ci break; 35407ac75b1Sopenharmony_ci case COMPONENT_DECORATOR_REUSEABLE: 35507ac75b1Sopenharmony_ci storedFileInfo.getCurrentArkTsFile().recycleComponents.add(componentName); 35607ac75b1Sopenharmony_ci structInfo.isReusable = true; 35707ac75b1Sopenharmony_ci break; 35807ac75b1Sopenharmony_ci } 35907ac75b1Sopenharmony_ci } else { 36007ac75b1Sopenharmony_ci validateInvalidStructDecorator(element, componentName, log, sourceFile); 36107ac75b1Sopenharmony_ci } 36207ac75b1Sopenharmony_ci }); 36307ac75b1Sopenharmony_ci validateStruct(hasInnerComponentDecorator, componentName, component, log, sourceFile, structInfo); 36407ac75b1Sopenharmony_ci} 36507ac75b1Sopenharmony_ci 36607ac75b1Sopenharmony_cifunction validateInvalidStructDecorator(element: ts.Decorator, componentName: string, log: LogInfo[], 36707ac75b1Sopenharmony_ci sourceFile: ts.SourceFile): void { 36807ac75b1Sopenharmony_ci const pos: number = element.expression ? element.expression.pos : element.pos; 36907ac75b1Sopenharmony_ci const message: string = `The struct '${componentName}' use invalid decorator.`; 37007ac75b1Sopenharmony_ci addLog(LogType.WARN, message, pos, log, sourceFile); 37107ac75b1Sopenharmony_ci} 37207ac75b1Sopenharmony_ci 37307ac75b1Sopenharmony_cifunction validateStruct(hasInnerComponentDecorator: boolean, componentName: string, component: ts.Identifier, 37407ac75b1Sopenharmony_ci log: LogInfo[], sourceFile: ts.SourceFile, structInfo: StructInfo): void { 37507ac75b1Sopenharmony_ci if (!hasInnerComponentDecorator) { 37607ac75b1Sopenharmony_ci const message: string = `Decorator '@Component', '@ComponentV2', or '@CustomDialog' is missing for struct '${componentName}'.`; 37707ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, component.pos, log, sourceFile); 37807ac75b1Sopenharmony_ci } else if (structInfo.isComponentV2 && (structInfo.isComponentV1 || structInfo.isReusable || structInfo.isCustomDialog) ) { 37907ac75b1Sopenharmony_ci const message: string = `The struct '${componentName}' can not be decorated with '@ComponentV2' ` + 38007ac75b1Sopenharmony_ci `and '@Component', '@Reusable', '@CustomDialog' at the same time.`; 38107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, component.pos, log, sourceFile); 38207ac75b1Sopenharmony_ci } 38307ac75b1Sopenharmony_ci if (BUILDIN_STYLE_NAMES.has(componentName)) { 38407ac75b1Sopenharmony_ci const message: string = `The struct '${componentName}' cannot have the same name ` + 38507ac75b1Sopenharmony_ci `as the built-in attribute '${componentName}'.`; 38607ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, component.pos, log, sourceFile); 38707ac75b1Sopenharmony_ci } 38807ac75b1Sopenharmony_ci if (INNER_COMPONENT_NAMES.has(componentName)) { 38907ac75b1Sopenharmony_ci const message: string = `The struct '${componentName}' cannot have the same name ` + 39007ac75b1Sopenharmony_ci `as the built-in component '${componentName}'.`; 39107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, component.pos, log, sourceFile); 39207ac75b1Sopenharmony_ci } 39307ac75b1Sopenharmony_ci} 39407ac75b1Sopenharmony_ci 39507ac75b1Sopenharmony_cifunction checkConcurrentDecorator(node: ts.FunctionDeclaration | ts.MethodDeclaration, log: LogInfo[], 39607ac75b1Sopenharmony_ci sourceFile: ts.SourceFile): void { 39707ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 39807ac75b1Sopenharmony_ci if (projectConfig.compileMode === JSBUNDLE) { 39907ac75b1Sopenharmony_ci const message: string = `@Concurrent can only be used in ESMODULE compile mode.`; 40007ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, decorators![0].pos, log, sourceFile); 40107ac75b1Sopenharmony_ci } 40207ac75b1Sopenharmony_ci if (ts.isMethodDeclaration(node)) { 40307ac75b1Sopenharmony_ci const message: string = `@Concurrent can not be used on method. please use it on function declaration.`; 40407ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, decorators![0].pos, log, sourceFile); 40507ac75b1Sopenharmony_ci } 40607ac75b1Sopenharmony_ci if (node.asteriskToken) { 40707ac75b1Sopenharmony_ci let hasAsync: boolean = false; 40807ac75b1Sopenharmony_ci const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 40907ac75b1Sopenharmony_ci const checkAsyncModifier = (modifier: ts.Modifier) : boolean => modifier.kind === ts.SyntaxKind.AsyncKeyword; 41007ac75b1Sopenharmony_ci modifiers && (hasAsync = modifiers.some(checkAsyncModifier)); 41107ac75b1Sopenharmony_ci const funcKind: string = hasAsync ? 'Async generator' : 'Generator'; 41207ac75b1Sopenharmony_ci const message: string = `@Concurrent can not be used on ${funcKind} function declaration.`; 41307ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, decorators![0].pos, log, sourceFile); 41407ac75b1Sopenharmony_ci } 41507ac75b1Sopenharmony_ci} 41607ac75b1Sopenharmony_ci 41707ac75b1Sopenharmony_cifunction collectLocalStorageName(node: ts.Decorator): void { 41807ac75b1Sopenharmony_ci if (node && node.expression && ts.isCallExpression(node.expression)) { 41907ac75b1Sopenharmony_ci if (node.expression.arguments && node.expression.arguments.length) { 42007ac75b1Sopenharmony_ci node.expression.arguments.forEach((item: ts.Node, index: number) => { 42107ac75b1Sopenharmony_ci if (ts.isIdentifier(item) && index === 0) { 42207ac75b1Sopenharmony_ci componentCollection.localStorageName = item.getText(); 42307ac75b1Sopenharmony_ci componentCollection.localStorageNode = item; 42407ac75b1Sopenharmony_ci } else if (ts.isObjectLiteralExpression(item) && index === 0) { 42507ac75b1Sopenharmony_ci componentCollection.localStorageName = null; 42607ac75b1Sopenharmony_ci componentCollection.localStorageNode = item; 42707ac75b1Sopenharmony_ci } else { 42807ac75b1Sopenharmony_ci componentCollection.localSharedStorage = item; 42907ac75b1Sopenharmony_ci } 43007ac75b1Sopenharmony_ci }); 43107ac75b1Sopenharmony_ci } 43207ac75b1Sopenharmony_ci } else { 43307ac75b1Sopenharmony_ci componentCollection.localStorageName = null; 43407ac75b1Sopenharmony_ci componentCollection.localStorageNode = null; 43507ac75b1Sopenharmony_ci } 43607ac75b1Sopenharmony_ci} 43707ac75b1Sopenharmony_ci 43807ac75b1Sopenharmony_cifunction checkUISyntax(filePath: string, allComponentNames: Set<string>, content: string, 43907ac75b1Sopenharmony_ci log: LogInfo[], sourceFile: ts.SourceFile | null, fileQuery: string): void { 44007ac75b1Sopenharmony_ci if (!sourceFile) { 44107ac75b1Sopenharmony_ci sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, ts.ScriptKind.ETS); 44207ac75b1Sopenharmony_ci } 44307ac75b1Sopenharmony_ci visitAllNode(sourceFile, sourceFile, allComponentNames, log, false, false, false, false, fileQuery, false, false); 44407ac75b1Sopenharmony_ci} 44507ac75b1Sopenharmony_ci 44607ac75b1Sopenharmony_cifunction visitAllNode(node: ts.Node, sourceFileNode: ts.SourceFile, allComponentNames: Set<string>, 44707ac75b1Sopenharmony_ci log: LogInfo[], structContext: boolean, classContext: boolean, isObservedClass: boolean, 44807ac75b1Sopenharmony_ci isComponentV2: boolean, fileQuery: string, isObservedV1Class: boolean, isSendableClass: boolean): void { 44907ac75b1Sopenharmony_ci if (ts.isStructDeclaration(node) && node.name && ts.isIdentifier(node.name)) { 45007ac75b1Sopenharmony_ci structContext = true; 45107ac75b1Sopenharmony_ci const structName: string = node.name.escapedText.toString(); 45207ac75b1Sopenharmony_ci const structInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(structName); 45307ac75b1Sopenharmony_ci if (structInfo.isComponentV2) { 45407ac75b1Sopenharmony_ci processStructComponentV2.parseComponentProperty(node, structInfo, log, sourceFileNode); 45507ac75b1Sopenharmony_ci isComponentV2 = true; 45607ac75b1Sopenharmony_ci } else { 45707ac75b1Sopenharmony_ci collectComponentProps(node, structInfo); 45807ac75b1Sopenharmony_ci } 45907ac75b1Sopenharmony_ci } 46007ac75b1Sopenharmony_ci if (ts.isClassDeclaration(node) && node.name && ts.isIdentifier(node.name)) { 46107ac75b1Sopenharmony_ci classContext = true; 46207ac75b1Sopenharmony_ci [isObservedV1Class, isObservedClass, isSendableClass] = parseClassDecorator(node, sourceFileNode, log); 46307ac75b1Sopenharmony_ci } 46407ac75b1Sopenharmony_ci if (ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) { 46507ac75b1Sopenharmony_ci methodDecoratorCollect(node); 46607ac75b1Sopenharmony_ci if (hasDecorator(node, COMPONENT_CONCURRENT_DECORATOR)) { 46707ac75b1Sopenharmony_ci // ark compiler's feature 46807ac75b1Sopenharmony_ci checkConcurrentDecorator(node, log, sourceFileNode); 46907ac75b1Sopenharmony_ci } 47007ac75b1Sopenharmony_ci validateFunction(node, sourceFileNode, log); 47107ac75b1Sopenharmony_ci } 47207ac75b1Sopenharmony_ci checkDecoratorCount(node, sourceFileNode, log); 47307ac75b1Sopenharmony_ci checkDecorator(sourceFileNode, node, log, structContext, classContext, isObservedClass, isComponentV2, 47407ac75b1Sopenharmony_ci isObservedV1Class, isSendableClass); 47507ac75b1Sopenharmony_ci node.getChildren().forEach((item: ts.Node) => visitAllNode(item, sourceFileNode, allComponentNames, log, 47607ac75b1Sopenharmony_ci structContext, classContext, isObservedClass, isComponentV2, fileQuery, isObservedV1Class, isSendableClass)); 47707ac75b1Sopenharmony_ci structContext = false; 47807ac75b1Sopenharmony_ci classContext = false; 47907ac75b1Sopenharmony_ci isObservedClass = false; 48007ac75b1Sopenharmony_ci isObservedV1Class = false; 48107ac75b1Sopenharmony_ci isSendableClass = false; 48207ac75b1Sopenharmony_ci} 48307ac75b1Sopenharmony_ci 48407ac75b1Sopenharmony_ciconst v1ComponentDecorators: string[] = [ 48507ac75b1Sopenharmony_ci 'State', 'Prop', 'Link', 'Provide', 'Consume', 48607ac75b1Sopenharmony_ci 'StorageLink', 'StorageProp', 'LocalStorageLink', 'LocalStorageProp' 48707ac75b1Sopenharmony_ci]; 48807ac75b1Sopenharmony_ciconst v2ComponentDecorators: string[] = [ 48907ac75b1Sopenharmony_ci 'Local', 'Param', 'Event', 'Provider', 'Consumer' 49007ac75b1Sopenharmony_ci]; 49107ac75b1Sopenharmony_cifunction validatePropertyInStruct(structContext: boolean, decoratorNode: ts.Identifier, 49207ac75b1Sopenharmony_ci decoratorName: string, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 49307ac75b1Sopenharmony_ci if (structContext) { 49407ac75b1Sopenharmony_ci const isV1Decorator: boolean = v1ComponentDecorators.includes(decoratorName); 49507ac75b1Sopenharmony_ci const isV2Decorator: boolean = v2ComponentDecorators.includes(decoratorName); 49607ac75b1Sopenharmony_ci if (!isV1Decorator && !isV2Decorator) { 49707ac75b1Sopenharmony_ci return; 49807ac75b1Sopenharmony_ci } 49907ac75b1Sopenharmony_ci const classResult: ClassDecoratorResult = new ClassDecoratorResult(); 50007ac75b1Sopenharmony_ci const propertyNode: ts.PropertyDeclaration = getPropertyNodeByDecorator(decoratorNode); 50107ac75b1Sopenharmony_ci if (propertyNode && propertyNode.type && globalProgram.checker) { 50207ac75b1Sopenharmony_ci validatePropertyType(propertyNode.type, classResult); 50307ac75b1Sopenharmony_ci } 50407ac75b1Sopenharmony_ci let message: string; 50507ac75b1Sopenharmony_ci if (isV1Decorator && classResult.hasObservedV2) { 50607ac75b1Sopenharmony_ci message = `The type of the @${decoratorName} property can not be a class decorated with @ObservedV2.`; 50707ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, decoratorNode.getStart(), log, sourceFileNode); 50807ac75b1Sopenharmony_ci return; 50907ac75b1Sopenharmony_ci } 51007ac75b1Sopenharmony_ci if (isV2Decorator && classResult.hasObserved) { 51107ac75b1Sopenharmony_ci message = `The type of the @${decoratorName} property can not be a class decorated with @Observed.`; 51207ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, decoratorNode.getStart(), log, sourceFileNode); 51307ac75b1Sopenharmony_ci return; 51407ac75b1Sopenharmony_ci } 51507ac75b1Sopenharmony_ci } 51607ac75b1Sopenharmony_ci} 51707ac75b1Sopenharmony_ci 51807ac75b1Sopenharmony_cifunction getPropertyNodeByDecorator(decoratorNode: ts.Identifier): ts.PropertyDeclaration { 51907ac75b1Sopenharmony_ci if (ts.isDecorator(decoratorNode.parent) && ts.isPropertyDeclaration(decoratorNode.parent.parent)) { 52007ac75b1Sopenharmony_ci return decoratorNode.parent.parent; 52107ac75b1Sopenharmony_ci } 52207ac75b1Sopenharmony_ci if (ts.isCallExpression(decoratorNode.parent) && ts.isDecorator(decoratorNode.parent.parent) && 52307ac75b1Sopenharmony_ci ts.isPropertyDeclaration(decoratorNode.parent.parent.parent)) { 52407ac75b1Sopenharmony_ci return decoratorNode.parent.parent.parent; 52507ac75b1Sopenharmony_ci } 52607ac75b1Sopenharmony_ci return undefined; 52707ac75b1Sopenharmony_ci} 52807ac75b1Sopenharmony_ci 52907ac75b1Sopenharmony_cifunction validatePropertyType(node: ts.TypeNode, classResult: ClassDecoratorResult): void { 53007ac75b1Sopenharmony_ci if (ts.isUnionTypeNode(node) && node.types && node.types.length) { 53107ac75b1Sopenharmony_ci node.types.forEach((item: ts.TypeNode) => { 53207ac75b1Sopenharmony_ci validatePropertyType(item, classResult); 53307ac75b1Sopenharmony_ci }); 53407ac75b1Sopenharmony_ci } 53507ac75b1Sopenharmony_ci if (ts.isTypeReferenceNode(node) && node.typeName) { 53607ac75b1Sopenharmony_ci const typeNode: ts.Type = globalProgram.checker.getTypeAtLocation(node.typeName); 53707ac75b1Sopenharmony_ci parsePropertyType(typeNode, classResult); 53807ac75b1Sopenharmony_ci } 53907ac75b1Sopenharmony_ci} 54007ac75b1Sopenharmony_ci 54107ac75b1Sopenharmony_cifunction parsePropertyType(type: ts.Type, classResult: ClassDecoratorResult): void { 54207ac75b1Sopenharmony_ci // @ts-ignore 54307ac75b1Sopenharmony_ci if (type && type.types && type.types.length) { 54407ac75b1Sopenharmony_ci // @ts-ignore 54507ac75b1Sopenharmony_ci type.types.forEach((item: ts.Type) => { 54607ac75b1Sopenharmony_ci parsePropertyType(item, classResult); 54707ac75b1Sopenharmony_ci }); 54807ac75b1Sopenharmony_ci } 54907ac75b1Sopenharmony_ci if (type && type.symbol && type.symbol.valueDeclaration && 55007ac75b1Sopenharmony_ci ts.isClassDeclaration(type.symbol.valueDeclaration)) { 55107ac75b1Sopenharmony_ci const result: ClassDecoratorResult = getClassDecoratorResult(type.symbol.valueDeclaration); 55207ac75b1Sopenharmony_ci if (result.hasObserved) { 55307ac75b1Sopenharmony_ci classResult.hasObserved = result.hasObserved; 55407ac75b1Sopenharmony_ci } 55507ac75b1Sopenharmony_ci if (result.hasObservedV2) { 55607ac75b1Sopenharmony_ci classResult.hasObservedV2 = result.hasObservedV2; 55707ac75b1Sopenharmony_ci } 55807ac75b1Sopenharmony_ci } 55907ac75b1Sopenharmony_ci} 56007ac75b1Sopenharmony_ci 56107ac75b1Sopenharmony_cifunction checkDecoratorCount(node: ts.Node, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 56207ac75b1Sopenharmony_ci if (ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isMethodDeclaration(node)) { 56307ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 56407ac75b1Sopenharmony_ci let innerDecoratorCount: number = 0; 56507ac75b1Sopenharmony_ci const exludeDecorators: string[] = ['@Require', '@Once']; 56607ac75b1Sopenharmony_ci const v1MethodDecorators: string[] = ['@Builder', '@Styles']; 56707ac75b1Sopenharmony_ci const v1DecoratorMap: Map<string, number> = new Map<string, number>(); 56807ac75b1Sopenharmony_ci const v2DecoratorMap: Map<string, number> = new Map<string, number>(); 56907ac75b1Sopenharmony_ci let checkDecoratorCount: number = 0; 57007ac75b1Sopenharmony_ci decorators.forEach((item: ts.Decorator) => { 57107ac75b1Sopenharmony_ci const decoratorName: string = item.getText().replace(/\([^\(\)]*\)/, ''); 57207ac75b1Sopenharmony_ci if (!exludeDecorators.includes(decoratorName) && (constantDefine.DECORATOR_V2.includes(decoratorName) || 57307ac75b1Sopenharmony_ci decoratorName === '@BuilderParam')) { 57407ac75b1Sopenharmony_ci const count: number = v2DecoratorMap.get(decoratorName) || 0; 57507ac75b1Sopenharmony_ci v2DecoratorMap.set(decoratorName, count + 1); 57607ac75b1Sopenharmony_ci return; 57707ac75b1Sopenharmony_ci } 57807ac75b1Sopenharmony_ci if (v1MethodDecorators.includes(decoratorName)) { 57907ac75b1Sopenharmony_ci const count: number = v1DecoratorMap.get(decoratorName) || 0; 58007ac75b1Sopenharmony_ci v1DecoratorMap.set(decoratorName, count + 1); 58107ac75b1Sopenharmony_ci return; 58207ac75b1Sopenharmony_ci } 58307ac75b1Sopenharmony_ci if (decoratorName === COMPONENT_LOCAL_BUILDER_DECORATOR && decorators.length > 1) { 58407ac75b1Sopenharmony_ci checkDecoratorCount = checkDecoratorCount + 1; 58507ac75b1Sopenharmony_ci return; 58607ac75b1Sopenharmony_ci } 58707ac75b1Sopenharmony_ci }); 58807ac75b1Sopenharmony_ci const v2DecoratorMapKeys: string[] = Array.from(v2DecoratorMap.keys()); 58907ac75b1Sopenharmony_ci const v2DecoratorMapValues: number[] = Array.from(v2DecoratorMap.values()); 59007ac75b1Sopenharmony_ci const v1DecoratorMapKeys: string[] = Array.from(v1DecoratorMap.keys()); 59107ac75b1Sopenharmony_ci const v1DecoratorMapValues: number[] = Array.from(v1DecoratorMap.values()); 59207ac75b1Sopenharmony_ci innerDecoratorCount = v2DecoratorMapKeys.length + v1DecoratorMapKeys.length; 59307ac75b1Sopenharmony_ci getMessageCollection().checkLocalBuilderDecoratorCount(node, sourceFileNode, checkDecoratorCount, log); 59407ac75b1Sopenharmony_ci if (innerDecoratorCount > 1) { 59507ac75b1Sopenharmony_ci const message: string = 'The member property or method can not be decorated by multiple built-in decorators.'; 59607ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 59707ac75b1Sopenharmony_ci } 59807ac75b1Sopenharmony_ci const v2Duplicate: boolean = v2DecoratorMapValues.length && 59907ac75b1Sopenharmony_ci v2DecoratorMapValues.some((count: number) => count > 1); 60007ac75b1Sopenharmony_ci const v1Duplicate: boolean = v1DecoratorMapValues.length && 60107ac75b1Sopenharmony_ci v1DecoratorMapValues.some((count: number) => count > 1); 60207ac75b1Sopenharmony_ci const duplicateMessage: string = 'Duplicate decorators for method are not allowed.'; 60307ac75b1Sopenharmony_ci if (v2Duplicate || v1Duplicate) { 60407ac75b1Sopenharmony_ci addLog(v1Duplicate ? LogType.WARN : LogType.ERROR, duplicateMessage, node.getStart(), log, sourceFileNode); 60507ac75b1Sopenharmony_ci } 60607ac75b1Sopenharmony_ci } 60707ac75b1Sopenharmony_ci} 60807ac75b1Sopenharmony_ci 60907ac75b1Sopenharmony_cifunction methodDecoratorCollect(node: ts.MethodDeclaration | ts.FunctionDeclaration): void { 61007ac75b1Sopenharmony_ci const extendResult: ExtendResult = { decoratorName: '', componentName: '' }; 61107ac75b1Sopenharmony_ci const builderCondition: builderConditionType = { 61207ac75b1Sopenharmony_ci isBuilder: false, 61307ac75b1Sopenharmony_ci isLocalBuilder: false 61407ac75b1Sopenharmony_ci }; 61507ac75b1Sopenharmony_ci if (isBuilderOrLocalBuilder(node, builderCondition)) { 61607ac75b1Sopenharmony_ci if (builderCondition.isBuilder) { 61707ac75b1Sopenharmony_ci CUSTOM_BUILDER_METHOD.add(node.name.getText()); 61807ac75b1Sopenharmony_ci if (ts.isFunctionDeclaration(node)) { 61907ac75b1Sopenharmony_ci GLOBAL_CUSTOM_BUILDER_METHOD.add(node.name.getText()); 62007ac75b1Sopenharmony_ci } else { 62107ac75b1Sopenharmony_ci INNER_CUSTOM_BUILDER_METHOD.add(node.name.getText()); 62207ac75b1Sopenharmony_ci } 62307ac75b1Sopenharmony_ci } else if (builderCondition.isLocalBuilder) { 62407ac75b1Sopenharmony_ci INNER_CUSTOM_LOCALBUILDER_METHOD.add(node.name.getText()); 62507ac75b1Sopenharmony_ci } 62607ac75b1Sopenharmony_ci } else if (ts.isFunctionDeclaration(node) && isExtendFunction(node, extendResult)) { 62707ac75b1Sopenharmony_ci if (extendResult.decoratorName === CHECK_COMPONENT_EXTEND_DECORATOR) { 62807ac75b1Sopenharmony_ci collectExtend(EXTEND_ATTRIBUTE, extendResult.componentName, node.name.getText()); 62907ac75b1Sopenharmony_ci } 63007ac75b1Sopenharmony_ci if (extendResult.decoratorName === CHECK_COMPONENT_ANIMATABLE_EXTEND_DECORATOR) { 63107ac75b1Sopenharmony_ci collectExtend(storedFileInfo.getCurrentArkTsFile().animatableExtendAttribute, 63207ac75b1Sopenharmony_ci extendResult.componentName, node.name.getText()); 63307ac75b1Sopenharmony_ci } 63407ac75b1Sopenharmony_ci } else if (hasDecorator(node, COMPONENT_STYLES_DECORATOR)) { 63507ac75b1Sopenharmony_ci collectStyles(node); 63607ac75b1Sopenharmony_ci } 63707ac75b1Sopenharmony_ci} 63807ac75b1Sopenharmony_ci 63907ac75b1Sopenharmony_cifunction collectStyles(node: ts.FunctionLikeDeclarationBase): void { 64007ac75b1Sopenharmony_ci if (ts.isBlock(node.body) && node.body.statements) { 64107ac75b1Sopenharmony_ci if (ts.isFunctionDeclaration(node)) { 64207ac75b1Sopenharmony_ci GLOBAL_STYLE_FUNCTION.set(node.name.getText(), node.body); 64307ac75b1Sopenharmony_ci } else { 64407ac75b1Sopenharmony_ci INNER_STYLE_FUNCTION.set(node.name.getText(), node.body); 64507ac75b1Sopenharmony_ci } 64607ac75b1Sopenharmony_ci STYLES_ATTRIBUTE.add(node.name.getText()); 64707ac75b1Sopenharmony_ci BUILDIN_STYLE_NAMES.add(node.name.getText()); 64807ac75b1Sopenharmony_ci } 64907ac75b1Sopenharmony_ci} 65007ac75b1Sopenharmony_ci 65107ac75b1Sopenharmony_cifunction validateFunction(node: ts.MethodDeclaration | ts.FunctionDeclaration, 65207ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 65307ac75b1Sopenharmony_ci if (ts.isFunctionDeclaration(node)) { 65407ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 65507ac75b1Sopenharmony_ci const decoratorMap: Map<string, number> = new Map<string, number>(); 65607ac75b1Sopenharmony_ci decorators.forEach((item: ts.Decorator) => { 65707ac75b1Sopenharmony_ci const decoratorName: string = item.getText().replace(/\([^\(\)]*\)/, '') 65807ac75b1Sopenharmony_ci .replace(/^@/, '').trim(); 65907ac75b1Sopenharmony_ci const count: number = decoratorMap.get(decoratorName) || 0; 66007ac75b1Sopenharmony_ci decoratorMap.set(decoratorName, count + 1); 66107ac75b1Sopenharmony_ci }); 66207ac75b1Sopenharmony_ci const decoratorValues: number[] = Array.from(decoratorMap.values()); 66307ac75b1Sopenharmony_ci const hasDuplicate: boolean = decoratorValues.length && 66407ac75b1Sopenharmony_ci decoratorValues.some((count: number) => count > 1); 66507ac75b1Sopenharmony_ci if (hasDuplicate) { 66607ac75b1Sopenharmony_ci const message: string = 'Duplicate decorators for function are not allowed.'; 66707ac75b1Sopenharmony_ci addLog(LogType.WARN, message, node.getStart(), log, sourceFileNode); 66807ac75b1Sopenharmony_ci } 66907ac75b1Sopenharmony_ci const decoratorKeys: string[] = Array.from(decoratorMap.keys()); 67007ac75b1Sopenharmony_ci if (decoratorKeys.length > 1 || decoratorKeys.includes('LocalBuilder')) { 67107ac75b1Sopenharmony_ci const message: string = 'A function can only be decorated by one of the ' + 67207ac75b1Sopenharmony_ci `'AnimatableExtend, Builder, Extend, Styles, Concurrent and Sendable'.`; 67307ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 67407ac75b1Sopenharmony_ci } 67507ac75b1Sopenharmony_ci } 67607ac75b1Sopenharmony_ci} 67707ac75b1Sopenharmony_ci 67807ac75b1Sopenharmony_cifunction checkDecorator(sourceFileNode: ts.SourceFile, node: ts.Node, 67907ac75b1Sopenharmony_ci log: LogInfo[], structContext: boolean, classContext: boolean, isObservedClass: boolean, 68007ac75b1Sopenharmony_ci isComponentV2: boolean, isObservedV1Class: boolean, isSendableClass: boolean): void { 68107ac75b1Sopenharmony_ci if (ts.isIdentifier(node) && (ts.isDecorator(node.parent) || 68207ac75b1Sopenharmony_ci (ts.isCallExpression(node.parent) && ts.isDecorator(node.parent.parent)))) { 68307ac75b1Sopenharmony_ci const decoratorName: string = node.escapedText.toString(); 68407ac75b1Sopenharmony_ci setLocalBuilderInFile(decoratorName); 68507ac75b1Sopenharmony_ci validateStructDecorator(sourceFileNode, node, log, structContext, decoratorName, isComponentV2); 68607ac75b1Sopenharmony_ci validateMethodDecorator(sourceFileNode, node, log, structContext, decoratorName); 68707ac75b1Sopenharmony_ci validateClassDecorator(sourceFileNode, node, log, classContext, decoratorName, isObservedClass, 68807ac75b1Sopenharmony_ci isObservedV1Class, isSendableClass); 68907ac75b1Sopenharmony_ci validatePropertyInStruct(structContext, node, decoratorName, sourceFileNode, log); 69007ac75b1Sopenharmony_ci return; 69107ac75b1Sopenharmony_ci } 69207ac75b1Sopenharmony_ci if (ts.isDecorator(node)) { 69307ac75b1Sopenharmony_ci validateSingleDecorator(node, sourceFileNode, log, isComponentV2); 69407ac75b1Sopenharmony_ci } 69507ac75b1Sopenharmony_ci} 69607ac75b1Sopenharmony_ci 69707ac75b1Sopenharmony_cifunction setLocalBuilderInFile(decoratorName: string): void { 69807ac75b1Sopenharmony_ci if (decoratorName === 'LocalBuilder') { 69907ac75b1Sopenharmony_ci storedFileInfo.hasLocalBuilderInFile = true; 70007ac75b1Sopenharmony_ci } 70107ac75b1Sopenharmony_ci} 70207ac75b1Sopenharmony_ci 70307ac75b1Sopenharmony_cifunction validateSingleDecorator(node: ts.Decorator, sourceFileNode: ts.SourceFile, 70407ac75b1Sopenharmony_ci log: LogInfo[], isComponentV2: boolean): void { 70507ac75b1Sopenharmony_ci const decoratorName: string = node.getText().replace(/\([^\(\)]*\)/, ''); 70607ac75b1Sopenharmony_ci if (decoratorName === constantDefine.COMPUTED_DECORATOR && node.parent && !ts.isGetAccessor(node.parent)) { 70707ac75b1Sopenharmony_ci const message: string = `@Computed can only decorate 'GetAccessor'.`; 70807ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 70907ac75b1Sopenharmony_ci return; 71007ac75b1Sopenharmony_ci } 71107ac75b1Sopenharmony_ci const partialDecoratorCollection: string[] = [constantDefine.MONITOR_DECORATOR, COMPONENT_LOCAL_BUILDER_DECORATOR]; 71207ac75b1Sopenharmony_ci if (partialDecoratorCollection.includes(decoratorName) && node.parent && 71307ac75b1Sopenharmony_ci !ts.isMethodDeclaration(node.parent)) { 71407ac75b1Sopenharmony_ci const message: string = `'${decoratorName}' can only decorate method.`; 71507ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 71607ac75b1Sopenharmony_ci return; 71707ac75b1Sopenharmony_ci } 71807ac75b1Sopenharmony_ci if (isMemberForComponentV2(decoratorName, isComponentV2) && node.parent && 71907ac75b1Sopenharmony_ci !ts.isPropertyDeclaration(node.parent)) { 72007ac75b1Sopenharmony_ci const message: string = `'${decoratorName}' can only decorate member property.`; 72107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 72207ac75b1Sopenharmony_ci return; 72307ac75b1Sopenharmony_ci } 72407ac75b1Sopenharmony_ci} 72507ac75b1Sopenharmony_ci 72607ac75b1Sopenharmony_cifunction isMemberForComponentV2(decoratorName: string, isComponentV2: boolean): boolean { 72707ac75b1Sopenharmony_ci return constantDefine.COMPONENT_MEMBER_DECORATOR_V2.includes(decoratorName) || 72807ac75b1Sopenharmony_ci (isComponentV2 && decoratorName === '@BuilderParam'); 72907ac75b1Sopenharmony_ci} 73007ac75b1Sopenharmony_ci 73107ac75b1Sopenharmony_ciconst classDecorators: string[] = [CLASS_TRACK_DECORATOR, CLASS_MIN_TRACK_DECORATOR, MIN_OBSERVED]; 73207ac75b1Sopenharmony_ciconst classMemberDecorators: string[] = [CLASS_TRACK_DECORATOR, CLASS_MIN_TRACK_DECORATOR, TYPE, 73307ac75b1Sopenharmony_ci constantDefine.MONITOR, constantDefine.COMPUTED]; 73407ac75b1Sopenharmony_ci 73507ac75b1Sopenharmony_cifunction validTypeCallback(node: ts.Identifier): boolean { 73607ac75b1Sopenharmony_ci let isSdkPath: boolean = true; 73707ac75b1Sopenharmony_ci if (globalProgram.checker && process.env.compileTool === 'rollup') { 73807ac75b1Sopenharmony_ci const symbolObj: ts.Symbol = getSymbolIfAliased(node); 73907ac75b1Sopenharmony_ci const fileName: string = symbolObj?.valueDeclaration?.getSourceFile()?.fileName; 74007ac75b1Sopenharmony_ci isSdkPath = /@ohos.arkui.*/.test(fileName); 74107ac75b1Sopenharmony_ci } 74207ac75b1Sopenharmony_ci return isSdkPath; 74307ac75b1Sopenharmony_ci} 74407ac75b1Sopenharmony_ci 74507ac75b1Sopenharmony_cifunction isTypeFromSdkCallback(classContext: boolean, decoratorName: string, isTypeFromSdk: boolean): boolean { 74607ac75b1Sopenharmony_ci if (!classContext && decoratorName === TYPE && isTypeFromSdk) { 74707ac75b1Sopenharmony_ci return true; 74807ac75b1Sopenharmony_ci } 74907ac75b1Sopenharmony_ci return false; 75007ac75b1Sopenharmony_ci} 75107ac75b1Sopenharmony_ci 75207ac75b1Sopenharmony_cifunction validateClassDecorator(sourceFileNode: ts.SourceFile, node: ts.Identifier, log: LogInfo[], 75307ac75b1Sopenharmony_ci classContext: boolean, decoratorName: string, isObservedClass: boolean, isObservedV1Class: boolean, 75407ac75b1Sopenharmony_ci isSendableClass: boolean): void { 75507ac75b1Sopenharmony_ci const isTypeFromSdk: boolean = validTypeCallback(node); 75607ac75b1Sopenharmony_ci if (!classContext && (classDecorators.includes(decoratorName) || isTypeFromSdkCallback(classContext, decoratorName, isTypeFromSdk))) { 75707ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can only be used in 'class'.`; 75807ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 75907ac75b1Sopenharmony_ci } else if (classContext && classMemberDecorators.includes(decoratorName)) { 76007ac75b1Sopenharmony_ci validateMemberInClass(isObservedClass, decoratorName, node, log, sourceFileNode, isObservedV1Class, isSendableClass, isTypeFromSdk); 76107ac75b1Sopenharmony_ci } 76207ac75b1Sopenharmony_ci} 76307ac75b1Sopenharmony_ci 76407ac75b1Sopenharmony_cifunction validateMemberInClass(isObservedClass: boolean, decoratorName: string, node: ts.Identifier, 76507ac75b1Sopenharmony_ci log: LogInfo[], sourceFileNode: ts.SourceFile, isObservedV1Class: boolean, isSendableClass: boolean, isTypeFromSdk: boolean): void { 76607ac75b1Sopenharmony_ci if (decoratorName === CLASS_TRACK_DECORATOR) { 76707ac75b1Sopenharmony_ci if (isObservedClass) { 76807ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can not be used in a 'class' decorated with ObservedV2.`; 76907ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 77007ac75b1Sopenharmony_ci } 77107ac75b1Sopenharmony_ci return; 77207ac75b1Sopenharmony_ci } 77307ac75b1Sopenharmony_ci if (decoratorName === TYPE) { 77407ac75b1Sopenharmony_ci if (isTypeFromSdk) { 77507ac75b1Sopenharmony_ci validType(sourceFileNode, node, log, decoratorName, isObservedV1Class, isSendableClass); 77607ac75b1Sopenharmony_ci } 77707ac75b1Sopenharmony_ci return; 77807ac75b1Sopenharmony_ci } 77907ac75b1Sopenharmony_ci if (!isObservedClass || !isPropertyForTrace(node, decoratorName)) { 78007ac75b1Sopenharmony_ci const info: string = decoratorName === CLASS_MIN_TRACK_DECORATOR ? 'variables' : 'method'; 78107ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' can decorate only member ${info} within a 'class' decorated with ObservedV2.`; 78207ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 78307ac75b1Sopenharmony_ci return; 78407ac75b1Sopenharmony_ci } 78507ac75b1Sopenharmony_ci} 78607ac75b1Sopenharmony_ci 78707ac75b1Sopenharmony_cifunction validType(sourceFileNode: ts.SourceFile, node: ts.Identifier, log: LogInfo[], decoratorName: string, 78807ac75b1Sopenharmony_ci isObservedV1Class: boolean, isSendableClass: boolean): void { 78907ac75b1Sopenharmony_ci if (isSendableClass) { 79007ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can not be used in a 'class' decorated with Sendable.`; 79107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 79207ac75b1Sopenharmony_ci } 79307ac75b1Sopenharmony_ci if (isObservedV1Class) { 79407ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can not be used in a 'class' decorated with Observed.`; 79507ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 79607ac75b1Sopenharmony_ci } 79707ac75b1Sopenharmony_ci if (ts.isDecorator(node.parent?.parent) && !ts.isPropertyDeclaration(node.parent?.parent?.parent)) { 79807ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' can decorate only member variables in a 'class'.`; 79907ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 80007ac75b1Sopenharmony_ci } 80107ac75b1Sopenharmony_ci} 80207ac75b1Sopenharmony_ci 80307ac75b1Sopenharmony_cifunction isPropertyForTrace(node: ts.Identifier, decoratorName: string): boolean { 80407ac75b1Sopenharmony_ci if (decoratorName === CLASS_MIN_TRACK_DECORATOR && ts.isDecorator(node.parent) && 80507ac75b1Sopenharmony_ci !ts.isPropertyDeclaration(node.parent.parent)) { 80607ac75b1Sopenharmony_ci return false; 80707ac75b1Sopenharmony_ci } 80807ac75b1Sopenharmony_ci return true; 80907ac75b1Sopenharmony_ci} 81007ac75b1Sopenharmony_ci 81107ac75b1Sopenharmony_ciclass ClassDecoratorResult { 81207ac75b1Sopenharmony_ci hasObserved: boolean = false; 81307ac75b1Sopenharmony_ci hasObservedV2: boolean = false; 81407ac75b1Sopenharmony_ci hasSendable: boolean = false; 81507ac75b1Sopenharmony_ci} 81607ac75b1Sopenharmony_ci 81707ac75b1Sopenharmony_cifunction parseClassDecorator(node: ts.ClassDeclaration, sourceFileNode: ts.SourceFile, 81807ac75b1Sopenharmony_ci log: LogInfo[]): [boolean, boolean, boolean] { 81907ac75b1Sopenharmony_ci const classResult: ClassDecoratorResult = getClassDecoratorResult(node); 82007ac75b1Sopenharmony_ci validateMutilObserved(node, classResult, sourceFileNode, log); 82107ac75b1Sopenharmony_ci if (classResult.hasObserved || classResult.hasObservedV2) { 82207ac75b1Sopenharmony_ci parseInheritClass(node, classResult, sourceFileNode, log); 82307ac75b1Sopenharmony_ci } 82407ac75b1Sopenharmony_ci return [classResult.hasObserved, classResult.hasObservedV2, classResult.hasSendable]; 82507ac75b1Sopenharmony_ci} 82607ac75b1Sopenharmony_ci 82707ac75b1Sopenharmony_cifunction getClassDecoratorResult(node: ts.ClassDeclaration): ClassDecoratorResult { 82807ac75b1Sopenharmony_ci const classResult: ClassDecoratorResult = new ClassDecoratorResult(); 82907ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 83007ac75b1Sopenharmony_ci decorators.forEach((item: ts.Decorator) => { 83107ac75b1Sopenharmony_ci if (ts.isIdentifier(item.expression)) { 83207ac75b1Sopenharmony_ci const decoratorName: string = item.expression.escapedText.toString(); 83307ac75b1Sopenharmony_ci switch (decoratorName) { 83407ac75b1Sopenharmony_ci case MIN_OBSERVED: 83507ac75b1Sopenharmony_ci classResult.hasObservedV2 = true; 83607ac75b1Sopenharmony_ci break; 83707ac75b1Sopenharmony_ci case OBSERVED: 83807ac75b1Sopenharmony_ci classResult.hasObserved = true; 83907ac75b1Sopenharmony_ci break; 84007ac75b1Sopenharmony_ci case SENDABLE: 84107ac75b1Sopenharmony_ci classResult.hasSendable = true; 84207ac75b1Sopenharmony_ci } 84307ac75b1Sopenharmony_ci } 84407ac75b1Sopenharmony_ci }); 84507ac75b1Sopenharmony_ci return classResult; 84607ac75b1Sopenharmony_ci} 84707ac75b1Sopenharmony_ci 84807ac75b1Sopenharmony_cifunction validateMutilObserved(node: ts.ClassDeclaration, classResult: ClassDecoratorResult, 84907ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 85007ac75b1Sopenharmony_ci if (classResult.hasObserved && classResult.hasObservedV2) { 85107ac75b1Sopenharmony_ci const message: string = `A class can not be decorated by '@Observed' and '@ObservedV2' at the same time.`; 85207ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.getStart(), log, sourceFileNode); 85307ac75b1Sopenharmony_ci } 85407ac75b1Sopenharmony_ci} 85507ac75b1Sopenharmony_ci 85607ac75b1Sopenharmony_cifunction parseInheritClass(node: ts.ClassDeclaration, childClassResult: ClassDecoratorResult, 85707ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 85807ac75b1Sopenharmony_ci if (globalProgram.checker && process.env.compileTool === 'rollup' && node.heritageClauses) { 85907ac75b1Sopenharmony_ci for (const heritageClause of node.heritageClauses) { 86007ac75b1Sopenharmony_ci if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword && heritageClause.types && 86107ac75b1Sopenharmony_ci heritageClause.types.length) { 86207ac75b1Sopenharmony_ci getClassNode(heritageClause.types[0].expression, childClassResult, node, sourceFileNode, log); 86307ac75b1Sopenharmony_ci } 86407ac75b1Sopenharmony_ci } 86507ac75b1Sopenharmony_ci } 86607ac75b1Sopenharmony_ci} 86707ac75b1Sopenharmony_ci 86807ac75b1Sopenharmony_cifunction getClassNode(parentType: ts.Node, childClassResult: ClassDecoratorResult, 86907ac75b1Sopenharmony_ci childClass: ts.ClassDeclaration, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 87007ac75b1Sopenharmony_ci const symbol: ts.Symbol = parentType && getSymbolIfAliased(parentType); 87107ac75b1Sopenharmony_ci if (symbol && symbol.valueDeclaration) { 87207ac75b1Sopenharmony_ci if (ts.isClassDeclaration(symbol.valueDeclaration)) { 87307ac75b1Sopenharmony_ci validateInheritClassDecorator(symbol.valueDeclaration, childClassResult, childClass, sourceFileNode, log); 87407ac75b1Sopenharmony_ci return; 87507ac75b1Sopenharmony_ci } 87607ac75b1Sopenharmony_ci if (ts.isPropertyAssignment(symbol.valueDeclaration)) { 87707ac75b1Sopenharmony_ci getClassNode(symbol.valueDeclaration.initializer, childClassResult, childClass, sourceFileNode, log); 87807ac75b1Sopenharmony_ci return; 87907ac75b1Sopenharmony_ci } 88007ac75b1Sopenharmony_ci if (ts.isShorthandPropertyAssignment(symbol.valueDeclaration)) { 88107ac75b1Sopenharmony_ci parseShorthandPropertyForClass(symbol.valueDeclaration, childClassResult, childClass, sourceFileNode, log); 88207ac75b1Sopenharmony_ci return; 88307ac75b1Sopenharmony_ci } 88407ac75b1Sopenharmony_ci } 88507ac75b1Sopenharmony_ci} 88607ac75b1Sopenharmony_ci 88707ac75b1Sopenharmony_cifunction parseShorthandPropertyForClass(node: ts.ShorthandPropertyAssignment, childClassResult: ClassDecoratorResult, 88807ac75b1Sopenharmony_ci childClass: ts.ClassDeclaration, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 88907ac75b1Sopenharmony_ci const shortSymbol: ts.Symbol = globalProgram.checker.getShorthandAssignmentValueSymbol(node); 89007ac75b1Sopenharmony_ci if (shortSymbol && shortSymbol.valueDeclaration && ts.isClassDeclaration(shortSymbol.valueDeclaration)) { 89107ac75b1Sopenharmony_ci validateInheritClassDecorator(shortSymbol.valueDeclaration, childClassResult, childClass, sourceFileNode, log); 89207ac75b1Sopenharmony_ci } 89307ac75b1Sopenharmony_ci} 89407ac75b1Sopenharmony_ci 89507ac75b1Sopenharmony_cifunction getSymbolIfAliased(node: ts.Node): ts.Symbol { 89607ac75b1Sopenharmony_ci const symbol: ts.Symbol = globalProgram.checker.getSymbolAtLocation(node); 89707ac75b1Sopenharmony_ci if (symbol && (symbol.getFlags() & ts.SymbolFlags.Alias) !== 0) { 89807ac75b1Sopenharmony_ci return globalProgram.checker.getAliasedSymbol(symbol); 89907ac75b1Sopenharmony_ci } 90007ac75b1Sopenharmony_ci return symbol; 90107ac75b1Sopenharmony_ci} 90207ac75b1Sopenharmony_ci 90307ac75b1Sopenharmony_cifunction validateInheritClassDecorator(parentNode: ts.ClassDeclaration, childClassResult: ClassDecoratorResult, 90407ac75b1Sopenharmony_ci childClass: ts.ClassDeclaration, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 90507ac75b1Sopenharmony_ci const parentClassResult: ClassDecoratorResult = getClassDecoratorResult(parentNode); 90607ac75b1Sopenharmony_ci if (childClassResult.hasObservedV2 && parentClassResult.hasObserved) { 90707ac75b1Sopenharmony_ci const message: string = `Because the current class is decorated by '@ObservedV2', ` + 90807ac75b1Sopenharmony_ci `it can not inherit a class decorated by '@Observed'.`; 90907ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, childClass.getStart(), log, sourceFileNode); 91007ac75b1Sopenharmony_ci return; 91107ac75b1Sopenharmony_ci } 91207ac75b1Sopenharmony_ci if (childClassResult.hasObserved && parentClassResult.hasObservedV2) { 91307ac75b1Sopenharmony_ci const message: string = `Because the current class is decorated by '@Observed', ` + 91407ac75b1Sopenharmony_ci `it can not inherit a class decorated by '@ObservedV2'.`; 91507ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, childClass.getStart(), log, sourceFileNode); 91607ac75b1Sopenharmony_ci return; 91707ac75b1Sopenharmony_ci } 91807ac75b1Sopenharmony_ci} 91907ac75b1Sopenharmony_ci 92007ac75b1Sopenharmony_cifunction validateStructDecorator(sourceFileNode: ts.SourceFile, node: ts.Identifier, log: LogInfo[], 92107ac75b1Sopenharmony_ci structContext: boolean, decoratorName: string, isComponentV2: boolean): void { 92207ac75b1Sopenharmony_ci const name: string = `@${decoratorName}`; 92307ac75b1Sopenharmony_ci if (structContext) { 92407ac75b1Sopenharmony_ci if (isComponentV2) { 92507ac75b1Sopenharmony_ci if (constantDefine.COMPONENT_MEMBER_DECORATOR_V1.includes(name)) { 92607ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can only be used in a 'struct' decorated with '@Component'.`; 92707ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 92807ac75b1Sopenharmony_ci } 92907ac75b1Sopenharmony_ci } else if (constantDefine.DECORATOR_V2.includes(name)) { 93007ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can only be used in a 'struct' decorated with '@ComponentV2'.`; 93107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 93207ac75b1Sopenharmony_ci } 93307ac75b1Sopenharmony_ci } else if (STRUCT_DECORATORS.has(name) || constantDefine.COMPONENT_MEMBER_DECORATOR_V2.includes(name)) { 93407ac75b1Sopenharmony_ci const message: string = `The '@${decoratorName}' decorator can only be used with 'struct'.`; 93507ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 93607ac75b1Sopenharmony_ci } 93707ac75b1Sopenharmony_ci} 93807ac75b1Sopenharmony_ci 93907ac75b1Sopenharmony_cifunction validateMethodDecorator(sourceFileNode: ts.SourceFile, node: ts.Identifier, log: LogInfo[], 94007ac75b1Sopenharmony_ci structContext: boolean, decoratorName: string): void { 94107ac75b1Sopenharmony_ci let message: string; 94207ac75b1Sopenharmony_ci if (ts.isMethodDeclaration(node.parent.parent) || 94307ac75b1Sopenharmony_ci (ts.isDecorator(node.parent.parent) && ts.isMethodDeclaration(node.parent.parent.parent))) { 94407ac75b1Sopenharmony_ci if (!structContext && STRUCT_CONTEXT_METHOD_DECORATORS.has(`@${decoratorName}`)) { 94507ac75b1Sopenharmony_ci message = `The '@${decoratorName}' decorator can only be used in 'struct'.`; 94607ac75b1Sopenharmony_ci } 94707ac75b1Sopenharmony_ci if (CHECK_EXTEND_DECORATORS.includes(decoratorName)) { 94807ac75b1Sopenharmony_ci message = `The '@${decoratorName}' decorator can not be a member property method of a 'class' or 'struct'.`; 94907ac75b1Sopenharmony_ci } 95007ac75b1Sopenharmony_ci if (message) { 95107ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, node.pos, log, sourceFileNode); 95207ac75b1Sopenharmony_ci } 95307ac75b1Sopenharmony_ci } 95407ac75b1Sopenharmony_ci} 95507ac75b1Sopenharmony_ci 95607ac75b1Sopenharmony_ciexport function isSendableClassDeclaration(classDeclarationNode: ts.ClassDeclaration): boolean { 95707ac75b1Sopenharmony_ci return hasDecorator(classDeclarationNode, COMPONENT_SENDABLE_DECORATOR) || 95807ac75b1Sopenharmony_ci (classDeclarationNode.members && classDeclarationNode.members.some((member: ts.Node) => { 95907ac75b1Sopenharmony_ci // Check if the constructor has "use sendable" as the first statement 96007ac75b1Sopenharmony_ci // (Sendable classes already transformed by process_ui_syntax.ts) 96107ac75b1Sopenharmony_ci if (ts.isConstructorDeclaration(member)) { 96207ac75b1Sopenharmony_ci if (!(member as ts.ConstructorDeclaration).body || 96307ac75b1Sopenharmony_ci !(member as ts.ConstructorDeclaration).body.statements) { 96407ac75b1Sopenharmony_ci return false; 96507ac75b1Sopenharmony_ci } 96607ac75b1Sopenharmony_ci const constructorStatements: ts.Statement[] = (member as ts.ConstructorDeclaration).body.statements; 96707ac75b1Sopenharmony_ci if (constructorStatements && constructorStatements[0] && 96807ac75b1Sopenharmony_ci ts.isExpressionStatement(constructorStatements[0])) { 96907ac75b1Sopenharmony_ci const expression: ts.Node = (constructorStatements[0] as ts.ExpressionStatement).expression; 97007ac75b1Sopenharmony_ci return expression && ts.isStringLiteral(expression) && 97107ac75b1Sopenharmony_ci (expression as ts.StringLiteral).text === 'use sendable'; 97207ac75b1Sopenharmony_ci } 97307ac75b1Sopenharmony_ci } 97407ac75b1Sopenharmony_ci return false; 97507ac75b1Sopenharmony_ci })); 97607ac75b1Sopenharmony_ci} 97707ac75b1Sopenharmony_ci 97807ac75b1Sopenharmony_ciexport function checkAllNode( 97907ac75b1Sopenharmony_ci node: ts.EtsComponentExpression, 98007ac75b1Sopenharmony_ci allComponentNames: Set<string>, 98107ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, 98207ac75b1Sopenharmony_ci log: LogInfo[] 98307ac75b1Sopenharmony_ci): void { 98407ac75b1Sopenharmony_ci if (ts.isIdentifier(node.expression)) { 98507ac75b1Sopenharmony_ci checkNoChildComponent(node, sourceFileNode, log); 98607ac75b1Sopenharmony_ci checkOneChildComponent(node, allComponentNames, sourceFileNode, log); 98707ac75b1Sopenharmony_ci checkSpecificChildComponent(node, allComponentNames, sourceFileNode, log); 98807ac75b1Sopenharmony_ci } 98907ac75b1Sopenharmony_ci} 99007ac75b1Sopenharmony_ci 99107ac75b1Sopenharmony_ciinterface ParamType { 99207ac75b1Sopenharmony_ci name: string, 99307ac75b1Sopenharmony_ci value: string, 99407ac75b1Sopenharmony_ci} 99507ac75b1Sopenharmony_ci 99607ac75b1Sopenharmony_cifunction checkNoChildComponent(node: ts.EtsComponentExpression, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 99707ac75b1Sopenharmony_ci const isCheckType: ParamType = { name: null, value: null}; 99807ac75b1Sopenharmony_ci if (hasChild(node, isCheckType)) { 99907ac75b1Sopenharmony_ci const componentName: string = (node.expression as ts.Identifier).escapedText.toString(); 100007ac75b1Sopenharmony_ci const pos: number = node.expression.getStart(); 100107ac75b1Sopenharmony_ci const message: string = isCheckType.name === null ? 100207ac75b1Sopenharmony_ci `The component '${componentName}' can't have any child.` : 100307ac75b1Sopenharmony_ci `When the component '${componentName}' set '${isCheckType.name}' is '${isCheckType.value}'` + 100407ac75b1Sopenharmony_ci `, can't have any child.`; 100507ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, pos, log, sourceFileNode); 100607ac75b1Sopenharmony_ci } 100707ac75b1Sopenharmony_ci} 100807ac75b1Sopenharmony_ci 100907ac75b1Sopenharmony_cifunction hasChild(node: ts.EtsComponentExpression, isCheckType: ParamType): boolean { 101007ac75b1Sopenharmony_ci const nodeName: ts.Identifier = node.expression as ts.Identifier; 101107ac75b1Sopenharmony_ci if ((AUTOMIC_COMPONENT.has(nodeName.escapedText.toString()) || judgeComponentType(nodeName, node, isCheckType)) && 101207ac75b1Sopenharmony_ci getNextNode(node)) { 101307ac75b1Sopenharmony_ci return true; 101407ac75b1Sopenharmony_ci } 101507ac75b1Sopenharmony_ci return false; 101607ac75b1Sopenharmony_ci} 101707ac75b1Sopenharmony_ci 101807ac75b1Sopenharmony_cifunction judgeComponentType(nodeName: ts.Identifier, etsComponentExpression: ts.EtsComponentExpression, 101907ac75b1Sopenharmony_ci isCheckType: ParamType): boolean { 102007ac75b1Sopenharmony_ci return COMPONENT_TOGGLE === nodeName.escapedText.toString() && 102107ac75b1Sopenharmony_ci etsComponentExpression.arguments && etsComponentExpression.arguments[0] && 102207ac75b1Sopenharmony_ci ts.isObjectLiteralExpression(etsComponentExpression.arguments[0]) && 102307ac75b1Sopenharmony_ci etsComponentExpression.arguments[0].getText() && 102407ac75b1Sopenharmony_ci judgeToggleComponentParamType(etsComponentExpression.arguments[0].getText(), isCheckType); 102507ac75b1Sopenharmony_ci} 102607ac75b1Sopenharmony_ci 102707ac75b1Sopenharmony_cifunction judgeToggleComponentParamType(param: string, isCheckType: ParamType): boolean { 102807ac75b1Sopenharmony_ci if (param.indexOf(RESOURCE_NAME_TYPE) > -1) { 102907ac75b1Sopenharmony_ci isCheckType.name = RESOURCE_NAME_TYPE; 103007ac75b1Sopenharmony_ci const match: string[] = param.match(/\b(Checkbox|Switch|Button)\b/); 103107ac75b1Sopenharmony_ci if (match && match.length) { 103207ac75b1Sopenharmony_ci isCheckType.value = match[0]; 103307ac75b1Sopenharmony_ci if (isCheckType.value === COMPONENT_BUTTON) { 103407ac75b1Sopenharmony_ci return false; 103507ac75b1Sopenharmony_ci } 103607ac75b1Sopenharmony_ci return true; 103707ac75b1Sopenharmony_ci } 103807ac75b1Sopenharmony_ci } 103907ac75b1Sopenharmony_ci return false; 104007ac75b1Sopenharmony_ci} 104107ac75b1Sopenharmony_ci 104207ac75b1Sopenharmony_cifunction getNextNode(node: ts.EtsComponentExpression): ts.Block { 104307ac75b1Sopenharmony_ci if (node.body && ts.isBlock(node.body)) { 104407ac75b1Sopenharmony_ci const statementsArray: ts.Block = node.body; 104507ac75b1Sopenharmony_ci return statementsArray; 104607ac75b1Sopenharmony_ci } 104707ac75b1Sopenharmony_ci return undefined; 104807ac75b1Sopenharmony_ci} 104907ac75b1Sopenharmony_ci 105007ac75b1Sopenharmony_cifunction checkOneChildComponent(node: ts.EtsComponentExpression, allComponentNames: Set<string>, 105107ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 105207ac75b1Sopenharmony_ci const isCheckType: ParamType = { name: null, value: null}; 105307ac75b1Sopenharmony_ci if (hasNonSingleChild(node, allComponentNames, isCheckType)) { 105407ac75b1Sopenharmony_ci const componentName: string = (node.expression as ts.Identifier).escapedText.toString(); 105507ac75b1Sopenharmony_ci const pos: number = node.expression.getStart(); 105607ac75b1Sopenharmony_ci const message: string = isCheckType.name === null ? 105707ac75b1Sopenharmony_ci `The component '${componentName}' can only have a single child component.` : 105807ac75b1Sopenharmony_ci `When the component '${componentName}' set '${isCheckType.name}' is ` + 105907ac75b1Sopenharmony_ci `'${isCheckType.value}', can only have a single child component.`; 106007ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, pos, log, sourceFileNode); 106107ac75b1Sopenharmony_ci } 106207ac75b1Sopenharmony_ci} 106307ac75b1Sopenharmony_ci 106407ac75b1Sopenharmony_cifunction hasNonSingleChild(node: ts.EtsComponentExpression, allComponentNames: Set<string>, 106507ac75b1Sopenharmony_ci isCheckType: ParamType): boolean { 106607ac75b1Sopenharmony_ci const nodeName: ts.Identifier = node.expression as ts.Identifier; 106707ac75b1Sopenharmony_ci const blockNode: ts.Block = getNextNode(node); 106807ac75b1Sopenharmony_ci if (SINGLE_CHILD_COMPONENT.has(nodeName.escapedText.toString()) || !judgeComponentType(nodeName, node, isCheckType) && 106907ac75b1Sopenharmony_ci isCheckType.value === COMPONENT_BUTTON) { 107007ac75b1Sopenharmony_ci if (!blockNode) { 107107ac75b1Sopenharmony_ci return false; 107207ac75b1Sopenharmony_ci } 107307ac75b1Sopenharmony_ci if (blockNode && blockNode.statements) { 107407ac75b1Sopenharmony_ci const length: number = blockNode.statements.length; 107507ac75b1Sopenharmony_ci if (!length) { 107607ac75b1Sopenharmony_ci return false; 107707ac75b1Sopenharmony_ci } 107807ac75b1Sopenharmony_ci if (length > 3) { 107907ac75b1Sopenharmony_ci return true; 108007ac75b1Sopenharmony_ci } 108107ac75b1Sopenharmony_ci const childCount: number = getBlockChildrenCount(blockNode, allComponentNames); 108207ac75b1Sopenharmony_ci if (childCount > 1) { 108307ac75b1Sopenharmony_ci return true; 108407ac75b1Sopenharmony_ci } 108507ac75b1Sopenharmony_ci } 108607ac75b1Sopenharmony_ci } 108707ac75b1Sopenharmony_ci return false; 108807ac75b1Sopenharmony_ci} 108907ac75b1Sopenharmony_ci 109007ac75b1Sopenharmony_cifunction getBlockChildrenCount(blockNode: ts.Block, allComponentNames: Set<string>): number { 109107ac75b1Sopenharmony_ci let maxCount: number = 0; 109207ac75b1Sopenharmony_ci const length: number = blockNode.statements.length; 109307ac75b1Sopenharmony_ci for (let i = 0; i < length; ++i) { 109407ac75b1Sopenharmony_ci const item: ts.Node = blockNode.statements[i]; 109507ac75b1Sopenharmony_ci if (ts.isExpressionStatement(item) && ts.isCallExpression(item.expression) && 109607ac75b1Sopenharmony_ci isForEachComponent(item.expression)) { 109707ac75b1Sopenharmony_ci maxCount += 2; 109807ac75b1Sopenharmony_ci } 109907ac75b1Sopenharmony_ci if (ts.isIfStatement(item)) { 110007ac75b1Sopenharmony_ci maxCount += getIfChildrenCount(item, allComponentNames); 110107ac75b1Sopenharmony_ci } 110207ac75b1Sopenharmony_ci if (ts.isExpressionStatement(item) && ts.isEtsComponentExpression(item.expression)) { 110307ac75b1Sopenharmony_ci maxCount += 1; 110407ac75b1Sopenharmony_ci } 110507ac75b1Sopenharmony_ci if (ts.isExpressionStatement(item) && ts.isCallExpression(item.expression)) { 110607ac75b1Sopenharmony_ci let newNode = item.expression; 110707ac75b1Sopenharmony_ci while (newNode.expression) { 110807ac75b1Sopenharmony_ci if (ts.isEtsComponentExpression(newNode) || ts.isCallExpression(newNode) && 110907ac75b1Sopenharmony_ci isComponent(newNode, allComponentNames)) { 111007ac75b1Sopenharmony_ci maxCount += 1; 111107ac75b1Sopenharmony_ci } 111207ac75b1Sopenharmony_ci newNode = newNode.expression; 111307ac75b1Sopenharmony_ci } 111407ac75b1Sopenharmony_ci } 111507ac75b1Sopenharmony_ci if (maxCount > 1) { 111607ac75b1Sopenharmony_ci break; 111707ac75b1Sopenharmony_ci } 111807ac75b1Sopenharmony_ci } 111907ac75b1Sopenharmony_ci return maxCount; 112007ac75b1Sopenharmony_ci} 112107ac75b1Sopenharmony_ci 112207ac75b1Sopenharmony_cifunction isComponent(node: ts.EtsComponentExpression | ts.CallExpression, allComponentNames: Set<string>): boolean { 112307ac75b1Sopenharmony_ci if (ts.isIdentifier(node.expression) && 112407ac75b1Sopenharmony_ci allComponentNames.has(node.expression.escapedText.toString())) { 112507ac75b1Sopenharmony_ci return true; 112607ac75b1Sopenharmony_ci } 112707ac75b1Sopenharmony_ci return false; 112807ac75b1Sopenharmony_ci} 112907ac75b1Sopenharmony_ci 113007ac75b1Sopenharmony_cifunction isForEachComponent(node: ts.EtsComponentExpression | ts.CallExpression): boolean { 113107ac75b1Sopenharmony_ci if (ts.isIdentifier(node.expression)) { 113207ac75b1Sopenharmony_ci const componentName: string = node.expression.escapedText.toString(); 113307ac75b1Sopenharmony_ci return componentName === COMPONENT_FOREACH || componentName === COMPONENT_LAZYFOREACH; 113407ac75b1Sopenharmony_ci } 113507ac75b1Sopenharmony_ci return false; 113607ac75b1Sopenharmony_ci} 113707ac75b1Sopenharmony_ci 113807ac75b1Sopenharmony_cifunction getIfChildrenCount(ifNode: ts.IfStatement, allComponentNames: Set<string>): number { 113907ac75b1Sopenharmony_ci const maxCount: number = 114007ac75b1Sopenharmony_ci Math.max(getStatementCount(ifNode.thenStatement, allComponentNames), 114107ac75b1Sopenharmony_ci getStatementCount(ifNode.elseStatement, allComponentNames)); 114207ac75b1Sopenharmony_ci return maxCount; 114307ac75b1Sopenharmony_ci} 114407ac75b1Sopenharmony_ci 114507ac75b1Sopenharmony_cifunction getStatementCount(node: ts.Node, allComponentNames: Set<string>): number { 114607ac75b1Sopenharmony_ci let maxCount: number = 0; 114707ac75b1Sopenharmony_ci if (!node) { 114807ac75b1Sopenharmony_ci return maxCount; 114907ac75b1Sopenharmony_ci } else if (ts.isBlock(node)) { 115007ac75b1Sopenharmony_ci maxCount = getBlockChildrenCount(node, allComponentNames); 115107ac75b1Sopenharmony_ci } else if (ts.isIfStatement(node)) { 115207ac75b1Sopenharmony_ci maxCount = getIfChildrenCount(node, allComponentNames); 115307ac75b1Sopenharmony_ci } else if (ts.isExpressionStatement(node) && ts.isEtsComponentExpression(node.expression) && 115407ac75b1Sopenharmony_ci isForEachComponent(node.expression)) { 115507ac75b1Sopenharmony_ci maxCount = 2; 115607ac75b1Sopenharmony_ci } else if (ts.isExpressionStatement(node) && ts.isEtsComponentExpression(node.expression) && 115707ac75b1Sopenharmony_ci !isForEachComponent(node.expression) && isComponent(node.expression, allComponentNames)) { 115807ac75b1Sopenharmony_ci maxCount = 1; 115907ac75b1Sopenharmony_ci } 116007ac75b1Sopenharmony_ci return maxCount; 116107ac75b1Sopenharmony_ci} 116207ac75b1Sopenharmony_ci 116307ac75b1Sopenharmony_cifunction checkSpecificChildComponent(node: ts.EtsComponentExpression, allComponentNames: Set<string>, 116407ac75b1Sopenharmony_ci sourceFileNode: ts.SourceFile, log: LogInfo[]): void { 116507ac75b1Sopenharmony_ci if (hasNonspecificChild(node, allComponentNames)) { 116607ac75b1Sopenharmony_ci const componentName: string = (node.expression as ts.Identifier).escapedText.toString(); 116707ac75b1Sopenharmony_ci const pos: number = node.expression.getStart(); 116807ac75b1Sopenharmony_ci const specificChildArray: string = 116907ac75b1Sopenharmony_ci Array.from(SPECIFIC_CHILD_COMPONENT.get(componentName)).join(' and '); 117007ac75b1Sopenharmony_ci const message: string = 117107ac75b1Sopenharmony_ci `The component '${componentName}' can only have the child component ${specificChildArray}.`; 117207ac75b1Sopenharmony_ci addLog(LogType.ERROR, message, pos, log, sourceFileNode); 117307ac75b1Sopenharmony_ci } 117407ac75b1Sopenharmony_ci} 117507ac75b1Sopenharmony_ci 117607ac75b1Sopenharmony_cifunction hasNonspecificChild(node: ts.EtsComponentExpression, 117707ac75b1Sopenharmony_ci allComponentNames: Set<string>): boolean { 117807ac75b1Sopenharmony_ci const nodeName: ts.Identifier = node.expression as ts.Identifier; 117907ac75b1Sopenharmony_ci const nodeNameString: string = nodeName.escapedText.toString(); 118007ac75b1Sopenharmony_ci const blockNode: ts.Block = getNextNode(node); 118107ac75b1Sopenharmony_ci let isNonspecific: boolean = false; 118207ac75b1Sopenharmony_ci if (SPECIFIC_CHILD_COMPONENT.has(nodeNameString) && blockNode) { 118307ac75b1Sopenharmony_ci const specificChildSet: Set<string> = SPECIFIC_CHILD_COMPONENT.get(nodeNameString); 118407ac75b1Sopenharmony_ci isNonspecific = isNonspecificChildBlock(blockNode, specificChildSet, allComponentNames); 118507ac75b1Sopenharmony_ci if (isNonspecific) { 118607ac75b1Sopenharmony_ci return isNonspecific; 118707ac75b1Sopenharmony_ci } 118807ac75b1Sopenharmony_ci } 118907ac75b1Sopenharmony_ci return isNonspecific; 119007ac75b1Sopenharmony_ci} 119107ac75b1Sopenharmony_ci 119207ac75b1Sopenharmony_cifunction isNonspecificChildBlock(blockNode: ts.Block, specificChildSet: Set<string>, 119307ac75b1Sopenharmony_ci allComponentNames: Set<string>): boolean { 119407ac75b1Sopenharmony_ci if (blockNode.statements) { 119507ac75b1Sopenharmony_ci const length: number = blockNode.statements.length; 119607ac75b1Sopenharmony_ci for (let i = 0; i < length; ++i) { 119707ac75b1Sopenharmony_ci const item: ts.Node = blockNode.statements[i]; 119807ac75b1Sopenharmony_ci if (ts.isIfStatement(item) && isNonspecificChildIf(item, specificChildSet, allComponentNames)) { 119907ac75b1Sopenharmony_ci return true; 120007ac75b1Sopenharmony_ci } 120107ac75b1Sopenharmony_ci if (ts.isExpressionStatement(item) && ts.isCallExpression(item.expression) && 120207ac75b1Sopenharmony_ci isForEachComponent(item.expression) && 120307ac75b1Sopenharmony_ci isNonspecificChildForEach(item.expression, specificChildSet, allComponentNames)) { 120407ac75b1Sopenharmony_ci return true; 120507ac75b1Sopenharmony_ci } 120607ac75b1Sopenharmony_ci if (ts.isBlock(item) && isNonspecificChildBlock(item, specificChildSet, allComponentNames)) { 120707ac75b1Sopenharmony_ci return true; 120807ac75b1Sopenharmony_ci } 120907ac75b1Sopenharmony_ci if (ts.isExpressionStatement(item)) { 121007ac75b1Sopenharmony_ci let newNode: any = item.expression; 121107ac75b1Sopenharmony_ci while (newNode.expression) { 121207ac75b1Sopenharmony_ci if (ts.isEtsComponentExpression(newNode) && ts.isIdentifier(newNode.expression) && 121307ac75b1Sopenharmony_ci !isForEachComponent(newNode) && isComponent(newNode, allComponentNames)) { 121407ac75b1Sopenharmony_ci const isNonspecific: boolean = 121507ac75b1Sopenharmony_ci isNonspecificChildNonForEach(newNode, specificChildSet); 121607ac75b1Sopenharmony_ci if (isNonspecific) { 121707ac75b1Sopenharmony_ci return isNonspecific; 121807ac75b1Sopenharmony_ci } 121907ac75b1Sopenharmony_ci if (i + 1 < length && ts.isBlock(blockNode.statements[i + 1])) { 122007ac75b1Sopenharmony_ci ++i; 122107ac75b1Sopenharmony_ci } 122207ac75b1Sopenharmony_ci } 122307ac75b1Sopenharmony_ci newNode = newNode.expression; 122407ac75b1Sopenharmony_ci } 122507ac75b1Sopenharmony_ci } 122607ac75b1Sopenharmony_ci } 122707ac75b1Sopenharmony_ci } 122807ac75b1Sopenharmony_ci return false; 122907ac75b1Sopenharmony_ci} 123007ac75b1Sopenharmony_ci 123107ac75b1Sopenharmony_cifunction isNonspecificChildIf(node: ts.IfStatement, specificChildSet: Set<string>, 123207ac75b1Sopenharmony_ci allComponentNames: Set<string>): boolean { 123307ac75b1Sopenharmony_ci return isNonspecificChildIfStatement(node.thenStatement, specificChildSet, allComponentNames) || 123407ac75b1Sopenharmony_ci isNonspecificChildIfStatement(node.elseStatement, specificChildSet, allComponentNames); 123507ac75b1Sopenharmony_ci} 123607ac75b1Sopenharmony_ci 123707ac75b1Sopenharmony_cifunction isNonspecificChildForEach(node: ts.EtsComponentExpression, specificChildSet: Set<string>, 123807ac75b1Sopenharmony_ci allComponentNames: Set<string>): boolean { 123907ac75b1Sopenharmony_ci if (ts.isCallExpression(node) && node.arguments && 124007ac75b1Sopenharmony_ci node.arguments.length > 1 && ts.isArrowFunction(node.arguments[1])) { 124107ac75b1Sopenharmony_ci const arrowFunction: ts.ArrowFunction = node.arguments[1] as ts.ArrowFunction; 124207ac75b1Sopenharmony_ci const body: ts.Block | ts.EtsComponentExpression | ts.IfStatement = 124307ac75b1Sopenharmony_ci arrowFunction.body as ts.Block | ts.EtsComponentExpression | ts.IfStatement; 124407ac75b1Sopenharmony_ci if (!body) { 124507ac75b1Sopenharmony_ci return false; 124607ac75b1Sopenharmony_ci } 124707ac75b1Sopenharmony_ci if (ts.isBlock(body) && isNonspecificChildBlock(body, specificChildSet, allComponentNames)) { 124807ac75b1Sopenharmony_ci return true; 124907ac75b1Sopenharmony_ci } 125007ac75b1Sopenharmony_ci if (ts.isIfStatement(body) && isNonspecificChildIf(body, specificChildSet, allComponentNames)) { 125107ac75b1Sopenharmony_ci return true; 125207ac75b1Sopenharmony_ci } 125307ac75b1Sopenharmony_ci if (ts.isCallExpression(body) && isForEachComponent(body) && 125407ac75b1Sopenharmony_ci isNonspecificChildForEach(body, specificChildSet, allComponentNames)) { 125507ac75b1Sopenharmony_ci return true; 125607ac75b1Sopenharmony_ci } 125707ac75b1Sopenharmony_ci if (ts.isEtsComponentExpression(body) && !isForEachComponent(body) && 125807ac75b1Sopenharmony_ci isComponent(body, allComponentNames) && 125907ac75b1Sopenharmony_ci isNonspecificChildNonForEach(body, specificChildSet)) { 126007ac75b1Sopenharmony_ci return true; 126107ac75b1Sopenharmony_ci } 126207ac75b1Sopenharmony_ci } 126307ac75b1Sopenharmony_ci return false; 126407ac75b1Sopenharmony_ci} 126507ac75b1Sopenharmony_ci 126607ac75b1Sopenharmony_cifunction isNonspecificChildNonForEach(node: ts.EtsComponentExpression, 126707ac75b1Sopenharmony_ci specificChildSet: Set<string>): boolean { 126807ac75b1Sopenharmony_ci if (ts.isIdentifier(node.expression) && 126907ac75b1Sopenharmony_ci !specificChildSet.has(node.expression.escapedText.toString())) { 127007ac75b1Sopenharmony_ci return true; 127107ac75b1Sopenharmony_ci } 127207ac75b1Sopenharmony_ci return false; 127307ac75b1Sopenharmony_ci} 127407ac75b1Sopenharmony_ci 127507ac75b1Sopenharmony_cifunction isNonspecificChildIfStatement(node: ts.Node, specificChildSet: Set<string>, 127607ac75b1Sopenharmony_ci allComponentNames: Set<string>): boolean { 127707ac75b1Sopenharmony_ci if (!node) { 127807ac75b1Sopenharmony_ci return false; 127907ac75b1Sopenharmony_ci } 128007ac75b1Sopenharmony_ci if (ts.isBlock(node) && isNonspecificChildBlock(node, specificChildSet, allComponentNames)) { 128107ac75b1Sopenharmony_ci return true; 128207ac75b1Sopenharmony_ci } 128307ac75b1Sopenharmony_ci if (ts.isIfStatement(node) && isNonspecificChildIf(node, specificChildSet, allComponentNames)) { 128407ac75b1Sopenharmony_ci return true; 128507ac75b1Sopenharmony_ci } 128607ac75b1Sopenharmony_ci if (ts.isExpressionStatement(node) && ts.isEtsComponentExpression(node.expression) && 128707ac75b1Sopenharmony_ci isForEachComponent(node.expression) && 128807ac75b1Sopenharmony_ci isNonspecificChildForEach(node.expression, specificChildSet, allComponentNames)) { 128907ac75b1Sopenharmony_ci return true; 129007ac75b1Sopenharmony_ci } 129107ac75b1Sopenharmony_ci if (ts.isExpressionStatement(node) && ts.isEtsComponentExpression(node.expression) && 129207ac75b1Sopenharmony_ci !isForEachComponent(node.expression) && isComponent(node.expression, allComponentNames) && 129307ac75b1Sopenharmony_ci isNonspecificChildNonForEach(node.expression, specificChildSet)) { 129407ac75b1Sopenharmony_ci return true; 129507ac75b1Sopenharmony_ci } 129607ac75b1Sopenharmony_ci return false; 129707ac75b1Sopenharmony_ci} 129807ac75b1Sopenharmony_ci 129907ac75b1Sopenharmony_cifunction collectComponentProps(node: ts.StructDeclaration, structInfo: StructInfo): void { 130007ac75b1Sopenharmony_ci const componentName: string = node.name.getText(); 130107ac75b1Sopenharmony_ci const componentSet: IComponentSet = getComponentSet(node, true); 130207ac75b1Sopenharmony_ci propertyCollection.set(componentName, componentSet.properties); 130307ac75b1Sopenharmony_ci stateCollection.set(componentName, componentSet.states); 130407ac75b1Sopenharmony_ci linkCollection.set(componentName, componentSet.links); 130507ac75b1Sopenharmony_ci storedFileInfo.overallLinkCollection.set(componentName, componentSet.links); 130607ac75b1Sopenharmony_ci propCollection.set(componentName, componentSet.props); 130707ac75b1Sopenharmony_ci regularCollection.set(componentName, componentSet.regulars); 130807ac75b1Sopenharmony_ci storagePropCollection.set(componentName, componentSet.storageProps); 130907ac75b1Sopenharmony_ci storageLinkCollection.set(componentName, componentSet.storageLinks); 131007ac75b1Sopenharmony_ci provideCollection.set(componentName, componentSet.provides); 131107ac75b1Sopenharmony_ci consumeCollection.set(componentName, componentSet.consumes); 131207ac75b1Sopenharmony_ci objectLinkCollection.set(componentName, componentSet.objectLinks); 131307ac75b1Sopenharmony_ci storedFileInfo.overallObjectLinkCollection.set(componentName, componentSet.objectLinks); 131407ac75b1Sopenharmony_ci localStorageLinkCollection.set(componentName, componentSet.localStorageLink); 131507ac75b1Sopenharmony_ci localStoragePropCollection.set(componentName, componentSet.localStorageProp); 131607ac75b1Sopenharmony_ci builderParamObjectCollection.set(componentName, componentSet.builderParams); 131707ac75b1Sopenharmony_ci builderParamInitialization.set(componentName, componentSet.builderParamData); 131807ac75b1Sopenharmony_ci propInitialization.set(componentName, componentSet.propData); 131907ac75b1Sopenharmony_ci regularInitialization.set(componentName, componentSet.regularInit); 132007ac75b1Sopenharmony_ci stateInitialization.set(componentName, componentSet.stateInit); 132107ac75b1Sopenharmony_ci provideInitialization.set(componentName, componentSet.provideInit); 132207ac75b1Sopenharmony_ci privateCollection.set(componentName, componentSet.privateCollection); 132307ac75b1Sopenharmony_ci structInfo.updatePropsDecoratorsV1.push( 132407ac75b1Sopenharmony_ci ...componentSet.states, ...componentSet.props, 132507ac75b1Sopenharmony_ci ...componentSet.provides, ...componentSet.objectLinks 132607ac75b1Sopenharmony_ci ); 132707ac75b1Sopenharmony_ci structInfo.linkDecoratorsV1.push(...componentSet.links); 132807ac75b1Sopenharmony_ci} 132907ac75b1Sopenharmony_ci 133007ac75b1Sopenharmony_ciexport function getComponentSet(node: ts.StructDeclaration, uiCheck: boolean = false): IComponentSet { 133107ac75b1Sopenharmony_ci const componentSet: IComponentSet = new IComponentSet(); 133207ac75b1Sopenharmony_ci traversalComponentProps(node, componentSet, uiCheck); 133307ac75b1Sopenharmony_ci return componentSet; 133407ac75b1Sopenharmony_ci} 133507ac75b1Sopenharmony_ci 133607ac75b1Sopenharmony_ciclass RecordRequire { 133707ac75b1Sopenharmony_ci hasRequire: boolean = false; 133807ac75b1Sopenharmony_ci hasProp: boolean = false; 133907ac75b1Sopenharmony_ci hasBuilderParam: boolean = false; 134007ac75b1Sopenharmony_ci hasRegular: boolean = false; 134107ac75b1Sopenharmony_ci hasState: boolean = false; 134207ac75b1Sopenharmony_ci hasProvide: boolean = false; 134307ac75b1Sopenharmony_ci} 134407ac75b1Sopenharmony_ci 134507ac75b1Sopenharmony_cifunction traversalComponentProps(node: ts.StructDeclaration, componentSet: IComponentSet, 134607ac75b1Sopenharmony_ci uiCheck: boolean = false): void { 134707ac75b1Sopenharmony_ci let isStatic: boolean = true; 134807ac75b1Sopenharmony_ci if (node.members) { 134907ac75b1Sopenharmony_ci const currentMethodCollection: Set<string> = new Set(); 135007ac75b1Sopenharmony_ci node.members.forEach(item => { 135107ac75b1Sopenharmony_ci if (ts.isPropertyDeclaration(item) && ts.isIdentifier(item.name)) { 135207ac75b1Sopenharmony_ci const propertyName: string = item.name.getText(); 135307ac75b1Sopenharmony_ci componentSet.properties.add(propertyName); 135407ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(item); 135507ac75b1Sopenharmony_ci const accessQualifierResult: AccessQualifierResult = getAccessQualifier(item, uiCheck); 135607ac75b1Sopenharmony_ci if (!decorators || !decorators.length) { 135707ac75b1Sopenharmony_ci componentSet.regulars.add(propertyName); 135807ac75b1Sopenharmony_ci setPrivateCollection(componentSet, accessQualifierResult, propertyName, COMPONENT_NON_DECORATOR); 135907ac75b1Sopenharmony_ci } else { 136007ac75b1Sopenharmony_ci isStatic = false; 136107ac75b1Sopenharmony_ci let hasValidatePrivate: boolean = false; 136207ac75b1Sopenharmony_ci const recordRequire: RecordRequire = new RecordRequire(); 136307ac75b1Sopenharmony_ci for (let i = 0; i < decorators.length; i++) { 136407ac75b1Sopenharmony_ci const decoratorName: string = decorators[i].getText().replace(/\(.*\)$/, '').trim(); 136507ac75b1Sopenharmony_ci if (INNER_COMPONENT_MEMBER_DECORATORS.has(decoratorName)) { 136607ac75b1Sopenharmony_ci dollarCollection.add('$' + propertyName); 136707ac75b1Sopenharmony_ci collectionStates(decorators[i], decoratorName, propertyName, 136807ac75b1Sopenharmony_ci componentSet, recordRequire); 136907ac75b1Sopenharmony_ci setPrivateCollection(componentSet, accessQualifierResult, propertyName, decoratorName); 137007ac75b1Sopenharmony_ci validateAccessQualifier(item, propertyName, decoratorName, accessQualifierResult, 137107ac75b1Sopenharmony_ci recordRequire, uiCheck, hasValidatePrivate); 137207ac75b1Sopenharmony_ci hasValidatePrivate = true; 137307ac75b1Sopenharmony_ci } 137407ac75b1Sopenharmony_ci } 137507ac75b1Sopenharmony_ci regularAndRequire(decorators, componentSet, recordRequire, propertyName, accessQualifierResult); 137607ac75b1Sopenharmony_ci checkRequire(propertyName, componentSet, recordRequire); 137707ac75b1Sopenharmony_ci } 137807ac75b1Sopenharmony_ci } 137907ac75b1Sopenharmony_ci if (ts.isMethodDeclaration(item) && item.name && ts.isIdentifier(item.name)) { 138007ac75b1Sopenharmony_ci validateStateVariable(item); 138107ac75b1Sopenharmony_ci currentMethodCollection.add(item.name.getText()); 138207ac75b1Sopenharmony_ci } 138307ac75b1Sopenharmony_ci }); 138407ac75b1Sopenharmony_ci collectCurrentClassMethod(node, currentMethodCollection); 138507ac75b1Sopenharmony_ci } 138607ac75b1Sopenharmony_ci isStaticViewCollection.set(node.name.getText(), isStatic); 138707ac75b1Sopenharmony_ci} 138807ac75b1Sopenharmony_ci 138907ac75b1Sopenharmony_cifunction collectCurrentClassMethod(node: ts.StructDeclaration, currentMethodCollection: Set<string>): void { 139007ac75b1Sopenharmony_ci const componentMethodCollection: Map<string, Set<string>> = new Map(); 139107ac75b1Sopenharmony_ci componentMethodCollection.set(node.name.getText(), currentMethodCollection); 139207ac75b1Sopenharmony_ci const sourceFile: ts.SourceFile = node.getSourceFile(); 139307ac75b1Sopenharmony_ci const filePath: string = sourceFile ? sourceFile.fileName : undefined; 139407ac75b1Sopenharmony_ci if (filePath) { 139507ac75b1Sopenharmony_ci const pageMethodCollection: Map<string, Set<string>> = classMethodCollection.get(filePath); 139607ac75b1Sopenharmony_ci if (!pageMethodCollection) { 139707ac75b1Sopenharmony_ci classMethodCollection.set(filePath, componentMethodCollection); 139807ac75b1Sopenharmony_ci } else if (!pageMethodCollection.get(node.name.getText())) { 139907ac75b1Sopenharmony_ci pageMethodCollection.set(node.name.getText(), currentMethodCollection); 140007ac75b1Sopenharmony_ci } 140107ac75b1Sopenharmony_ci } 140207ac75b1Sopenharmony_ci} 140307ac75b1Sopenharmony_ci 140407ac75b1Sopenharmony_ciconst FORBIDDEN_PUBLIC_ACCESS: string[] = [COMPONENT_STORAGE_PROP_DECORATOR, 140507ac75b1Sopenharmony_ci COMPONENT_STORAGE_LINK_DECORATOR, COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, 140607ac75b1Sopenharmony_ci COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, COMPONENT_CONSUME_DECORATOR 140707ac75b1Sopenharmony_ci]; 140807ac75b1Sopenharmony_ciconst FORBIDDEN_PRIVATE_ACCESS: string[] = [COMPONENT_LINK_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR]; 140907ac75b1Sopenharmony_ci 141007ac75b1Sopenharmony_cifunction validateAccessQualifier(node: ts.PropertyDeclaration, propertyName: string, 141107ac75b1Sopenharmony_ci decoratorName: string, accessQualifierResult: AccessQualifierResult, 141207ac75b1Sopenharmony_ci recordRequire: RecordRequire, uiCheck: boolean = false, hasValidatePrivate: boolean): void { 141307ac75b1Sopenharmony_ci if (uiCheck) { 141407ac75b1Sopenharmony_ci if (accessQualifierResult.hasPublic && FORBIDDEN_PUBLIC_ACCESS.includes(decoratorName)) { 141507ac75b1Sopenharmony_ci transformLog.errors.push({ 141607ac75b1Sopenharmony_ci type: LogType.WARN, 141707ac75b1Sopenharmony_ci message: `Property '${propertyName}' can not be decorated with both ${decoratorName} and public.`, 141807ac75b1Sopenharmony_ci pos: node.getStart() 141907ac75b1Sopenharmony_ci }); 142007ac75b1Sopenharmony_ci } 142107ac75b1Sopenharmony_ci if (accessQualifierResult.hasPrivate) { 142207ac75b1Sopenharmony_ci if (FORBIDDEN_PRIVATE_ACCESS.includes(decoratorName)) { 142307ac75b1Sopenharmony_ci transformLog.errors.push({ 142407ac75b1Sopenharmony_ci type: LogType.WARN, 142507ac75b1Sopenharmony_ci message: `Property '${propertyName}' can not be decorated with both ${decoratorName} and private.`, 142607ac75b1Sopenharmony_ci pos: node.getStart() 142707ac75b1Sopenharmony_ci }); 142807ac75b1Sopenharmony_ci } 142907ac75b1Sopenharmony_ci if (recordRequire.hasRequire && !hasValidatePrivate) { 143007ac75b1Sopenharmony_ci transformLog.errors.push({ 143107ac75b1Sopenharmony_ci type: LogType.WARN, 143207ac75b1Sopenharmony_ci message: `Property '${propertyName}' can not be decorated with both @Require and private.`, 143307ac75b1Sopenharmony_ci pos: node.getStart() 143407ac75b1Sopenharmony_ci }); 143507ac75b1Sopenharmony_ci } 143607ac75b1Sopenharmony_ci } 143707ac75b1Sopenharmony_ci } 143807ac75b1Sopenharmony_ci} 143907ac75b1Sopenharmony_ci 144007ac75b1Sopenharmony_ciconst SUPPORT_PRIVATE_PROPS: string[] = [COMPONENT_NON_DECORATOR, COMPONENT_STATE_DECORATOR, 144107ac75b1Sopenharmony_ci COMPONENT_PROP_DECORATOR, COMPONENT_PROVIDE_DECORATOR, COMPONENT_BUILDERPARAM_DECORATOR 144207ac75b1Sopenharmony_ci]; 144307ac75b1Sopenharmony_ci 144407ac75b1Sopenharmony_cifunction setPrivateCollection(componentSet: IComponentSet, accessQualifierResult: AccessQualifierResult, 144507ac75b1Sopenharmony_ci propertyName: string, decoratorName: string): void { 144607ac75b1Sopenharmony_ci if (accessQualifierResult.hasPrivate && SUPPORT_PRIVATE_PROPS.includes(decoratorName)) { 144707ac75b1Sopenharmony_ci componentSet.privateCollection.add(propertyName); 144807ac75b1Sopenharmony_ci } 144907ac75b1Sopenharmony_ci} 145007ac75b1Sopenharmony_ci 145107ac75b1Sopenharmony_ciclass AccessQualifierResult { 145207ac75b1Sopenharmony_ci hasPrivate: boolean = false; 145307ac75b1Sopenharmony_ci hasPublic: boolean = false; 145407ac75b1Sopenharmony_ci} 145507ac75b1Sopenharmony_ci 145607ac75b1Sopenharmony_cifunction getAccessQualifier(node: ts.PropertyDeclaration, uiCheck: boolean = false): AccessQualifierResult { 145707ac75b1Sopenharmony_ci const modifiers: readonly ts.Modifier[] = ts.getModifiers(node); 145807ac75b1Sopenharmony_ci const accessQualifierResult: AccessQualifierResult = new AccessQualifierResult(); 145907ac75b1Sopenharmony_ci if (modifiers && modifiers.length) { 146007ac75b1Sopenharmony_ci modifiers.forEach((item) => { 146107ac75b1Sopenharmony_ci if (item.kind === ts.SyntaxKind.PrivateKeyword) { 146207ac75b1Sopenharmony_ci accessQualifierResult.hasPrivate = true; 146307ac75b1Sopenharmony_ci } 146407ac75b1Sopenharmony_ci if (item.kind === ts.SyntaxKind.PublicKeyword) { 146507ac75b1Sopenharmony_ci accessQualifierResult.hasPublic = true; 146607ac75b1Sopenharmony_ci } 146707ac75b1Sopenharmony_ci if (uiCheck && item.kind === ts.SyntaxKind.ProtectedKeyword) { 146807ac75b1Sopenharmony_ci transformLog.errors.push({ 146907ac75b1Sopenharmony_ci type: LogType.WARN, 147007ac75b1Sopenharmony_ci message: `The member attributes of a struct can not be protected.`, 147107ac75b1Sopenharmony_ci pos: node.getStart() 147207ac75b1Sopenharmony_ci }); 147307ac75b1Sopenharmony_ci } 147407ac75b1Sopenharmony_ci }); 147507ac75b1Sopenharmony_ci } 147607ac75b1Sopenharmony_ci return accessQualifierResult; 147707ac75b1Sopenharmony_ci} 147807ac75b1Sopenharmony_ci 147907ac75b1Sopenharmony_cifunction regularAndRequire(decorators: readonly ts.Decorator[], componentSet: IComponentSet, 148007ac75b1Sopenharmony_ci recordRequire: RecordRequire, propertyName: string, accessQualifierResult: AccessQualifierResult): void { 148107ac75b1Sopenharmony_ci if (decorators && decorators.length === 1 && decorators[0].getText() === COMPONENT_REQUIRE_DECORATOR) { 148207ac75b1Sopenharmony_ci componentSet.regulars.add(propertyName); 148307ac75b1Sopenharmony_ci recordRequire.hasRegular = true; 148407ac75b1Sopenharmony_ci setPrivateCollection(componentSet, accessQualifierResult, propertyName, COMPONENT_NON_DECORATOR); 148507ac75b1Sopenharmony_ci } 148607ac75b1Sopenharmony_ci} 148707ac75b1Sopenharmony_ci 148807ac75b1Sopenharmony_cifunction checkRequire(name: string, componentSet: IComponentSet, recordRequire: RecordRequire): void { 148907ac75b1Sopenharmony_ci if (recordRequire.hasRequire) { 149007ac75b1Sopenharmony_ci setInitValue('hasProp', 'propData', name, componentSet, recordRequire); 149107ac75b1Sopenharmony_ci setInitValue('hasBuilderParam', 'builderParamData', name, componentSet, recordRequire); 149207ac75b1Sopenharmony_ci setInitValue('hasRegular', 'regularInit', name, componentSet, recordRequire); 149307ac75b1Sopenharmony_ci setInitValue('hasState', 'stateInit', name, componentSet, recordRequire); 149407ac75b1Sopenharmony_ci setInitValue('hasProvide', 'provideInit', name, componentSet, recordRequire); 149507ac75b1Sopenharmony_ci } 149607ac75b1Sopenharmony_ci} 149707ac75b1Sopenharmony_ci 149807ac75b1Sopenharmony_cifunction setInitValue(requirekey: string, initKey: string, name: string, componentSet: IComponentSet, 149907ac75b1Sopenharmony_ci recordRequire: RecordRequire): void { 150007ac75b1Sopenharmony_ci if (recordRequire[requirekey]) { 150107ac75b1Sopenharmony_ci componentSet[initKey].add(name); 150207ac75b1Sopenharmony_ci } 150307ac75b1Sopenharmony_ci} 150407ac75b1Sopenharmony_ci 150507ac75b1Sopenharmony_cifunction collectionStates(node: ts.Decorator, decorator: string, name: string, 150607ac75b1Sopenharmony_ci componentSet: IComponentSet, recordRequire: RecordRequire): void { 150707ac75b1Sopenharmony_ci switch (decorator) { 150807ac75b1Sopenharmony_ci case COMPONENT_STATE_DECORATOR: 150907ac75b1Sopenharmony_ci componentSet.states.add(name); 151007ac75b1Sopenharmony_ci recordRequire.hasState = true; 151107ac75b1Sopenharmony_ci break; 151207ac75b1Sopenharmony_ci case COMPONENT_LINK_DECORATOR: 151307ac75b1Sopenharmony_ci componentSet.links.add(name); 151407ac75b1Sopenharmony_ci break; 151507ac75b1Sopenharmony_ci case COMPONENT_PROP_DECORATOR: 151607ac75b1Sopenharmony_ci recordRequire.hasProp = true; 151707ac75b1Sopenharmony_ci componentSet.props.add(name); 151807ac75b1Sopenharmony_ci break; 151907ac75b1Sopenharmony_ci case COMPONENT_STORAGE_PROP_DECORATOR: 152007ac75b1Sopenharmony_ci componentSet.storageProps.add(name); 152107ac75b1Sopenharmony_ci break; 152207ac75b1Sopenharmony_ci case COMPONENT_STORAGE_LINK_DECORATOR: 152307ac75b1Sopenharmony_ci componentSet.storageLinks.add(name); 152407ac75b1Sopenharmony_ci break; 152507ac75b1Sopenharmony_ci case COMPONENT_PROVIDE_DECORATOR: 152607ac75b1Sopenharmony_ci recordRequire.hasProvide = true; 152707ac75b1Sopenharmony_ci componentSet.provides.add(name); 152807ac75b1Sopenharmony_ci break; 152907ac75b1Sopenharmony_ci case COMPONENT_CONSUME_DECORATOR: 153007ac75b1Sopenharmony_ci componentSet.consumes.add(name); 153107ac75b1Sopenharmony_ci break; 153207ac75b1Sopenharmony_ci case COMPONENT_OBJECT_LINK_DECORATOR: 153307ac75b1Sopenharmony_ci componentSet.objectLinks.add(name); 153407ac75b1Sopenharmony_ci break; 153507ac75b1Sopenharmony_ci case COMPONENT_BUILDERPARAM_DECORATOR: 153607ac75b1Sopenharmony_ci recordRequire.hasBuilderParam = true; 153707ac75b1Sopenharmony_ci componentSet.builderParams.add(name); 153807ac75b1Sopenharmony_ci break; 153907ac75b1Sopenharmony_ci case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR : 154007ac75b1Sopenharmony_ci collectionlocalStorageParam(node, name, componentSet.localStorageLink); 154107ac75b1Sopenharmony_ci break; 154207ac75b1Sopenharmony_ci case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: 154307ac75b1Sopenharmony_ci collectionlocalStorageParam(node, name, componentSet.localStorageProp); 154407ac75b1Sopenharmony_ci break; 154507ac75b1Sopenharmony_ci case COMPONENT_REQUIRE_DECORATOR: 154607ac75b1Sopenharmony_ci recordRequire.hasRequire = true; 154707ac75b1Sopenharmony_ci break; 154807ac75b1Sopenharmony_ci } 154907ac75b1Sopenharmony_ci} 155007ac75b1Sopenharmony_ci 155107ac75b1Sopenharmony_cifunction collectionlocalStorageParam(node: ts.Decorator, name: string, 155207ac75b1Sopenharmony_ci localStorage: Map<string, Set<string>>): void { 155307ac75b1Sopenharmony_ci const localStorageParam: Set<string> = new Set(); 155407ac75b1Sopenharmony_ci if (node && ts.isCallExpression(node.expression) && node.expression.arguments && 155507ac75b1Sopenharmony_ci node.expression.arguments.length) { 155607ac75b1Sopenharmony_ci localStorage.set(name, localStorageParam.add( 155707ac75b1Sopenharmony_ci node.expression.arguments[0].getText())); 155807ac75b1Sopenharmony_ci } 155907ac75b1Sopenharmony_ci} 156007ac75b1Sopenharmony_ci 156107ac75b1Sopenharmony_ciexport interface ReplaceResult { 156207ac75b1Sopenharmony_ci content: string, 156307ac75b1Sopenharmony_ci log: LogInfo[] 156407ac75b1Sopenharmony_ci} 156507ac75b1Sopenharmony_ci 156607ac75b1Sopenharmony_ciexport function sourceReplace(source: string, sourcePath: string): ReplaceResult { 156707ac75b1Sopenharmony_ci let content: string = source; 156807ac75b1Sopenharmony_ci const log: LogInfo[] = []; 156907ac75b1Sopenharmony_ci content = preprocessExtend(content); 157007ac75b1Sopenharmony_ci content = preprocessNewExtend(content); 157107ac75b1Sopenharmony_ci // process @system. 157207ac75b1Sopenharmony_ci content = processSystemApi(content, false, sourcePath); 157307ac75b1Sopenharmony_ci collectImportNames(content, sourcePath); 157407ac75b1Sopenharmony_ci 157507ac75b1Sopenharmony_ci return { 157607ac75b1Sopenharmony_ci content: content, 157707ac75b1Sopenharmony_ci log: log 157807ac75b1Sopenharmony_ci }; 157907ac75b1Sopenharmony_ci} 158007ac75b1Sopenharmony_ci 158107ac75b1Sopenharmony_ciexport function preprocessExtend(content: string, extendCollection?: Set<string>): string { 158207ac75b1Sopenharmony_ci const REG_EXTEND: RegExp = /@Extend(\s+)([^\.\s]+)\.([^\(]+)\(/gm; 158307ac75b1Sopenharmony_ci return content.replace(REG_EXTEND, (item, item1, item2, item3) => { 158407ac75b1Sopenharmony_ci collectExtend(EXTEND_ATTRIBUTE, item2, '__' + item2 + '__' + item3); 158507ac75b1Sopenharmony_ci collectExtend(EXTEND_ATTRIBUTE, item2, item3); 158607ac75b1Sopenharmony_ci if (extendCollection) { 158707ac75b1Sopenharmony_ci extendCollection.add(item3); 158807ac75b1Sopenharmony_ci } 158907ac75b1Sopenharmony_ci return `@Extend(${item2})${item1}function __${item2}__${item3}(`; 159007ac75b1Sopenharmony_ci }); 159107ac75b1Sopenharmony_ci} 159207ac75b1Sopenharmony_ci 159307ac75b1Sopenharmony_ciexport function preprocessNewExtend(content: string, extendCollection?: Set<string>): string { 159407ac75b1Sopenharmony_ci const REG_EXTEND: RegExp = /@Extend\s*\([^\)]+\)\s*function\s+([^\(\s]+)\s*\(/gm; 159507ac75b1Sopenharmony_ci return content.replace(REG_EXTEND, (item, item1) => { 159607ac75b1Sopenharmony_ci if (extendCollection) { 159707ac75b1Sopenharmony_ci extendCollection.add(item1); 159807ac75b1Sopenharmony_ci } 159907ac75b1Sopenharmony_ci return item; 160007ac75b1Sopenharmony_ci }); 160107ac75b1Sopenharmony_ci} 160207ac75b1Sopenharmony_ci 160307ac75b1Sopenharmony_cifunction replaceSystemApi(item: string, systemValue: string, moduleType: string, systemKey: string): string { 160407ac75b1Sopenharmony_ci // if change format, please update regexp in transformModuleSpecifier 160507ac75b1Sopenharmony_ci if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) { 160607ac75b1Sopenharmony_ci item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; 160707ac75b1Sopenharmony_ci } else if (moduleType === SYSTEM_PLUGIN || moduleType === OHOS_PLUGIN) { 160807ac75b1Sopenharmony_ci item = `var ${systemValue} = globalThis.requireNapi('${systemKey}')`; 160907ac75b1Sopenharmony_ci } 161007ac75b1Sopenharmony_ci return item; 161107ac75b1Sopenharmony_ci} 161207ac75b1Sopenharmony_ci 161307ac75b1Sopenharmony_cifunction replaceLibSo(importValue: string, libSoKey: string, sourcePath: string = null): string { 161407ac75b1Sopenharmony_ci if (sourcePath) { 161507ac75b1Sopenharmony_ci useOSFiles.add(sourcePath); 161607ac75b1Sopenharmony_ci } 161707ac75b1Sopenharmony_ci // if change format, please update regexp in transformModuleSpecifier 161807ac75b1Sopenharmony_ci return projectConfig.bundleName && projectConfig.moduleName ? 161907ac75b1Sopenharmony_ci `var ${importValue} = globalThis.requireNapi("${libSoKey}", true, "${projectConfig.bundleName}/${projectConfig.moduleName}");` : 162007ac75b1Sopenharmony_ci `var ${importValue} = globalThis.requireNapi("${libSoKey}", true);`; 162107ac75b1Sopenharmony_ci} 162207ac75b1Sopenharmony_ci 162307ac75b1Sopenharmony_ciexport function processSystemApi(content: string, isProcessAllowList: boolean = false, 162407ac75b1Sopenharmony_ci sourcePath: string = null, isSystemModule: boolean = false): string { 162507ac75b1Sopenharmony_ci if (isProcessAllowList && projectConfig.compileMode === ESMODULE) { 162607ac75b1Sopenharmony_ci // remove the unused system api import decl like following when compile as [esmodule] 162707ac75b1Sopenharmony_ci // in the result_process phase 162807ac75b1Sopenharmony_ci // e.g. import "@ohos.application.xxx" 162907ac75b1Sopenharmony_ci const REG_UNUSED_SYSTEM_IMPORT: RegExp = /import(?:\s*)['"]@(system|ohos)\.(\S+)['"]/g; 163007ac75b1Sopenharmony_ci content = content.replace(REG_UNUSED_SYSTEM_IMPORT, ''); 163107ac75b1Sopenharmony_ci } 163207ac75b1Sopenharmony_ci 163307ac75b1Sopenharmony_ci const REG_IMPORT_DECL: RegExp = isProcessAllowList ? projectConfig.compileMode === ESMODULE ? 163407ac75b1Sopenharmony_ci /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]/g : 163507ac75b1Sopenharmony_ci /(import|const)\s+(.+)\s*=\s*(\_\_importDefault\()?require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)(\))?/g : 163607ac75b1Sopenharmony_ci /(import|export)\s+(?:(.+)|\{([\s\S]+)\})\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; 163707ac75b1Sopenharmony_ci 163807ac75b1Sopenharmony_ci const systemValueCollection: Set<string> = new Set(); 163907ac75b1Sopenharmony_ci const processedContent: string = content.replace(REG_IMPORT_DECL, (item, item1, item2, item3, item4, item5, item6) => { 164007ac75b1Sopenharmony_ci const importValue: string = isProcessAllowList ? projectConfig.compileMode === ESMODULE ? item1 : item2 : item2 || item5; 164107ac75b1Sopenharmony_ci 164207ac75b1Sopenharmony_ci if (isProcessAllowList) { 164307ac75b1Sopenharmony_ci systemValueCollection.add(importValue); 164407ac75b1Sopenharmony_ci if (projectConfig.compileMode !== ESMODULE) { 164507ac75b1Sopenharmony_ci collectSourcemapNames(sourcePath, importValue, item5); 164607ac75b1Sopenharmony_ci return replaceSystemApi(item, importValue, item4, item5); 164707ac75b1Sopenharmony_ci } 164807ac75b1Sopenharmony_ci collectSourcemapNames(sourcePath, importValue, item3); 164907ac75b1Sopenharmony_ci return replaceSystemApi(item, importValue, item2, item3); 165007ac75b1Sopenharmony_ci } 165107ac75b1Sopenharmony_ci 165207ac75b1Sopenharmony_ci const moduleRequest: string = item4 || item6; 165307ac75b1Sopenharmony_ci if (/^@(system|ohos)\./.test(moduleRequest)) { // ohos/system.api 165407ac75b1Sopenharmony_ci // ets & ts file need compile with .d.ts, so do not replace at the phase of pre_process 165507ac75b1Sopenharmony_ci if (!isSystemModule) { 165607ac75b1Sopenharmony_ci return item; 165707ac75b1Sopenharmony_ci } 165807ac75b1Sopenharmony_ci const result: RegExpMatchArray = moduleRequest.match(/^@(system|ohos)\.(\S+)$/); 165907ac75b1Sopenharmony_ci const moduleType: string = result[1]; 166007ac75b1Sopenharmony_ci const apiName: string = result[2]; 166107ac75b1Sopenharmony_ci return replaceSystemApi(item, importValue, moduleType, apiName); 166207ac75b1Sopenharmony_ci } else if (/^lib(\S+)\.so$/.test(moduleRequest)) { // libxxx.so 166307ac75b1Sopenharmony_ci const result: RegExpMatchArray = moduleRequest.match(/^lib(\S+)\.so$/); 166407ac75b1Sopenharmony_ci const libSoKey: string = result[1]; 166507ac75b1Sopenharmony_ci return replaceLibSo(importValue, libSoKey, sourcePath); 166607ac75b1Sopenharmony_ci } 166707ac75b1Sopenharmony_ci return item; 166807ac75b1Sopenharmony_ci }); 166907ac75b1Sopenharmony_ci return processInnerModule(processedContent, systemValueCollection); 167007ac75b1Sopenharmony_ci} 167107ac75b1Sopenharmony_ci 167207ac75b1Sopenharmony_cifunction collectSourcemapNames(sourcePath: string, changedName: string, originalName: string): void { 167307ac75b1Sopenharmony_ci if (sourcePath == null) { 167407ac75b1Sopenharmony_ci return; 167507ac75b1Sopenharmony_ci } 167607ac75b1Sopenharmony_ci const cleanSourcePath: string = sourcePath.replace('.ets', '.js').replace('.ts', '.js'); 167707ac75b1Sopenharmony_ci if (!sourcemapNamesCollection.has(cleanSourcePath)) { 167807ac75b1Sopenharmony_ci return; 167907ac75b1Sopenharmony_ci } 168007ac75b1Sopenharmony_ci 168107ac75b1Sopenharmony_ci const map: Map<string, string> = sourcemapNamesCollection.get(cleanSourcePath); 168207ac75b1Sopenharmony_ci if (map.has(changedName)) { 168307ac75b1Sopenharmony_ci return; 168407ac75b1Sopenharmony_ci } 168507ac75b1Sopenharmony_ci 168607ac75b1Sopenharmony_ci for (const entry of originalImportNamesMap.entries()) { 168707ac75b1Sopenharmony_ci const key: string = entry[0]; 168807ac75b1Sopenharmony_ci const value: string = entry[1]; 168907ac75b1Sopenharmony_ci if (value === '@ohos.' + originalName || value === '@system.' + originalName) { 169007ac75b1Sopenharmony_ci map.set(changedName.trim(), key); 169107ac75b1Sopenharmony_ci sourcemapNamesCollection.set(cleanSourcePath, map); 169207ac75b1Sopenharmony_ci originalImportNamesMap.delete(key); 169307ac75b1Sopenharmony_ci break; 169407ac75b1Sopenharmony_ci } 169507ac75b1Sopenharmony_ci } 169607ac75b1Sopenharmony_ci} 169707ac75b1Sopenharmony_ci 169807ac75b1Sopenharmony_ciexport function collectImportNames(content: string, sourcePath: string = null): void { 169907ac75b1Sopenharmony_ci const REG_IMPORT_DECL: RegExp = 170007ac75b1Sopenharmony_ci /(import|export)\s+(.+)\s+from\s+['"](\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"](\S+)['"]\s*\)/g; 170107ac75b1Sopenharmony_ci 170207ac75b1Sopenharmony_ci const decls: string[] = content.match(REG_IMPORT_DECL); 170307ac75b1Sopenharmony_ci if (decls !== null) { 170407ac75b1Sopenharmony_ci decls.forEach(decl => { 170507ac75b1Sopenharmony_ci const parts: string[] = decl.split(' '); 170607ac75b1Sopenharmony_ci if (parts.length === 4 && parts[0] === 'import' && parts[2] === 'from' && !parts[3].includes('.so')) { 170707ac75b1Sopenharmony_ci originalImportNamesMap.set(parts[1], parts[3].replace(/'/g, '')); 170807ac75b1Sopenharmony_ci } 170907ac75b1Sopenharmony_ci }); 171007ac75b1Sopenharmony_ci } 171107ac75b1Sopenharmony_ci 171207ac75b1Sopenharmony_ci if (sourcePath && sourcePath !== null) { 171307ac75b1Sopenharmony_ci const cleanSourcePath: string = sourcePath.replace('.ets', '.js').replace('.ts', '.js'); 171407ac75b1Sopenharmony_ci if (!sourcemapNamesCollection.has(cleanSourcePath)) { 171507ac75b1Sopenharmony_ci sourcemapNamesCollection.set(cleanSourcePath, new Map()); 171607ac75b1Sopenharmony_ci } 171707ac75b1Sopenharmony_ci } 171807ac75b1Sopenharmony_ci} 171907ac75b1Sopenharmony_ci 172007ac75b1Sopenharmony_cifunction processInnerModule(content: string, systemValueCollection: Set<string>): string { 172107ac75b1Sopenharmony_ci systemValueCollection.forEach(element => { 172207ac75b1Sopenharmony_ci const target: string = element.trim() + '.default'; 172307ac75b1Sopenharmony_ci while (content.includes(target)) { 172407ac75b1Sopenharmony_ci content = content.replace(target, element.trim()); 172507ac75b1Sopenharmony_ci } 172607ac75b1Sopenharmony_ci }); 172707ac75b1Sopenharmony_ci return content; 172807ac75b1Sopenharmony_ci} 172907ac75b1Sopenharmony_ci 173007ac75b1Sopenharmony_ciexport function resetComponentCollection(): void { 173107ac75b1Sopenharmony_ci componentCollection.entryComponent = null; 173207ac75b1Sopenharmony_ci componentCollection.entryComponentPos = null; 173307ac75b1Sopenharmony_ci componentCollection.previewComponent = []; 173407ac75b1Sopenharmony_ci stateObjectCollection.clear(); 173507ac75b1Sopenharmony_ci builderParamInitialization.clear(); 173607ac75b1Sopenharmony_ci propInitialization.clear(); 173707ac75b1Sopenharmony_ci propCollection.clear(); 173807ac75b1Sopenharmony_ci objectLinkCollection.clear(); 173907ac75b1Sopenharmony_ci linkCollection.clear(); 174007ac75b1Sopenharmony_ci storedFileInfo.overallLinkCollection.clear(); 174107ac75b1Sopenharmony_ci storedFileInfo.overallObjectLinkCollection.clear(); 174207ac75b1Sopenharmony_ci storedFileInfo.overallBuilderParamCollection.clear(); 174307ac75b1Sopenharmony_ci regularInitialization.clear(); 174407ac75b1Sopenharmony_ci stateInitialization.clear(); 174507ac75b1Sopenharmony_ci provideInitialization.clear(); 174607ac75b1Sopenharmony_ci privateCollection.clear(); 174707ac75b1Sopenharmony_ci} 174807ac75b1Sopenharmony_ci 174907ac75b1Sopenharmony_cifunction checkEntryComponent(node: ts.StructDeclaration, log: LogInfo[], sourceFile: ts.SourceFile): void { 175007ac75b1Sopenharmony_ci const modifiers = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined; 175107ac75b1Sopenharmony_ci if (modifiers) { 175207ac75b1Sopenharmony_ci for (let i = 0; i < modifiers.length; i++) { 175307ac75b1Sopenharmony_ci if (modifiers[i].kind === ts.SyntaxKind.ExportKeyword) { 175407ac75b1Sopenharmony_ci const message: string = `It's not a recommended way to export struct with @Entry decorator, ` + 175507ac75b1Sopenharmony_ci `which may cause ACE Engine error in component preview mode.`; 175607ac75b1Sopenharmony_ci addLog(LogType.WARN, message, node.getStart(), log, sourceFile); 175707ac75b1Sopenharmony_ci break; 175807ac75b1Sopenharmony_ci } 175907ac75b1Sopenharmony_ci } 176007ac75b1Sopenharmony_ci } 176107ac75b1Sopenharmony_ci} 176207ac75b1Sopenharmony_ci 176307ac75b1Sopenharmony_cifunction validateStateVariable(node: ts.MethodDeclaration): void { 176407ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 176507ac75b1Sopenharmony_ci if (decorators && decorators.length) { 176607ac75b1Sopenharmony_ci for (let i = 0; i < decorators.length; i++) { 176707ac75b1Sopenharmony_ci const decoratorName: string = decorators[i].getText().replace(/\(.*\)$/, '').trim(); 176807ac75b1Sopenharmony_ci if (CARD_ENABLE_DECORATORS[decoratorName]) { 176907ac75b1Sopenharmony_ci validatorCard(transformLog.errors, CARD_LOG_TYPE_DECORATORS, 177007ac75b1Sopenharmony_ci decorators[i].getStart(), decoratorName); 177107ac75b1Sopenharmony_ci } 177207ac75b1Sopenharmony_ci if (INNER_COMPONENT_MEMBER_DECORATORS.has(decoratorName)) { 177307ac75b1Sopenharmony_ci transformLog.errors.push({ 177407ac75b1Sopenharmony_ci type: LogType.ERROR, 177507ac75b1Sopenharmony_ci message: `'${decorators[i].getText()}' can not decorate the method.`, 177607ac75b1Sopenharmony_ci pos: decorators[i].getStart() 177707ac75b1Sopenharmony_ci }); 177807ac75b1Sopenharmony_ci } 177907ac75b1Sopenharmony_ci } 178007ac75b1Sopenharmony_ci } 178107ac75b1Sopenharmony_ci} 178207ac75b1Sopenharmony_ci 178307ac75b1Sopenharmony_ciexport function getObservedPropertyCollection(className: string): Set<string> { 178407ac75b1Sopenharmony_ci const observedProperthCollection: Set<string> = new Set([ 178507ac75b1Sopenharmony_ci ...stateCollection.get(className), 178607ac75b1Sopenharmony_ci ...linkCollection.get(className), 178707ac75b1Sopenharmony_ci ...propCollection.get(className), 178807ac75b1Sopenharmony_ci ...storageLinkCollection.get(className), 178907ac75b1Sopenharmony_ci ...storageLinkCollection.get(className), 179007ac75b1Sopenharmony_ci ...provideCollection.get(className), 179107ac75b1Sopenharmony_ci ...consumeCollection.get(className), 179207ac75b1Sopenharmony_ci ...objectLinkCollection.get(className) 179307ac75b1Sopenharmony_ci ]); 179407ac75b1Sopenharmony_ci getLocalStorageCollection(className, observedProperthCollection); 179507ac75b1Sopenharmony_ci return observedProperthCollection; 179607ac75b1Sopenharmony_ci} 179707ac75b1Sopenharmony_ci 179807ac75b1Sopenharmony_ciexport function getLocalStorageCollection(componentName: string, collection: Set<string>): void { 179907ac75b1Sopenharmony_ci if (localStorageLinkCollection.get(componentName)) { 180007ac75b1Sopenharmony_ci for (const key of localStorageLinkCollection.get(componentName).keys()) { 180107ac75b1Sopenharmony_ci collection.add(key); 180207ac75b1Sopenharmony_ci } 180307ac75b1Sopenharmony_ci } 180407ac75b1Sopenharmony_ci if (localStoragePropCollection.get(componentName)) { 180507ac75b1Sopenharmony_ci for (const key of localStoragePropCollection.get(componentName).keys()) { 180607ac75b1Sopenharmony_ci collection.add(key); 180707ac75b1Sopenharmony_ci } 180807ac75b1Sopenharmony_ci } 180907ac75b1Sopenharmony_ci} 181007ac75b1Sopenharmony_ci 181107ac75b1Sopenharmony_ciexport function resetValidateUiSyntax(): void { 181207ac75b1Sopenharmony_ci observedClassCollection.clear(); 181307ac75b1Sopenharmony_ci enumCollection.clear(); 181407ac75b1Sopenharmony_ci classMethodCollection.clear(); 181507ac75b1Sopenharmony_ci dollarCollection.clear(); 181607ac75b1Sopenharmony_ci stateCollection.clear(); 181707ac75b1Sopenharmony_ci regularCollection.clear(); 181807ac75b1Sopenharmony_ci storagePropCollection.clear(); 181907ac75b1Sopenharmony_ci storageLinkCollection.clear(); 182007ac75b1Sopenharmony_ci provideCollection.clear(); 182107ac75b1Sopenharmony_ci consumeCollection.clear(); 182207ac75b1Sopenharmony_ci builderParamObjectCollection.clear(); 182307ac75b1Sopenharmony_ci localStorageLinkCollection.clear(); 182407ac75b1Sopenharmony_ci localStoragePropCollection.clear(); 182507ac75b1Sopenharmony_ci isStaticViewCollection.clear(); 182607ac75b1Sopenharmony_ci useOSFiles.clear(); 182707ac75b1Sopenharmony_ci sourcemapNamesCollection.clear(); 182807ac75b1Sopenharmony_ci originalImportNamesMap.clear(); 182907ac75b1Sopenharmony_ci} 1830