diff --git a/compiler/src/interop/src/process_custom_component.ts b/compiler/src/interop/src/process_custom_component.ts index 71d9aa2b7088dc33be6b2f88370c8ff1bacb4640..bd990b7a604f2c8b865679a9b5e6805bad2288d5 100644 --- a/compiler/src/interop/src/process_custom_component.ts +++ b/compiler/src/interop/src/process_custom_component.ts @@ -63,6 +63,8 @@ import { COMPONENTV2_LOCAL_DECORATOR, COMPONENTV2_CONSUMER_DECORATOR, COMPONENTV2_PROVIDER_DECORATOR, + COMPONENTV2_PARAM_DECORATOR, + COMPONENTV2_EVENT_DECORATOR, VIEWSTACKPROCESSOR, } from './pre_define'; import { @@ -371,6 +373,7 @@ class ChildAndParentComponentInfo { forbiddenInitPropsV2: string[]; updatePropsForV1Parent: string[]; updatePropsForV2Parent: string[]; + forbiddenInitPropsV1Recieve: string[]; constructor(childName: string, childNode: ts.CallExpression, propsAndObjectLinks: string[]) { this.childName = childName; this.propsAndObjectLinks = propsAndObjectLinks; @@ -388,9 +391,24 @@ class ChildAndParentComponentInfo { this.updatePropsForV2Parent = [...this.parentStructInfo.localDecoratorSet, ...this.parentStructInfo.paramDecoratorMap.keys(), ...this.parentStructInfo.providerDecoratorSet, ...this.parentStructInfo.consumerDecoratorSet]; + this.forbiddenInitPropsV1Recieve = extractAllDecoratorPropertyNames( + this.childStructInfo.updatePropsDecoratorsV1Receive); } } +function extractAllDecoratorPropertyNames(decoratorMap: Map): string[] { + const propertyNames: string[] = []; + for (const [, decorators] of decoratorMap) { + decorators.forEach(decorator => { + const propName = decorator.name || decorator.key || decorator.propertyName || ''; + if (propName) { + propertyNames.push(propName); + } + }); + } + return propertyNames; +} + function getUpdatePropsForV1Parent(): string[] { const propertiesMapArr: Array>> = [ stateCollection, linkCollection, propCollection, @@ -434,19 +452,97 @@ function getForbbidenInitPropsV2Type(itemName: string, info: ChildAndParentCompo typeName = COMPONENTV2_CONSUMER_DECORATOR; } else if (info.childStructInfo.providerDecoratorSet.has(itemName)) { typeName = COMPONENTV2_PROVIDER_DECORATOR; + } else if (info.childStructInfo.paramDecoratorMap.has(itemName)) { + typeName = COMPONENTV2_PARAM_DECORATOR; + } else if (info.childStructInfo.eventDecoratorMap.has(itemName)) { + typeName = COMPONENTV2_EVENT_DECORATOR; } return typeName; } +function getForbbidenInitPropsV1Type(itemName: string, info: ChildAndParentComponentInfo): string { + const { updatePropsDecoratorsV1Receive } = info.childStructInfo; + const stateDecorators = updatePropsDecoratorsV1Receive.get('@state') || []; + const propDecorators = updatePropsDecoratorsV1Receive.get('@prop') || []; + const provideDecorators = updatePropsDecoratorsV1Receive.get('@provide') || []; + const consumeDecorators = updatePropsDecoratorsV1Receive.get('@consume') || []; + const objectLinkDecorators = updatePropsDecoratorsV1Receive.get('@ObjectLink') || []; + const storageLinkDecorators = updatePropsDecoratorsV1Receive.get('@StorageLink') || []; + const storagePropDecorators = updatePropsDecoratorsV1Receive.get('@StorageProp') || []; + const localStorageLinkDecorators = updatePropsDecoratorsV1Receive.get('@LocalStorageLink') || []; + const localStoragePropDecorators = updatePropsDecoratorsV1Receive.get('@LocalStorageProp') || []; + + if (hasDecoratorInArray(stateDecorators, itemName)) { + return COMPONENT_STATE_DECORATOR; + } else if (hasDecoratorInArray(propDecorators, itemName)) { + return COMPONENT_PROP_DECORATOR; + } else if (hasDecoratorInArray(provideDecorators, itemName)) { + return COMPONENT_PROVIDE_DECORATOR; + } else if (hasDecoratorInArray(consumeDecorators, itemName)) { + return COMPONENT_CONSUME_DECORATOR; + } else if (hasDecoratorInArray(objectLinkDecorators, itemName)) { + return COMPONENT_OBJECT_LINK_DECORATOR; + } else if (hasDecoratorInArray(storageLinkDecorators, itemName)) { + return COMPONENT_STORAGE_LINK_DECORATOR; + } else if (hasDecoratorInArray(storagePropDecorators, itemName)) { + return COMPONENT_STORAGE_PROP_DECORATOR; + } else if (hasDecoratorInArray(localStorageLinkDecorators, itemName)) { + return COMPONENT_LOCAL_STORAGE_LINK_DECORATOR; + } else if (hasDecoratorInArray(localStoragePropDecorators, itemName)) { + return COMPONENT_LOCAL_STORAGE_PROP_DECORATOR; + } + return COMPONENT_NON_DECORATOR; +} + +function hasDecoratorInArray(decorators: any[], itemName: string): boolean { + return decorators.some(decorator => { + return decorator.name === itemName || + decorator.key === itemName || + (decorator.constructor && decorator.constructor.name === itemName); + }); +} + function validateChildProperty(item: ts.PropertyAssignment, itemName: string, childParam: ts.PropertyAssignment[], log: LogInfo[], info: ChildAndParentComponentInfo): void { + if (!info.parentStructInfo.isComponentV2 && info.childStructInfo.isComponentV2) { + // ts.isPropertyAccessExpression(value) + // ts.isThisTypeNode + // ts.SyntaxKind.ThisKeyword + console.log("validateChildProperty 111",ts.SyntaxKind.ThisKeyword); + console.log("validateChildProperty 222",ts.isPropertyAccessExpression); + const propType: string = getForbbidenInitPropsV2Type(itemName, info); + log.push({ + type: LogType.ERROR, + message: `The V2child '${propType}' property '${itemName}' in the custom component '${info.childName}'` + + ` cannot be initialized here. 1.1 use 1.2 validateChildProperty.`, + pos: item.getStart(), + code: '10905324' + }); + return; + } else if (info.parentStructInfo.isComponentV2 && !info.childStructInfo.isComponentV2) { + // const isThisAttribute = + // ts.isMemberExpression(node.left) && + // ts.isThisExpression(node.left.object) && + // ts.isIdentifier(node.left.property); + if (info.forbiddenInitPropsV1Recieve.includes(itemName)) { + const propType: string = getForbbidenInitPropsV1Type(itemName, info); + log.push({ + type: LogType.ERROR, + message: `The V2child '${propType}' property '${itemName}' in the custom component '${info.childName}'` + + ` cannot be initialized here. 1.1 use 1.2 validateChildProperty.`, + pos: item.getStart(), + code: '10905324' + }); + return; + } + } if (info.childStructInfo.isComponentV2) { if (info.forbiddenInitPropsV2.includes(itemName)) { const propType: string = getForbbidenInitPropsV2Type(itemName, info); log.push({ type: LogType.ERROR, message: `The '${propType}' property '${itemName}' in the custom component '${info.childName}'` + - ` cannot be initialized here (forbidden to specify).`, + ` cannot be initialized here (forbidden to specify). 1.1 use 1.2 validateChildProperty.`, pos: item.getStart(), code: '10905324' }); diff --git a/compiler/src/interop/src/process_import.ts b/compiler/src/interop/src/process_import.ts index 8ca3073c3a7d8118f3354f16524e75efa63cb733..1e7099f3acb93a31fac2f3d38f3e5068bd8a3c5f 100644 --- a/compiler/src/interop/src/process_import.ts +++ b/compiler/src/interop/src/process_import.ts @@ -934,6 +934,15 @@ function setComponentCollectionInfo(name: string, componentSet: IComponentSet, i ...componentSet.provides, ...componentSet.objectLinks ); asComponentNameStructInfo.linkDecoratorsV1.push(...componentSet.links); + asComponentNameStructInfo.addDecoratorsBatch('@state', [...componentSet.states]); + asComponentNameStructInfo.addDecoratorsBatch('@prop', [...componentSet.props]); + asComponentNameStructInfo.addDecoratorsBatch('@provide', [...componentSet.provides]); + asComponentNameStructInfo.addDecoratorsBatch('@consume', [...componentSet.consumes]); + asComponentNameStructInfo.addDecoratorsBatch('@ObjectLink', [...componentSet.objectLinks]); + asComponentNameStructInfo.addDecoratorsBatch('@StorageLink', [...componentSet.storageLinks]); + asComponentNameStructInfo.addDecoratorsBatch('@StorageProp', [...componentSet.storageProps]); + asComponentNameStructInfo.addDecoratorsBatch('@LocalStorageLink', [...componentSet.localStorageLink]); + asComponentNameStructInfo.addDecoratorsBatch('@LocalStorageProp', [...componentSet.localStorageProp]); return; } const nameStructInfo: StructInfo = processStructComponentV2.getOrCreateStructInfo(name); @@ -942,6 +951,15 @@ function setComponentCollectionInfo(name: string, componentSet: IComponentSet, i ...componentSet.provides, ...componentSet.objectLinks ); nameStructInfo.linkDecoratorsV1.push(...componentSet.links); + nameStructInfo.addDecoratorsBatch('@state', [...componentSet.states]); + nameStructInfo.addDecoratorsBatch('@prop', [...componentSet.props]); + nameStructInfo.addDecoratorsBatch('@provide', [...componentSet.provides]); + nameStructInfo.addDecoratorsBatch('@consume', [...componentSet.consumes]); + nameStructInfo.addDecoratorsBatch('@ObjectLink', [...componentSet.objectLinks]); + nameStructInfo.addDecoratorsBatch('@StorageLink', [...componentSet.storageLinks]); + nameStructInfo.addDecoratorsBatch('@StorageProp', [...componentSet.storageProps]); + nameStructInfo.addDecoratorsBatch('@LocalStorageLink', [...componentSet.localStorageLink]); + nameStructInfo.addDecoratorsBatch('@LocalStorageProp', [...componentSet.localStorageProp]); } function parseComponentInImportNode(originNode: ts.StructDeclaration, name: string, diff --git a/compiler/src/interop/src/process_struct_componentV2.ts b/compiler/src/interop/src/process_struct_componentV2.ts index 17baf35db8be0e6ec7b6a0c2d9a7fd763d20cf49..7d82effdfa10d09e85120f3e740614ea90752f46 100644 --- a/compiler/src/interop/src/process_struct_componentV2.ts +++ b/compiler/src/interop/src/process_struct_componentV2.ts @@ -83,6 +83,12 @@ export class StructInfo { staticPropertySet: Set = new Set(); computedDecoratorSet: Set = new Set(); monitorDecoratorSet: Set = new Set(); + updatePropsDecoratorsV1Receive: Map = new Map(); + addDecoratorsBatch(decoratorType: string, decorators: any[]): void { + if (!decorators.length) return; + const existing = this.updatePropsDecoratorsV1Receive.get(decoratorType) || []; + this.updatePropsDecoratorsV1Receive.set(decoratorType, [...existing, ...decorators]); + } } const structMapInEts: Map = new Map(); diff --git a/compiler/src/interop/src/validate_ui_syntax.ts b/compiler/src/interop/src/validate_ui_syntax.ts index 75bc3703d9024e23da99ea3204ddc794a72f52dd..2434555132dacd930c186448e309c310121d55e8 100644 --- a/compiler/src/interop/src/validate_ui_syntax.ts +++ b/compiler/src/interop/src/validate_ui_syntax.ts @@ -537,6 +537,40 @@ function validatePropertyInStruct(structContext: boolean, decoratorNode: ts.Iden } } +const v1ComponentDecoratorsReceive: string[] = [ + 'State', 'Prop', 'Link', 'Provide', 'Consume', 'ObjectLink', + 'StorageLink', 'StorageProp', 'LocalStorageLink', 'LocalStorageProp', 'Observed' +]; +const v2ComponentDecoratorsReceive: string[] = [ + 'Local', 'Param', 'Event', 'Provider', 'ObservedV2', 'Consumer' +]; +function validateInteropPropertyInStruct(structContext: boolean, decoratorNode: ts.Identifier, + decoratorName: string, sourceFileNode: ts.SourceFile, log: LogInfo[]): void { + if (structContext) { + const isV1DecoratorReceive: boolean = v1ComponentDecoratorsReceive.includes(decoratorName); + const isV2DecoratorReceive: boolean = v2ComponentDecoratorsReceive.includes(decoratorName); + if (!isV2DecoratorReceive && !isV1DecoratorReceive) { + return; + } + const classResult: ClassDecoratorResult = new ClassDecoratorResult(); + const propertyNode: ts.PropertyDeclaration = getPropertyNodeByDecorator(decoratorNode); + const checker: ts.TypeChecker | undefined = CurrentProcessFile.getChecker(); + if (propertyNode && propertyNode.type && checker) { + validatePropertyType(propertyNode.type, classResult); + } + let message: string; + if (isV1DecoratorReceive && classResult.hasObservedV2) { + message = `The type of the '@${decoratorName}' property can not be a class decorated with '@ObservedV2'.`; + addLog(LogType.ERROR, message, decoratorNode.getStart(), log, sourceFileNode, { code: '10905348' }); + return; + } else if (isV2DecoratorReceive && classResult.hasObserved) { + message = `The type of the '@${decoratorName}' property can not be a class decorated with '@Observed'.`; + addLog(LogType.ERROR, message, decoratorNode.getStart(), log, sourceFileNode, { code: '10905348' }); + return; + } + } +} + function getPropertyNodeByDecorator(decoratorNode: ts.Identifier): ts.PropertyDeclaration { if (ts.isDecorator(decoratorNode.parent) && ts.isPropertyDeclaration(decoratorNode.parent.parent)) { return decoratorNode.parent.parent; @@ -1457,6 +1491,15 @@ function collectComponentProps(node: ts.StructDeclaration, structInfo: StructInf ...componentSet.provides, ...componentSet.objectLinks ); structInfo.linkDecoratorsV1.push(...componentSet.links); + structInfo.addDecoratorsBatch('@state', [...componentSet.states]); + structInfo.addDecoratorsBatch('@prop', [...componentSet.props]); + structInfo.addDecoratorsBatch('@provide', [...componentSet.provides]); + structInfo.addDecoratorsBatch('@consume', [...componentSet.consumes]); + structInfo.addDecoratorsBatch('@ObjectLink', [...componentSet.objectLinks]); + structInfo.addDecoratorsBatch('@StorageLink', [...componentSet.storageLinks]); + structInfo.addDecoratorsBatch('@StorageProp', [...componentSet.storageProps]); + structInfo.addDecoratorsBatch('@LocalStorageLink', [...componentSet.localStorageLink]); + structInfo.addDecoratorsBatch('@LocalStorageProp', [...componentSet.localStorageProp]); } export function getComponentSet(node: ts.StructDeclaration, uiCheck: boolean = false): IComponentSet {