From 5342dcdc002525b51852ed31769b91ecfe2aa658 Mon Sep 17 00:00:00 2001 From: KRVPerera Date: Tue, 16 Jun 2020 23:46:00 +0530 Subject: [PATCH] Remove object readonly check for annotation values --- .../semantics/analyzer/SymbolEnter.java | 70 ++++++++++++++++++- .../compiler/semantics/model/SymbolTable.java | 1 - 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolEnter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolEnter.java index 730e68d2da1a..774dc952201c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolEnter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolEnter.java @@ -65,10 +65,13 @@ import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BIntersectionType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BMapType; import org.wso2.ballerinalang.compiler.semantics.model.types.BObjectType; import org.wso2.ballerinalang.compiler.semantics.model.types.BRecordType; import org.wso2.ballerinalang.compiler.semantics.model.types.BServiceType; import org.wso2.ballerinalang.compiler.semantics.model.types.BStructureType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTableType; +import org.wso2.ballerinalang.compiler.semantics.model.types.BTupleType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.semantics.model.types.BTypeIdSet; import org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType; @@ -1361,8 +1364,22 @@ private boolean isValidAnnotationType(BType type) { switch (type.tag) { case TypeTags.MAP: + BType constraintType = ((BMapType) type).constraint; + return isAnyDataOrReadOnlyTypeSkippingObjectType(constraintType); case TypeTags.RECORD: - return types.isAssignable(type, symTable.anydataOrReadOnlyMapType); + BRecordType recordType = (BRecordType) type; + for (BField field : recordType.fields.values()) { + if (!isAnyDataOrReadOnlyTypeSkippingObjectType(field.type)) { + return false; + } + } + + BType recordRestType = recordType.restFieldType; + if (recordRestType == null || recordRestType == symTable.noType) { + return true; + } + + return isAnyDataOrReadOnlyTypeSkippingObjectType(recordRestType); case TypeTags.ARRAY: BType elementType = ((BArrayType) type).eType; if ((elementType.tag == TypeTags.MAP) || (elementType.tag == TypeTags.RECORD)) { @@ -1374,6 +1391,57 @@ private boolean isValidAnnotationType(BType type) { return types.isAssignable(type, symTable.trueType); } + private boolean isAnyDataOrReadOnlyTypeSkippingObjectType(BType type) { + if (type == symTable.semanticError) { + return false; + } + switch (type.tag) { + case TypeTags.OBJECT: + return true; + case TypeTags.RECORD: + BRecordType recordType = (BRecordType) type; + for (BField field : recordType.fields.values()) { + if (!isAnyDataOrReadOnlyTypeSkippingObjectType(field.type)) { + return false; + } + } + BType recordRestType = recordType.restFieldType; + if (recordRestType == null || recordRestType == symTable.noType) { + return true; + } + return isAnyDataOrReadOnlyTypeSkippingObjectType(recordRestType); + case TypeTags.MAP: + BType constraintType = ((BMapType) type).constraint; + return isAnyDataOrReadOnlyTypeSkippingObjectType(constraintType); + case TypeTags.UNION: + for (BType memberType : ((BUnionType) type).getMemberTypes()) { + if (!isAnyDataOrReadOnlyTypeSkippingObjectType(memberType)) { + return false; + } + } + return true; + case TypeTags.TUPLE: + BTupleType tupleType = (BTupleType) type; + for (BType tupMemType : tupleType.getTupleTypes()) { + if (!isAnyDataOrReadOnlyTypeSkippingObjectType(tupMemType)) { + return false; + } + } + BType tupRestType = tupleType.restType; + if (tupRestType == null) { + return true; + } + return isAnyDataOrReadOnlyTypeSkippingObjectType(tupRestType); + case TypeTags.TABLE: + return isAnyDataOrReadOnlyTypeSkippingObjectType(((BTableType) type).constraint); + case TypeTags.ARRAY: + return isAnyDataOrReadOnlyTypeSkippingObjectType(((BArrayType) type).getElementType()); + } + + return types.isAssignable(type, symTable.anydataOrReadOnlyType); + } + + /** * Visit each compilation unit (.bal file) and add each top-level node * in the compilation unit to the package node. diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java index 89bd7aa40a98..cdbfc148af28 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/SymbolTable.java @@ -137,7 +137,6 @@ public class SymbolTable { public final BType semanticError = new BType(TypeTags.SEMANTIC_ERROR, null); public final BType nullSet = new BType(TypeTags.NULL_SET, null); public final BUnionType anydataOrReadOnlyType = BUnionType.create(null, anydataType, readonlyType); - public final BType anydataOrReadOnlyMapType = new BMapType(TypeTags.MAP, anydataOrReadOnlyType, null); public BType streamType = new BStreamType(TypeTags.STREAM, anydataType, null, null); public BType tableType = new BTableType(TypeTags.TABLE, anydataType, null);