From f7429a1cccbfd821433dfe3ad35b88f6be37515e Mon Sep 17 00:00:00 2001 From: puyajun Date: Tue, 15 Mar 2022 18:47:26 +0800 Subject: [PATCH] puyajun@huawei.com add localStorage doctor Signed-off-by: puyajun --- compiler/src/compile_info.ts | 2 +- compiler/src/gen_abc.ts | 12 +-- compiler/src/gen_abc_plugin.ts | 14 +-- compiler/src/pre_define.ts | 8 +- compiler/src/process_component_class.ts | 58 ++++++++++-- compiler/src/process_component_constructor.ts | 35 +++++-- compiler/src/process_component_member.ts | 7 +- compiler/src/process_custom_component.ts | 4 +- compiler/src/process_ui_syntax.ts | 29 +++++- compiler/src/validate_ui_syntax.ts | 68 ++++++++++++-- compiler/test/ut/localStorage/localStorage.ts | 94 +++++++++++++++++++ 11 files changed, 282 insertions(+), 49 deletions(-) create mode 100644 compiler/test/ut/localStorage/localStorage.ts diff --git a/compiler/src/compile_info.ts b/compiler/src/compile_info.ts index 50cf43f1d..3a744e86b 100644 --- a/compiler/src/compile_info.ts +++ b/compiler/src/compile_info.ts @@ -300,7 +300,7 @@ export class ResultStates { if (message.includes(item)) { return true; } - }) + }); if (reg.test(message)) { const match: string[] = message.match(reg); if (match[1] && nameArr.includes(match[1])) { diff --git a/compiler/src/gen_abc.ts b/compiler/src/gen_abc.ts index 8d20e07a5..b0c2020a4 100644 --- a/compiler/src/gen_abc.ts +++ b/compiler/src/gen_abc.ts @@ -27,7 +27,7 @@ function js2abcByWorkers(jsonInput: string, cmd: string): Promise { for (let i = 0; i < inputPaths.length; ++i) { const input = inputPaths[i].path; const singleCmd = `${cmd} "${input}"`; - logger.debug("gen abc cmd is: ", singleCmd, " ,file size is:", inputPaths[i].size, " byte"); + logger.debug('gen abc cmd is: ', singleCmd, ' ,file size is:', inputPaths[i].size, ' byte'); try { childProcess.execSync(singleCmd); } catch (e) { @@ -49,10 +49,10 @@ function js2abcByWorkers(jsonInput: string, cmd: string): Promise { } } -logger.debug("worker data is: ", JSON.stringify(process.env)); -logger.debug("gen_abc isWorker is: ", cluster.isWorker); -if (cluster.isWorker && process.env["inputs"] !== undefined && process.env["cmd"] !== undefined) { - logger.debug("==>worker #", cluster.worker.id, "started!"); - js2abcByWorkers(process.env["inputs"], process.env["cmd"]); +logger.debug('worker data is: ', JSON.stringify(process.env)); +logger.debug('gen_abc isWorker is: ', cluster.isWorker); +if (cluster.isWorker && process.env['inputs'] !== undefined && process.env['cmd'] !== undefined) { + logger.debug('==>worker #', cluster.worker.id, 'started!'); + js2abcByWorkers(process.env['inputs'], process.env['cmd']); process.exit(); } diff --git a/compiler/src/gen_abc_plugin.ts b/compiler/src/gen_abc_plugin.ts index eac73f7de..a1c16a3c0 100644 --- a/compiler/src/gen_abc_plugin.ts +++ b/compiler/src/gen_abc_plugin.ts @@ -107,7 +107,7 @@ function getSmallestSizeGroup(groupSize: Map) { } function splitJsBundlesBySize(bundleArray: Array, groupNumber: number) { - let result = []; + const result = []; if (bundleArray.length < groupNumber) { result.push(bundleArray); return result; @@ -153,9 +153,9 @@ function invokeWorkersToGenAbc() { const clusterNewApiVersion = 16; const currentNodeVersion = parseInt(process.version.split('.')[0]); - const useNewApi = currentNodeVersion >= clusterNewApiVersion ? true : false; + const useNewApi = currentNodeVersion >= clusterNewApiVersion; - if ((useNewApi && cluster.isPrimary) || (!useNewApi && cluster.isMaster)) { + if (useNewApi && cluster.isPrimary || !useNewApi && cluster.isMaster) { if (useNewApi) { cluster.setupPrimary({ exec: path.resolve(__dirname, genAbcScript) @@ -167,10 +167,10 @@ function invokeWorkersToGenAbc() { } for (let i = 0; i < workerNumber; ++i) { - let workerData = { - "inputs": JSON.stringify(splitedBundles[i]), - "cmd": cmdPrefix - } + const workerData = { + 'inputs': JSON.stringify(splitedBundles[i]), + 'cmd': cmdPrefix + }; cluster.fork(workerData); } diff --git a/compiler/src/pre_define.ts b/compiler/src/pre_define.ts index d746eedd0..530569b01 100644 --- a/compiler/src/pre_define.ts +++ b/compiler/src/pre_define.ts @@ -37,6 +37,8 @@ export const COMPONENT_CONSUME_DECORATOR: string = '@Consume'; export const COMPONENT_OBJECT_LINK_DECORATOR: string = '@ObjectLink'; export const COMPONENT_WATCH_DECORATOR: string = '@Watch'; export const COMPONENT_BUILDERPARAM_DECORATOR: string = '@BuilderParam'; +export const COMPONENT_LOCAL_STORAGE_LINK_DECORATOR: string = '@LocalStorageLink'; +export const COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: string = '@LocalStorageProp'; export const COMPONENT_DECORATORS_PARAMS: Set = new Set([COMPONENT_CONSUME_DECORATOR, COMPONENT_STORAGE_PROP_DECORATOR, COMPONENT_STORAGE_LINK_DECORATOR, COMPONENT_PROVIDE_DECORATOR, @@ -46,7 +48,8 @@ export const INNER_COMPONENT_DECORATORS: Set = new Set([COMPONENT_DECORA export const INNER_COMPONENT_MEMBER_DECORATORS: Set = new Set([COMPONENT_STATE_DECORATOR, COMPONENT_PROP_DECORATOR, COMPONENT_LINK_DECORATOR, COMPONENT_STORAGE_PROP_DECORATOR, COMPONENT_STORAGE_LINK_DECORATOR, COMPONENT_PROVIDE_DECORATOR, COMPONENT_CONSUME_DECORATOR, - COMPONENT_OBJECT_LINK_DECORATOR, COMPONENT_WATCH_DECORATOR, COMPONENT_BUILDERPARAM_DECORATOR]); + COMPONENT_OBJECT_LINK_DECORATOR, COMPONENT_WATCH_DECORATOR, COMPONENT_BUILDERPARAM_DECORATOR, + COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, COMPONENT_LOCAL_STORAGE_PROP_DECORATOR]); export const COMPONENT_OBSERVED_DECORATOR: string = '@Observed'; export const COMPONENT_BUILDER_DECORATOR: string = '@Builder'; @@ -109,6 +112,9 @@ export const COMPONENT_CONSTRUCTOR_ID: string = 'compilerAssignedUniqueChildId'; export const COMPONENT_CONSTRUCTOR_PARENT: string = 'parent'; export const COMPONENT_CONSTRUCTOR_PARAMS: string = 'params'; export const COMPONENT_CONSTRUCTOR_UNDEFINED: string = 'undefined'; +export const COMPONENT_CONSTRUCTOR_LOCALSTORAGE: string = 'localStorage'; +export const COMPONENT_SET_AND_LINK: string = 'setAndLink'; +export const COMPONENT_SET_AND_PROP: string = 'setAndProp'; export const BUILD_ON: string = 'on'; export const BUILD_OFF: string = 'off'; diff --git a/compiler/src/process_component_class.ts b/compiler/src/process_component_class.ts index dc177f35b..6eb06a40f 100644 --- a/compiler/src/process_component_class.ts +++ b/compiler/src/process_component_class.ts @@ -48,7 +48,13 @@ import { COMPONENT_STYLES_DECORATOR, STYLES, INTERFACE_NAME_SUFFIX, - OBSERVED_PROPERTY_ABSTRACT + OBSERVED_PROPERTY_ABSTRACT, + COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, + COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, + COMPONENT_CONSTRUCTOR_LOCALSTORAGE, + COMPONENT_SET_AND_LINK, + COMPONENT_SET_AND_PROP, + COMPONENT_CONSTRUCTOR_UNDEFINED } from './pre_define'; import { BUILDIN_STYLE_NAMES, @@ -59,7 +65,9 @@ import { } from './component_map'; import { componentCollection, - linkCollection + linkCollection, + localStorageLinkCollection, + localStoragePropCollection } from './validate_ui_syntax'; import { addConstructor, @@ -114,7 +122,7 @@ type BuildCount = { function processMembers(members: ts.NodeArray, parentComponentName: ts.Identifier, context: ts.TransformationContext, log: LogInfo[], program: ts.Program, hasPreview: boolean): ts.ClassElement[] { const buildCount: BuildCount = { count: 0 }; - let ctorNode: any = getInitConstructor(members); + let ctorNode: any = getInitConstructor(members, parentComponentName); const newMembers: ts.ClassElement[] = []; const watchMap: Map = new Map(); const updateParamsStatements: ts.Statement[] = []; @@ -126,9 +134,9 @@ function processMembers(members: ts.NodeArray, parentComponentN members.forEach((item: ts.ClassElement) => { let updateItem: ts.ClassElement; if (ts.isPropertyDeclaration(item)) { - addPropertyMember(item, newMembers, program); const result: UpdateResult = processMemberVariableDecorators(parentComponentName, item, ctorNode, watchMap, checkController, log, program, context, hasPreview, interfaceNode); + addPropertyMember(item, newMembers, program, parentComponentName.getText()); if (result.isItemUpdate()) { updateItem = result.getProperity(); } else { @@ -171,7 +179,7 @@ function processMembers(members: ts.NodeArray, parentComponentN } function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], - program: ts.Program):void { + program: ts.Program, parentComponentName: string):void { const propertyItem: ts.PropertyDeclaration = item as ts.PropertyDeclaration; let decoratorName: string; let updatePropertyItem: ts.PropertyDeclaration; @@ -183,6 +191,7 @@ function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], for (let i = 0; i < propertyItem.decorators.length; i++) { let newType: ts.TypeNode; decoratorName = propertyItem.decorators[i].getText().replace(/\(.*\)$/, '').trim(); + let isLocalStorage: boolean = false; switch (decoratorName) { case COMPONENT_STATE_DECORATOR: case COMPONENT_PROVIDE_DECORATOR: @@ -204,8 +213,14 @@ function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], case COMPONENT_STORAGE_LINK_DECORATOR: newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [type]); break; + case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR: + case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: + newType = ts.factory.createTypeReferenceNode(OBSERVED_PROPERTY_ABSTRACT, [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)]); + isLocalStorage = true; + break; } - updatePropertyItem = createPropertyDeclaration(propertyItem, newType, false); + updatePropertyItem = createPropertyDeclaration(propertyItem, newType, false, + isLocalStorage, parentComponentName); if (updatePropertyItem) { newMembers.push(updatePropertyItem); } @@ -214,7 +229,8 @@ function addPropertyMember(item: ts.ClassElement, newMembers: ts.ClassElement[], } function createPropertyDeclaration(propertyItem: ts.PropertyDeclaration, newType: ts.TypeNode | undefined, - normalVar: boolean): ts.PropertyDeclaration { + normalVar: boolean, isLocalStorage: boolean = false, parentComponentName: string = null +): ts.PropertyDeclaration { if (typeof newType === undefined) { return undefined; } @@ -226,7 +242,33 @@ function createPropertyDeclaration(propertyItem: ts.PropertyDeclaration, newType ts.factory.createModifier(ts.SyntaxKind.PrivateKeyword); return ts.factory.updatePropertyDeclaration(propertyItem, undefined, propertyItem.modifiers || [privateM], prefix + propertyItem.name.getText(), - propertyItem.questionToken, newType, undefined); + propertyItem.questionToken, newType, isLocalStorage ? + createLocalStroageCallExpression(propertyItem, propertyItem.name.getText(), + parentComponentName) : undefined); +} + +function createLocalStroageCallExpression(node: ts.PropertyDeclaration, name: string, + parentComponentName: string): ts.CallExpression { + const localStorageLink: Set = localStorageLinkCollection.get(parentComponentName).get(name); + const localStorageProp: Set = localStoragePropCollection.get(parentComponentName).get(name); + return ts.factory.createCallExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createPropertyAccessExpression( + ts.factory.createThis(), + ts.factory.createIdentifier(`${COMPONENT_CONSTRUCTOR_LOCALSTORAGE}_`) + ), + ts.factory.createIdentifier(localStorageLink && !localStorageProp ? COMPONENT_SET_AND_LINK : + COMPONENT_SET_AND_PROP) + ), + [node.type], + [ + ts.factory.createStringLiteral(localStorageLink && !localStorageProp ? + Array.from(localStorageLink)[0] : Array.from(localStorageProp)[0]), + ts.factory.createNumericLiteral(node.initializer ? node.initializer.getText() + : COMPONENT_CONSTRUCTOR_UNDEFINED), ts.factory.createThis(), + ts.factory.createStringLiteral(name || COMPONENT_CONSTRUCTOR_UNDEFINED) + ] + ); } function processComponentMethod(node: ts.MethodDeclaration, parentComponentName: ts.Identifier, diff --git a/compiler/src/process_component_constructor.ts b/compiler/src/process_component_constructor.ts index 9555249a2..2c5776b11 100644 --- a/compiler/src/process_component_constructor.ts +++ b/compiler/src/process_component_constructor.ts @@ -22,17 +22,23 @@ import { COMPONENT_CONSTRUCTOR_UPDATE_PARAMS, COMPONENT_WATCH_FUNCTION, BASE_COMPONENT_NAME, - INTERFACE_NAME_SUFFIX + INTERFACE_NAME_SUFFIX, + COMPONENT_CONSTRUCTOR_LOCALSTORAGE } from './pre_define'; -export function getInitConstructor(members: ts.NodeArray): ts.ConstructorDeclaration { +import { + localStorageLinkCollection, + localStoragePropCollection +} from './validate_ui_syntax'; +export function getInitConstructor(members: ts.NodeArray, parentComponentName: ts.Identifier +): ts.ConstructorDeclaration { let ctorNode: any = members.find(item => { return ts.isConstructorDeclaration(item); }); if (ctorNode) { ctorNode = updateConstructor(ctorNode, [], [], true); } - return initConstructorParams(ctorNode); + return initConstructorParams(ctorNode, parentComponentName); } export function updateConstructor(ctorNode: ts.ConstructorDeclaration, @@ -63,15 +69,22 @@ export function updateConstructor(ctorNode: ts.ConstructorDeclaration, ctorPara = addParamsType(ctorNode, modifyPara, parentComponentName); } ctorNode = ts.factory.updateConstructorDeclaration(ctorNode, ctorNode.decorators, - ctorNode.modifiers, ctorPara, + ctorNode.modifiers, modifyPara || ctorNode.parameters, ts.factory.createBlock(modifyBody || ctorNode.body.statements, true)); } return ctorNode; } -function initConstructorParams(node: ts.ConstructorDeclaration): ts.ConstructorDeclaration { - const paramNames: string[] = [COMPONENT_CONSTRUCTOR_ID, COMPONENT_CONSTRUCTOR_PARENT, - COMPONENT_CONSTRUCTOR_PARAMS]; +function initConstructorParams(node: ts.ConstructorDeclaration, parentComponentName: ts.Identifier +): ts.ConstructorDeclaration { + if (!ts.isIdentifier(parentComponentName)) { + return; + } + const localStorageNum: number = localStorageLinkCollection.get(parentComponentName.getText()).size + + localStoragePropCollection.get(parentComponentName.getText()).size; + const paramNames: Set = new Set([COMPONENT_CONSTRUCTOR_ID, COMPONENT_CONSTRUCTOR_PARENT, + COMPONENT_CONSTRUCTOR_PARAMS, localStorageNum ? COMPONENT_CONSTRUCTOR_LOCALSTORAGE : + COMPONENT_CONSTRUCTOR_PARAMS]); const newParameters: ts.ParameterDeclaration[] = Array.from(node.parameters); if (newParameters.length !== 0) { // @ts-ignore @@ -114,13 +127,15 @@ function addParamsType(ctorNode: ts.ConstructorDeclaration, modifyPara: ts.Param break; } newTSPara.push(parameter); - }) + }); return newTSPara; } export function addConstructor(ctorNode: any, watchMap: Map, parentComponentName: ts.Identifier): ts.ConstructorDeclaration { const watchStatements: ts.ExpressionStatement[] = []; + const localStorageNum: number = localStorageLinkCollection.get(parentComponentName.getText()).size + + localStoragePropCollection.get(parentComponentName.getText()).size; watchMap.forEach((value, key) => { const watchNode: ts.ExpressionStatement = ts.factory.createExpressionStatement( ts.factory.createCallExpression( @@ -141,7 +156,9 @@ export function addConstructor(ctorNode: any, watchMap: Map, const callSuperStatement: ts.Statement = ts.factory.createExpressionStatement( ts.factory.createCallExpression(ts.factory.createSuper(), undefined, [ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_ID), - ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)])); + localStorageNum ? (ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT), + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_LOCALSTORAGE)) : + ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_PARENT)])); const updateWithValueParamsStatement: ts.Statement = ts.factory.createExpressionStatement( ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression( ts.factory.createThis(), ts.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UPDATE_PARAMS)), diff --git a/compiler/src/process_component_member.ts b/compiler/src/process_component_member.ts index 9de044526..2cfe878b6 100644 --- a/compiler/src/process_component_member.ts +++ b/compiler/src/process_component_member.ts @@ -50,7 +50,9 @@ import { SET_CONTROLLER_CTR_TYPE, BASE_COMPONENT_NAME, COMPONENT_CREATE_FUNCTION, - COMPONENT_BUILDERPARAM_DECORATOR + COMPONENT_BUILDERPARAM_DECORATOR, + COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, + COMPONENT_LOCAL_STORAGE_PROP_DECORATOR } from './pre_define'; import { forbiddenUseStateType, @@ -85,7 +87,8 @@ export const propAndLinkDecorators: Set = new Set([COMPONENT_PROP_DECORATOR, COMPONENT_LINK_DECORATOR]); export const appStorageDecorators: Set = - new Set([COMPONENT_STORAGE_PROP_DECORATOR, COMPONENT_STORAGE_LINK_DECORATOR]); + new Set([COMPONENT_STORAGE_PROP_DECORATOR, COMPONENT_STORAGE_LINK_DECORATOR, + COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, COMPONENT_LOCAL_STORAGE_PROP_DECORATOR]); export const mandatorySpecifyDefaultValueDecorators: Set = new Set([...observedPropertyDecorators, ...appStorageDecorators]); diff --git a/compiler/src/process_custom_component.ts b/compiler/src/process_custom_component.ts index 50109765b..833c3b758 100644 --- a/compiler/src/process_custom_component.ts +++ b/compiler/src/process_custom_component.ts @@ -123,7 +123,9 @@ function addCustomComponent(node: ts.ExpressionStatement, newStatements: ts.Stat const customComponentName: string = getCustomComponentName(newNode); const propertyArray: ts.ObjectLiteralElementLike[] = []; validateCustomComponentPrams(node, customComponentName, propertyArray, log); - addCustomComponentStatements(node, newStatements, newNode, customComponentName, propertyArray); + if (customComponentName) { + addCustomComponentStatements(node, newStatements, newNode, customComponentName, propertyArray); + } } } diff --git a/compiler/src/process_ui_syntax.ts b/compiler/src/process_ui_syntax.ts index 6269820fb..156fc62e7 100644 --- a/compiler/src/process_ui_syntax.ts +++ b/compiler/src/process_ui_syntax.ts @@ -61,6 +61,10 @@ import { GLOBAL_STYLE_FUNCTION, INTERFACE_NODE_SET } from './component_map'; +import { + localStorageLinkCollection, + localStoragePropCollection +} from './validate_ui_syntax'; import { resources } from '../main'; import { createCustomComponentNewExpression, createViewCreate } from './process_component_member'; @@ -408,25 +412,42 @@ function isExtendFunction(node: ts.FunctionDeclaration): string { function createEntryNode(node: ts.SourceFile, context: ts.TransformationContext): ts.SourceFile { if (componentCollection.entryComponent) { const entryNode: ts.ExpressionStatement = - createEntryFunction(componentCollection.entryComponent, context); + createEntryFunction(node, componentCollection.entryComponent, context); return context.factory.updateSourceFile(node, [...node.statements, entryNode]); } else if (componentCollection.previewComponent) { const entryNode: ts.ExpressionStatement = - createEntryFunction(componentCollection.previewComponent, context); + createEntryFunction(node, componentCollection.previewComponent, context); return context.factory.updateSourceFile(node, [...node.statements, entryNode]); } else { return node; } } -function createEntryFunction(name: string, context: ts.TransformationContext) +function createEntryFunction(node: ts.SourceFile, name: string, context: ts.TransformationContext) : ts.ExpressionStatement { + let localStorageName: string; + const localStorageNum: number = localStorageLinkCollection.get(name).size + + localStoragePropCollection.get(name).size; + if (componentCollection.entryComponent === name && componentCollection.localStorageName && + localStorageNum) { + localStorageName = componentCollection.localStorageName; + } else if (componentCollection.entryComponent === name && !componentCollection.localStorageName + && localStorageNum) { + transformLog.errors.push({ + type: LogType.ERROR, + message: `'${name}' @Entry shuould have a param, lilk'@Entrey(storage)'.`, + pos: componentCollection.entryComponentPos + }); + return; + } return context.factory.createExpressionStatement(context.factory.createCallExpression( context.factory.createIdentifier(PAGE_ENTRY_FUNCTION_NAME), undefined, [context.factory.createNewExpression(context.factory.createIdentifier(name), undefined, [context.factory.createStringLiteral((++componentInfo.id).toString()), context.factory.createIdentifier(COMPONENT_CONSTRUCTOR_UNDEFINED), - context.factory.createObjectLiteralExpression([], false)])])); + localStorageName ? (context.factory.createObjectLiteralExpression([], false), + context.factory.createIdentifier(localStorageName)) : + context.factory.createObjectLiteralExpression([], false)])])); } export function resetLog(): void { diff --git a/compiler/src/validate_ui_syntax.ts b/compiler/src/validate_ui_syntax.ts index 882859c5f..e64299f54 100644 --- a/compiler/src/validate_ui_syntax.ts +++ b/compiler/src/validate_ui_syntax.ts @@ -37,6 +37,8 @@ import { COMPONENT_CONSUME_DECORATOR, COMPONENT_OBJECT_LINK_DECORATOR, COMPONENT_OBSERVED_DECORATOR, + COMPONENT_LOCAL_STORAGE_LINK_DECORATOR, + COMPONENT_LOCAL_STORAGE_PROP_DECORATOR, STYLES, VALIDATE_MODULE, COMPONENT_BUILDER_DECORATOR @@ -61,14 +63,16 @@ import { } from './utils'; import { projectConfig } from '../main'; import { collectExtend } from './process_ui_syntax'; -import { importModuleCollection } from "./ets_checker"; +import { importModuleCollection } from './ets_checker'; export interface ComponentCollection { + localStorageName: string; entryComponent: string; previewComponent: string; customDialogs: Set; customComponents: Set; currentClassName: string; + entryComponentPos: number; } export interface IComponentSet { @@ -82,10 +86,14 @@ export interface IComponentSet { provides: Set; consumes: Set; objectLinks: Set; + localStorageLink: Map>; + localStorageProp: Map>; } export const componentCollection: ComponentCollection = { + localStorageName: null, entryComponent: null, + entryComponentPos: null, previewComponent: null, customDialogs: new Set([]), customComponents: new Set([]), @@ -107,6 +115,8 @@ export const storageLinkCollection: Map> = new Map(); export const provideCollection: Map> = new Map(); export const consumeCollection: Map> = new Map(); export const objectLinkCollection: Map> = new Map(); +export const localStorageLinkCollection: Map>> = new Map(); +export const localStoragePropCollection: Map>> = new Map(); export const isStaticViewCollection: Map = new Map(); @@ -249,6 +259,8 @@ function checkDecorators(decorators: ts.NodeArray, result: Decorat case COMPONENT_DECORATOR_ENTRY: result.entryCount++; componentCollection.entryComponent = componentName; + componentCollection.entryComponentPos = decorators.pos; + collectLocalStorageName(element); break; case COMPONENT_DECORATOR_PREVIEW: result.previewCount++; @@ -284,6 +296,19 @@ function checkDecorators(decorators: ts.NodeArray, result: Decorat } } +function collectLocalStorageName(node: ts.Decorator): void { + if (node && node.expression && ts.isCallExpression(node.expression) && node.expression.arguments + && node.expression.arguments.length) { + node.expression.arguments.forEach((item: ts.Identifier, index: number) => { + if (ts.isIdentifier(item) && index === 0) { + componentCollection.localStorageName = item.getText(); + } + }); + } else { + componentCollection.localStorageName = null; + } +} + function checkUISyntax(filePath: string, allComponentNames: Set, content: string, log: LogInfo[]): void { const sourceFile: ts.SourceFile = ts.createSourceFile(filePath, content, @@ -613,6 +638,8 @@ function collectComponentProps(node: ts.StructDeclaration): void { provideCollection.set(componentName, ComponentSet.provides); consumeCollection.set(componentName, ComponentSet.consumes); objectLinkCollection.set(componentName, ComponentSet.objectLinks); + localStorageLinkCollection.set(componentName, ComponentSet.localStorageLink); + localStoragePropCollection.set(componentName, ComponentSet.localStorageProp); } export function getComponentSet(node: ts.StructDeclaration): IComponentSet { @@ -626,18 +653,21 @@ export function getComponentSet(node: ts.StructDeclaration): IComponentSet { const provides: Set = new Set(); const consumes: Set = new Set(); const objectLinks: Set = new Set(); + const localStorageLink: Map> = new Map(); + const localStorageProp: Map> = new Map(); traversalComponentProps(node, propertys, regulars, states, links, props, storageProps, - storageLinks, provides, consumes, objectLinks); + storageLinks, provides, consumes, objectLinks, localStorageLink, localStorageProp); return { propertys, regulars, states, links, props, storageProps, storageLinks, provides, - consumes, objectLinks + consumes, objectLinks, localStorageLink, localStorageProp }; } function traversalComponentProps(node: ts.StructDeclaration, propertys: Set, regulars: Set, states: Set, links: Set, props: Set, storageProps: Set, storageLinks: Set, provides: Set, - consumes: Set, objectLinks: Set): void { + consumes: Set, objectLinks: Set, + localStorageLink: Map>, localStorageProp: Map>): void { let isStatic: boolean = true; if (node.members) { const currentMethodCollection: Set = new Set(); @@ -653,8 +683,8 @@ function traversalComponentProps(node: ts.StructDeclaration, propertys: Set, links: Set, - props: Set, storageProps: Set, storageLinks: Set, provides: Set, - consumes: Set, objectLinks: Set): void { +function collectionStates(node: ts.Decorator, decorator: string, name: string, + states: Set, links: Set, props: Set, storageProps: Set, + storageLinks: Set, provides: Set, consumes: Set, objectLinks: Set, + localStorageLink: Map>, localStorageProp: Map>): void { switch (decorator) { case COMPONENT_STATE_DECORATOR: states.add(name); @@ -696,6 +727,22 @@ function collectionStates(decorator: string, name: string, states: Set, case COMPONENT_OBJECT_LINK_DECORATOR: objectLinks.add(name); break; + case COMPONENT_LOCAL_STORAGE_LINK_DECORATOR : + collectionlocalStorageParam(node, name, localStorageLink); + break; + case COMPONENT_LOCAL_STORAGE_PROP_DECORATOR: + collectionlocalStorageParam(node, name, localStorageProp); + break; + } +} + +function collectionlocalStorageParam(node: ts.Decorator, name: string, + localStorage: Map>): void { + const localStorageParam: Set = new Set(); + if (node && ts.isCallExpression(node.expression) && node.expression.arguments && + node.expression.arguments.length && ts.isStringLiteral(node.expression.arguments[0])) { + localStorage.set(name, localStorageParam.add( + node.expression.arguments[0].getText().replace(/\"/g, ''))); } } @@ -749,7 +796,7 @@ export function processSystemApi(content: string, isProcessWhiteList: boolean = let moduleType: string = item2 || item5; let systemKey: string = item3 || item6; let systemValue: string = item1 || item4; - if (!VALIDATE_MODULE.includes(systemValue)){ + if (!VALIDATE_MODULE.includes(systemValue)) { importModuleCollection.add(systemValue); } if (!isProcessWhiteList && validateWhiteListModule(moduleType, systemKey)) { @@ -794,5 +841,6 @@ function validateWhiteListModule(moduleType: string, systemKey: string): boolean export function resetComponentCollection() { componentCollection.entryComponent = null; + componentCollection.entryComponentPos = null; componentCollection.previewComponent = null; } diff --git a/compiler/test/ut/localStorage/localStorage.ts b/compiler/test/ut/localStorage/localStorage.ts new file mode 100644 index 000000000..c78182560 --- /dev/null +++ b/compiler/test/ut/localStorage/localStorage.ts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +exports.source = ` +let storage = LocalStorage.GetShared(); + +class ClassA { + public id: number = 1; + public type: number = 2; + public a: string = "aaa"; + constructor(a: string){ + this.a = a; + } +} + +@Entry(storage) +@Component +struct LocalStorageComponent { + @LocalStorageLink("storageSimpleProp") simpleVarName: number = 0; + @LocalStorageProp("storageObjectProp") objectName: ClassA = new ClassA("x"); + build() { + Column() { + Text(this.objectName.a) + .onClick(()=>{ + this.simpleVarName +=1; + this.objectName.a = this.objectName.a === 'x' ? 'yex' : 'no'; + }) + } + .height(500) + } +} +` +exports.expectResult = +`let storage = LocalStorage.GetShared(); +class ClassA { + constructor(a) { + this.id = 1; + this.type = 2; + this.a = "aaa"; + this.a = a; + } +} +class LocalStorageComponent extends View { + constructor(compilerAssignedUniqueChildId, parent, params, localStorage) { + super(compilerAssignedUniqueChildId, localStorage); + this.__simpleVarName = this.localStorage_.setAndLink("storageSimpleProp", 0, this, "simpleVarName"); + this.__objectName = this.localStorage_.setAndProp("storageObjectProp", new ClassA("x"), this, "objectName"); + this.updateWithValueParams(params); + } + updateWithValueParams(params) { + } + aboutToBeDeleted() { + this.__simpleVarName.aboutToBeDeleted(); + this.__objectName.aboutToBeDeleted(); + SubscriberManager.Get().delete(this.id()); + } + get simpleVarName() { + return this.__simpleVarName.get(); + } + set simpleVarName(newValue) { + this.__simpleVarName.set(newValue); + } + get objectName() { + return this.__objectName.get(); + } + set objectName(newValue) { + this.__objectName.set(newValue); + } + render() { + Column.create(); + Column.height(500); + Text.create(this.objectName.a); + Text.onClick(() => { + this.simpleVarName += 1; + this.objectName.a = this.objectName.a === 'x' ? 'yex' : 'no'; + }); + Text.pop(); + Column.pop(); + } +} +loadDocument(new LocalStorageComponent("1", undefined, storage)); +` \ No newline at end of file -- Gitee