From 9593c36193bde6c1af1273c699273d4c38767acf Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 01:40:41 +0530 Subject: [PATCH 01/43] Generate closures for annotations of local record types --- .../compiler/desugar/AnnotationDesugar.java | 81 +- .../compiler/desugar/Desugar.java | 8 + .../desugar/LocalAnnotationDesugar.java | 1463 +++++++++++++++++ .../model/symbols/BRecordTypeSymbol.java | 1 + .../compiler/tree/BLangPackage.java | 3 + 5 files changed, 1545 insertions(+), 11 deletions(-) create mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 57d7e6363a35..7e62b08f2803 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -81,6 +81,7 @@ import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; import org.wso2.ballerinalang.compiler.tree.types.BLangBuiltInRefTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangConstrainedType; +import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangStructureTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangType; import org.wso2.ballerinalang.compiler.tree.types.BLangValueType; @@ -138,6 +139,7 @@ public class AnnotationDesugar { private final Names names; private SymbolResolver symResolver; private ConstantValueResolver constantValueResolver; + private LocalAnnotationDesugar localAnnotationDesugar; public static AnnotationDesugar getInstance(CompilerContext context) { AnnotationDesugar annotationDesugar = context.get(ANNOTATION_DESUGAR_KEY); @@ -155,6 +157,7 @@ private AnnotationDesugar(CompilerContext context) { this.names = Names.getInstance(context); this.symResolver = SymbolResolver.getInstance(context); this.constantValueResolver = ConstantValueResolver.getInstance(context); + this.localAnnotationDesugar = LocalAnnotationDesugar.getInstance(context); } /** @@ -382,7 +385,7 @@ private BLangLambdaFunction defineAnnotations(Location pos, BLangClassDefinition if (!classDef.annAttachments.isEmpty()) { function = defineFunction(pos, pkgID, owner); mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(pos, symTable.mapType); - addAnnotsToLiteral(classDef.annAttachments, mapLiteral, function, env, isLocalObjectCtor); + addAnnotsToLiteral(classDef.annAttachments, mapLiteral, pos, env, isLocalObjectCtor); } for (BLangSimpleVariable field : classDef.fields) { @@ -449,7 +452,7 @@ void defineStatementAnnotations(List attachments, SymbolEnv env) { BLangFunction function = defineFunction(location, pkgID, owner); BLangRecordLiteral mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); - addAnnotsToLiteral(attachments, mapLiteral, function, env, false); + addAnnotsToLiteral(attachments, mapLiteral, location, env, false); } private void defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { @@ -579,7 +582,8 @@ private BLangLambdaFunction defineAnnotations(List an BLangFunction function = defineFunction(location, pkgID, owner); BLangRecordLiteral mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); - addAnnotsToLiteral(annAttachments, mapLiteral, function, env, isLocalObjectCtor); + SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(function, function.symbol.scope, env); + addAnnotsToLiteral(annAttachments, mapLiteral, location, funcEnv, isLocalObjectCtor); if (mapLiteral.fields.isEmpty()) { return null; @@ -599,7 +603,7 @@ private BLangLambdaFunction defineAnnotations(BLangTypeDefinition typeDef, BLang if (!typeDef.annAttachments.isEmpty()) { function = defineFunction(typeDef.pos, pkgID, owner); mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); - addAnnotsToLiteral(typeDef.annAttachments, mapLiteral, function, env, false); + addAnnotsToLiteral(typeDef.annAttachments, mapLiteral, typeDef.pos, env, false); annotFunctionDefined = true; } @@ -628,6 +632,44 @@ private BLangLambdaFunction defineAnnotations(BLangTypeDefinition typeDef, BLang return lambdaFunction; } + + public BLangLambdaFunction defineAnnotationsForLocalRecords(BLangRecordTypeNode recordTypeNode, + BLangPackage pkgNode, SymbolEnv env, PackageID pkgID, + BSymbol owner) { + BLangFunction function = null; + BLangRecordLiteral mapLiteral = null; + BLangLambdaFunction lambdaFunction = null; + + boolean annotFunctionDefined = false; + + for (BLangSimpleVariable field : recordTypeNode.fields) { + + BLangLambdaFunction fieldAnnotLambda = defineAnnotations(field.annAttachments, field.pos, pkgNode, env, + pkgID, owner, false); + if (fieldAnnotLambda != null) { + BInvokableSymbol invokableSymbol = + localAnnotationDesugar.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); + env.scope.define(invokableSymbol.name, invokableSymbol); + if (!annotFunctionDefined) { + function = defineFunction(recordTypeNode.pos, pkgID, owner); + mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); + annotFunctionDefined = true; + } + addInvocationToLiteral(mapLiteral, FIELD + DOT + field.name.value, + field.annAttachments.get(0).pos, invokableSymbol); + } + } + + if (annotFunctionDefined) { + if (mapLiteral.fields.isEmpty()) { + return null; + } + lambdaFunction = addReturnAndDefineLambda(function, mapLiteral, pkgNode, env, pkgID, owner); + } + + return lambdaFunction; + } + private BLangLambdaFunction defineAnnotations(BLangFunction bLangFunction, BLangPackage pkgNode, SymbolEnv env, PackageID pkgID, BSymbol owner) { BLangFunction function = null; @@ -640,7 +682,7 @@ private BLangLambdaFunction defineAnnotations(BLangFunction bLangFunction, BLang if (!bLangFunction.annAttachments.isEmpty()) { function = defineFunction(bLangFunction.pos, pkgID, owner); mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); - addAnnotsToLiteral(bLangFunction.annAttachments, mapLiteral, function, funcEnv, false); + addAnnotsToLiteral(bLangFunction.annAttachments, mapLiteral, bLangFunction.pos, funcEnv, false); annotFunctionDefined = true; } @@ -668,7 +710,8 @@ private BLangLambdaFunction defineAnnotations(BLangFunction bLangFunction, BLang BLangFunction retFunction = defineFunction(bLangFunction.pos, pkgID, owner); BLangRecordLiteral retMapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); - addAnnotsToLiteral(bLangFunction.returnTypeAnnAttachments, retMapLiteral, retFunction, funcEnv, false); + addAnnotsToLiteral(bLangFunction.returnTypeAnnAttachments, retMapLiteral, bLangFunction.pos, funcEnv, + false); BLangLambdaFunction returnAnnotLambda = addReturnAndDefineLambda(retFunction, retMapLiteral, pkgNode, env, pkgID, owner); addInvocationToLiteral(mapLiteral, RETURNS, bLangFunction.returnTypeAnnAttachments.get(0).pos, @@ -766,7 +809,7 @@ private BLangFunction defineFunction(Location pos, PackageID pkgID, BSymbol owne String funcName = ANNOT_FUNC + UNDERSCORE + annotFuncCount++; BLangFunction function = ASTBuilderUtil.createFunction(pos, funcName); function.setBType(new BInvokableType(Collections.emptyList(), symTable.mapType, null)); - + function.flagSet.add(Flag.PUBLIC); BLangBuiltInRefTypeNode anyMapType = (BLangBuiltInRefTypeNode) TreeBuilder.createBuiltInReferenceTypeNode(); anyMapType.typeKind = TypeKind.MAP; anyMapType.pos = pos; @@ -809,12 +852,12 @@ private BLangLambdaFunction addReturnAndDefineLambda(BLangFunction function, BLa pkgNode.functions.add(function); pkgNode.topLevelNodes.add(function); - lambdaFunction.function = desugar.rewrite(lambdaFunction.function, lambdaFunction.capturedClosureEnv); + pkgNode.anonFunctions.add(lambdaFunction); return lambdaFunction; } - private void addAnnotsToLiteral(List nodeAttachments, BLangRecordLiteral mapLiteral, - BLangFunction function, SymbolEnv env, boolean isLocalObjectCtor) { + public void addAnnotsToLiteral(List nodeAttachments, BLangRecordLiteral mapLiteral, + Location pos, SymbolEnv env, boolean isLocalObjectCtor) { Map> attachments = collectAnnotationAttachments(nodeAttachments, env); @@ -858,7 +901,7 @@ private void addAnnotsToLiteral(List nodeAttachments, // }; // // Adds // { ..., v1: [{ value: 1 }, { value: 2 }], ... } - addAnnotArray(function.pos, annotationSymbol.bvmAlias(), attachedType, + addAnnotArray(pos, annotationSymbol.bvmAlias(), attachedType, attachments.get(annotationSymbol), mapLiteral, isLocalObjectCtor); } } @@ -960,6 +1003,22 @@ private void addInvocationToLiteral(BLangRecordLiteral recordLiteral, String ide ASTBuilderUtil.createLiteral(pos, symTable.stringType, identifier), annotFuncInvocation)); } + private void addInvocationToLiteral(BLangRecordLiteral recordLiteral, String identifier, + Location pos, BInvokableSymbol invokableSymbol) { + BLangInvocation annotFuncInvocation = getInvocation(invokableSymbol); + recordLiteral.fields.add(ASTBuilderUtil.createBLangRecordKeyValue( + ASTBuilderUtil.createLiteral(pos, symTable.stringType, identifier), annotFuncInvocation)); + } + + private BLangInvocation getInvocation(BInvokableSymbol symbol) { + BLangInvocation funcInvocation = (BLangInvocation) TreeBuilder.createInvocationNode(); + funcInvocation.setBType(symbol.retType); + funcInvocation.symbol = symbol; + funcInvocation.name = ASTBuilderUtil.createIdentifier(symbol.pos, symbol.name.value); + funcInvocation.functionPointerInvocation = true; + return funcInvocation; + } + private void addAnnotValueAssignmentToMap(BLangSimpleVariable mapVar, String identifier, BlockNode target, Location targetPos, BLangExpression expression) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index a0f152046bb9..4c2245003e29 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -374,6 +374,7 @@ public class Desugar extends BLangNodeVisitor { private final SymbolEnter symbolEnter; private ClosureDesugar closureDesugar; private ParameterDesugar parameterDesugar; + private LocalAnnotationDesugar localAnnotationDesugar; private QueryDesugar queryDesugar; private TransactionDesugar transactionDesugar; private ObservabilityDesugar observabilityDesugar; @@ -447,6 +448,7 @@ private Desugar(CompilerContext context) { this.symbolEnter = SymbolEnter.getInstance(context); this.closureDesugar = ClosureDesugar.getInstance(context); this.parameterDesugar = ParameterDesugar.getInstance(context); + this.localAnnotationDesugar = LocalAnnotationDesugar.getInstance(context); this.queryDesugar = QueryDesugar.getInstance(context); this.transactionDesugar = TransactionDesugar.getInstance(context); this.observabilityDesugar = ObservabilityDesugar.getInstance(context); @@ -774,6 +776,7 @@ public void visit(BLangPackage pkgNode) { // create closures for default values parameterDesugar.visit(pkgNode); + localAnnotationDesugar.visit(pkgNode); // Initialize the annotation map annotationDesugar.initializeAnnotationMap(pkgNode); @@ -823,6 +826,11 @@ public void visit(BLangPackage pkgNode) { pkgNode.startFunction = rewrite(pkgNode.startFunction, env); pkgNode.stopFunction = rewrite(pkgNode.stopFunction, env); + for (int i = 0; i < pkgNode.anonFunctions.size(); i++) { + BLangLambdaFunction function = pkgNode.anonFunctions.get(i); + pkgNode.anonFunctions.set(i, rewrite(function, function.capturedClosureEnv)); + } + for (int i = 0; i < pkgNode.functions.size(); i++) { BLangFunction function = pkgNode.functions.get(i); if (!function.flagSet.contains(Flag.LAMBDA) || function.name.value.contains(MockDesugar.MOCK_FUNCTION)) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java new file mode 100644 index 000000000000..c6f312d2fc24 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java @@ -0,0 +1,1463 @@ +package org.wso2.ballerinalang.compiler.desugar; + +import org.ballerinalang.model.TreeBuilder; +import org.ballerinalang.model.elements.Flag; +import org.ballerinalang.model.elements.PackageID; +import org.ballerinalang.model.tree.NodeKind; +import org.ballerinalang.model.tree.expressions.RecordLiteralNode; +import org.wso2.ballerinalang.compiler.semantics.analyzer.SymbolResolver; +import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; +import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; +import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.tree.BLangAnnotation; +import org.wso2.ballerinalang.compiler.tree.BLangAnnotationAttachment; +import org.wso2.ballerinalang.compiler.tree.BLangBlockFunctionBody; +import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; +import org.wso2.ballerinalang.compiler.tree.BLangErrorVariable; +import org.wso2.ballerinalang.compiler.tree.BLangExprFunctionBody; +import org.wso2.ballerinalang.compiler.tree.BLangExternalFunctionBody; +import org.wso2.ballerinalang.compiler.tree.BLangFunction; +import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; +import org.wso2.ballerinalang.compiler.tree.BLangInvokableNode; +import org.wso2.ballerinalang.compiler.tree.BLangMarkdownDocumentation; +import org.wso2.ballerinalang.compiler.tree.BLangNode; +import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; +import org.wso2.ballerinalang.compiler.tree.BLangPackage; +import org.wso2.ballerinalang.compiler.tree.BLangRecordVariable; +import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; +import org.wso2.ballerinalang.compiler.tree.BLangService; +import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; +import org.wso2.ballerinalang.compiler.tree.BLangTableKeyTypeConstraint; +import org.wso2.ballerinalang.compiler.tree.BLangTupleVariable; +import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; +import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAnnotAccessExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangDynamicArgExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorVarRef; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangFieldBasedAccess; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangGroupExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangIgnoreExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangIndexBasedAccess; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangInferredTypedescDefaultNode; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangIsAssignableExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangIsLikeExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLetExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownDocumentationLine; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangRawTemplateLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordVarRef; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangRegExpTemplateLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangRestArgsExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangServiceConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTransactionalExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTupleVarRef; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeConversionExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeInit; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeTestExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypedescExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangUnaryExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWaitExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWaitForAllExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLCommentLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLElementAccess; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLElementLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLNavigationAccess; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLProcInsLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQName; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQuotedString; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLSequenceLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLTextLiteral; +import org.wso2.ballerinalang.compiler.tree.statements.BLangAssignment; +import org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt; +import org.wso2.ballerinalang.compiler.tree.statements.BLangBreak; +import org.wso2.ballerinalang.compiler.tree.statements.BLangCompoundAssignment; +import org.wso2.ballerinalang.compiler.tree.statements.BLangContinue; +import org.wso2.ballerinalang.compiler.tree.statements.BLangDo; +import org.wso2.ballerinalang.compiler.tree.statements.BLangErrorDestructure; +import org.wso2.ballerinalang.compiler.tree.statements.BLangErrorVariableDef; +import org.wso2.ballerinalang.compiler.tree.statements.BLangExpressionStmt; +import org.wso2.ballerinalang.compiler.tree.statements.BLangFail; +import org.wso2.ballerinalang.compiler.tree.statements.BLangForeach; +import org.wso2.ballerinalang.compiler.tree.statements.BLangForkJoin; +import org.wso2.ballerinalang.compiler.tree.statements.BLangIf; +import org.wso2.ballerinalang.compiler.tree.statements.BLangLock; +import org.wso2.ballerinalang.compiler.tree.statements.BLangMatchStatement; +import org.wso2.ballerinalang.compiler.tree.statements.BLangPanic; +import org.wso2.ballerinalang.compiler.tree.statements.BLangRecordDestructure; +import org.wso2.ballerinalang.compiler.tree.statements.BLangRecordVariableDef; +import org.wso2.ballerinalang.compiler.tree.statements.BLangRetry; +import org.wso2.ballerinalang.compiler.tree.statements.BLangRetryTransaction; +import org.wso2.ballerinalang.compiler.tree.statements.BLangReturn; +import org.wso2.ballerinalang.compiler.tree.statements.BLangRollback; +import org.wso2.ballerinalang.compiler.tree.statements.BLangSimpleVariableDef; +import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; +import org.wso2.ballerinalang.compiler.tree.statements.BLangTransaction; +import org.wso2.ballerinalang.compiler.tree.statements.BLangTupleDestructure; +import org.wso2.ballerinalang.compiler.tree.statements.BLangTupleVariableDef; +import org.wso2.ballerinalang.compiler.tree.statements.BLangWhile; +import org.wso2.ballerinalang.compiler.tree.statements.BLangWorkerSend; +import org.wso2.ballerinalang.compiler.tree.statements.BLangXMLNSStatement; +import org.wso2.ballerinalang.compiler.tree.types.BLangArrayType; +import org.wso2.ballerinalang.compiler.tree.types.BLangBuiltInRefTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangConstrainedType; +import org.wso2.ballerinalang.compiler.tree.types.BLangErrorType; +import org.wso2.ballerinalang.compiler.tree.types.BLangFiniteTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangFunctionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangIntersectionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangLetVariable; +import org.wso2.ballerinalang.compiler.tree.types.BLangObjectTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangStreamType; +import org.wso2.ballerinalang.compiler.tree.types.BLangTableTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangTupleTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangType; +import org.wso2.ballerinalang.compiler.tree.types.BLangUnionTypeNode; +import org.wso2.ballerinalang.compiler.tree.types.BLangUserDefinedType; +import org.wso2.ballerinalang.compiler.tree.types.BLangValueType; +import org.wso2.ballerinalang.compiler.util.ClosureVarSymbol; +import org.wso2.ballerinalang.compiler.util.CompilerContext; +import org.wso2.ballerinalang.util.Flags; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; + +/** + * Local annotation desugar for create closures for annotations. + * + * @since 2.0.0 + */ +public class LocalAnnotationDesugar extends BLangNodeVisitor { + private static final CompilerContext.Key LOCAL_ANNOTATION_DESUGAR_KEY = + new CompilerContext.Key<>(); + private Queue queue; + + private SymbolTable symTable; + private SymbolEnv env; + private BLangNode result; + private SymbolResolver symResolver; + private AnnotationDesugar annotationDesugar; + + public static LocalAnnotationDesugar getInstance(CompilerContext context) { + LocalAnnotationDesugar parameterDesugar = context.get(LOCAL_ANNOTATION_DESUGAR_KEY); + if (parameterDesugar == null) { + parameterDesugar = new LocalAnnotationDesugar(context); + } + + return parameterDesugar; + } + + private LocalAnnotationDesugar(CompilerContext context) { + context.put(LOCAL_ANNOTATION_DESUGAR_KEY, this); + this.symTable = SymbolTable.getInstance(context); + this.queue = new LinkedList<>(); + this.symResolver = SymbolResolver.getInstance(context); + this.annotationDesugar = AnnotationDesugar.getInstance(context); + } + + @Override + public void visit(BLangPackage pkgNode) { + SymbolEnv pkgEnv = this.symTable.pkgEnvMap.get(pkgNode.symbol); + + for (int i = 0; i < pkgNode.functions.size(); i++) { + BLangFunction bLangFunction = pkgNode.functions.get(i); + if (!bLangFunction.flagSet.contains(Flag.LAMBDA)) { + SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(bLangFunction, bLangFunction.symbol.scope, pkgEnv); + rewriteParamsAndReturnTypeOfFunction(bLangFunction, funcEnv); + } + } + pkgNode.services.forEach(service -> rewrite(service, pkgEnv)); + pkgNode.typeDefinitions.forEach(typeDefinition -> rewrite(typeDefinition, pkgEnv)); + pkgNode.xmlnsList.forEach(xmlns -> rewrite(xmlns, pkgEnv)); + pkgNode.constants.forEach(constant -> rewrite(constant, pkgEnv)); + pkgNode.annotations.forEach(annotation -> rewrite(annotation, pkgEnv)); + pkgNode.initFunction = rewrite(pkgNode.initFunction, pkgEnv); + pkgNode.classDefinitions = rewrite(pkgNode.classDefinitions, pkgEnv); + pkgNode.globalVars.forEach(globalVar -> rewrite(globalVar, pkgEnv)); + addClosuresToGlobalVariableList(pkgEnv); + for (int i = 0; i < pkgNode.functions.size(); i++) { + BLangFunction bLangFunction = pkgNode.functions.get(i); + if (!bLangFunction.flagSet.contains(Flag.LAMBDA)) { + rewrite(bLangFunction, pkgEnv); + } + } + + result = pkgNode; + } + + private void addClosuresToGlobalVariableList(SymbolEnv pkgEnv) { + Iterator iterator = queue.iterator(); + while (iterator.hasNext()) { + BLangSimpleVariable simpleVariable = queue.poll().var; + simpleVariable.flagSet.add(Flag.PUBLIC); + simpleVariable.symbol.flags |= Flags.PUBLIC; + pkgEnv.enclPkg.globalVars.add(0, rewrite(simpleVariable, pkgEnv)); + } + } + + @Override + public void visit(BLangFunction funcNode) { + SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(funcNode, funcNode.symbol.scope, env); + + if (funcNode.flagSet.contains(Flag.LAMBDA)) { + rewriteParamsAndReturnTypeOfFunction(funcNode, funcEnv); + } + funcNode.body = rewrite(funcNode.body, funcEnv); + result = funcNode; + } + + public void rewriteParamsAndReturnTypeOfFunction(BLangFunction funcNode, SymbolEnv funcEnv) { + for (BLangSimpleVariable bLangSimpleVariable : funcNode.requiredParams) { + rewrite(bLangSimpleVariable, funcEnv); + } + + if (funcNode.restParam != null) { + funcNode.restParam = rewrite(funcNode.restParam, funcEnv); + } + + if (funcNode.returnTypeNode != null && funcNode.returnTypeNode.getKind() != null) { + funcNode.returnTypeNode = rewrite(funcNode.returnTypeNode, funcEnv); + } + } + + @Override + public void visit(BLangBlockFunctionBody body) { + SymbolEnv blockEnv = SymbolEnv.createFuncBodyEnv(body, env); + body.stmts = rewriteStmt(body.stmts, blockEnv); + result = body; + } + + @Override + public void visit(BLangRawTemplateLiteral rawTemplateLiteral) { + result = rawTemplateLiteral; + } + + @Override + public void visit(BLangExprFunctionBody exprBody) { + exprBody.expr = rewriteExpr(exprBody.expr); + result = exprBody; + } + + @Override + public void visit(BLangResourceFunction resourceFunction) { + visit((BLangFunction) resourceFunction); + } + + @Override + public void visit(BLangExternalFunctionBody body) { + result = body; + } + + @Override + public void visit(BLangBlockStmt blockNode) { + SymbolEnv blockEnv = SymbolEnv.createBlockEnv(blockNode, env); + blockNode.stmts = rewriteStmt(blockNode.stmts, blockEnv); + + result = blockNode; + } + + @Override + public void visit(BLangService serviceNode) { + result = serviceNode; + } + + @Override + public void visit(BLangSimpleVariableDef varDefNode) { + varDefNode.var = rewrite(varDefNode.var, env); + result = varDefNode; + } + + @Override + public void visit(BLangReturn returnNode) { + if (returnNode.expr != null) { + returnNode.expr = rewriteExpr(returnNode.expr); + } + result = returnNode; + } + + @Override + public void visit(BLangTypeDefinition typeDef) { + typeDef.typeNode = rewrite(typeDef.typeNode, env); + result = typeDef; + } + + @Override + public void visit(BLangIntersectionTypeNode intersectionTypeNode) { + List rewrittenConstituents = new ArrayList<>(); + for (BLangType constituentTypeNode : intersectionTypeNode.constituentTypeNodes) { + rewrittenConstituents.add(rewrite(constituentTypeNode, env)); + } + intersectionTypeNode.constituentTypeNodes = rewrittenConstituents; + result = intersectionTypeNode; + } + + @Override + public void visit(BLangClassDefinition classDefinition) { + SymbolEnv classEnv = SymbolEnv.createClassEnv(classDefinition, classDefinition.symbol.scope, env); + for (BLangSimpleVariable bLangSimpleVariable : classDefinition.fields) { + bLangSimpleVariable.typeNode = rewrite(bLangSimpleVariable.typeNode, classEnv); + } + result = classDefinition; + } + + @Override + public void visit(BLangObjectTypeNode objectTypeNode) { + for (BLangSimpleVariable field : objectTypeNode.fields) { + rewrite(field, env); + } + result = objectTypeNode; + } + + @Override + public void visit(BLangObjectConstructorExpression objectConstructorExpression) { + objectConstructorExpression.typeInit = rewriteExpr(objectConstructorExpression.typeInit); + result = objectConstructorExpression; + } + + @Override + public void visit(BLangRecordTypeNode recordTypeNode) { + PackageID pkgID = recordTypeNode.symbol.pkgID; + BSymbol owner = recordTypeNode.symbol.owner; + + if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { + BLangLambdaFunction lambdaFunction = + annotationDesugar.defineAnnotationsForLocalRecords(recordTypeNode, env.enclPkg, env, pkgID, owner); + if (lambdaFunction != null) { + BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); + ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = + createSimpleVariable(invokableSymbol); + } + } + + for (BLangSimpleVariable field : recordTypeNode.fields) { + rewrite(field, env); + } + recordTypeNode.restFieldType = rewrite(recordTypeNode.restFieldType, env); + result = recordTypeNode; + } + + private BLangInvocation getInvocation(BInvokableSymbol symbol) { + BLangInvocation funcInvocation = (BLangInvocation) TreeBuilder.createInvocationNode(); + funcInvocation.setBType(symbol.retType); + funcInvocation.symbol = symbol; + funcInvocation.name = ASTBuilderUtil.createIdentifier(symbol.pos, symbol.name.value); + funcInvocation.functionPointerInvocation = true; + return funcInvocation; + } + + @Override + public void visit(BLangTupleTypeNode tupleTypeNode) { + List rewrittenMembers = new ArrayList<>(); + tupleTypeNode.memberTypeNodes.forEach(member -> rewrittenMembers.add(rewrite(member, env))); + tupleTypeNode.memberTypeNodes = rewrittenMembers; + tupleTypeNode.restParamType = rewrite(tupleTypeNode.restParamType, env); + result = tupleTypeNode; + } + + @Override + public void visit(BLangFiniteTypeNode finiteTypeNode) { + finiteTypeNode.valueSpace.forEach(param -> rewrite(param, env)); + result = finiteTypeNode; + } + + @Override + public void visit(BLangArrayType arrayType) { + arrayType.elemtype = rewrite(arrayType.elemtype, env); + result = arrayType; + } + + @Override + public void visit(BLangUserDefinedType userDefinedType) { + result = userDefinedType; + } + + @Override + public void visit(BLangUnionTypeNode unionTypeNode) { + List rewrittenMembers = new ArrayList<>(); + unionTypeNode.memberTypeNodes.forEach(typeNode -> rewrittenMembers.add(rewrite(typeNode, env))); + unionTypeNode.memberTypeNodes = rewrittenMembers; + result = unionTypeNode; + } + + @Override + public void visit(BLangValueType valueType) { + result = valueType; + } + + @Override + public void visit(BLangBuiltInRefTypeNode builtInRefTypeNode) { + result = builtInRefTypeNode; + } + + @Override + public void visit(BLangStreamType streamType) { + streamType.constraint = rewrite(streamType.constraint, env); + streamType.error = rewrite(streamType.error, env); + result = streamType; + } + + @Override + public void visit(BLangConstrainedType constrainedType) { + constrainedType.constraint = rewrite(constrainedType.constraint, env); + result = constrainedType; + } + + @Override + public void visit(BLangErrorType errorType) { + errorType.detailType = rewrite(errorType.detailType, env); + result = errorType; + } + + @Override + public void visit(BLangTableTypeNode tableTypeNode) { + tableTypeNode.constraint = rewrite(tableTypeNode.constraint, env); + tableTypeNode.tableKeyTypeConstraint = rewrite(tableTypeNode.tableKeyTypeConstraint, env); + result = tableTypeNode; + } + + @Override + public void visit(BLangInvocation.BLangResourceAccessInvocation resourceAccessInvocation) { + result = resourceAccessInvocation; + } + + @Override + public void visit(BLangTableKeyTypeConstraint keyTypeConstraint) { + keyTypeConstraint.keyType = rewrite(keyTypeConstraint.keyType, env); + result = keyTypeConstraint; + } + + @Override + public void visit(BLangFunctionTypeNode functionTypeNode) { + SymbolEnv funcEnv = SymbolEnv.createTypeEnv(functionTypeNode, functionTypeNode.getBType().tsymbol.scope, env); + for (BLangSimpleVariable param : functionTypeNode.params) { + rewrite(param, funcEnv); + } + if (functionTypeNode.restParam != null) { + functionTypeNode.restParam.typeNode = rewrite(functionTypeNode.restParam.typeNode, env); + } + if (functionTypeNode.returnTypeNode != null) { + functionTypeNode.returnTypeNode = rewrite(functionTypeNode.returnTypeNode, env); + } + + result = functionTypeNode; + } + + @Override + public void visit(BLangSimpleVariable varNode) { + if (varNode.typeNode != null && varNode.typeNode.getKind() != null) { + varNode.typeNode = rewrite(varNode.typeNode, env); + } + varNode.expr = rewriteExpr(varNode.expr); + result = varNode; + } + + private BSymbol getOwner(SymbolEnv symbolEnv) { + while (symbolEnv.node.getKind() != NodeKind.PACKAGE) { + NodeKind kind = symbolEnv.node.getKind(); + if (kind != NodeKind.BLOCK_FUNCTION_BODY && kind != NodeKind.BLOCK) { + symbolEnv = symbolEnv.enclEnv; + continue; + } + return symbolEnv.enclInvokable.symbol; + } + return symbolEnv.enclPkg.symbol; + } + + public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction) { + BInvokableSymbol invokableSymbol = function.symbol; + BType type = function.getBType(); + BInvokableSymbol varSymbol = new BInvokableSymbol(SymTag.VARIABLE, 0, invokableSymbol.name, + invokableSymbol.pkgID, type, + invokableSymbol.owner, function.pos, VIRTUAL); + varSymbol.params = invokableSymbol.params; + varSymbol.restParam = invokableSymbol.restParam; + varSymbol.retType = invokableSymbol.retType; + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(function.pos, function.name.value, type, + lambdaFunction, varSymbol); + BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(function.pos); + variableDef.var = simpleVariable; + variableDef.setBType(type); + queue.add(variableDef); + + return varSymbol; + } + + public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol) { + BType type = invokableSymbol.retType; + BVarSymbol varSymbol = new BVarSymbol(0, invokableSymbol.name, invokableSymbol.originalName, + invokableSymbol.pkgID, type, invokableSymbol.owner, invokableSymbol.pos, + VIRTUAL); + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(invokableSymbol.pos, + invokableSymbol.name.value, type, getInvocation(invokableSymbol), varSymbol); + BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(invokableSymbol.pos); + variableDef.var = simpleVariable; + variableDef.setBType(type); + queue.add(variableDef); + + return varSymbol; + } + + @Override + public void visit(BLangTupleVariable varNode) { + rewrite(varNode.restVariable, env); + result = varNode; + } + + @Override + public void visit(BLangRecordVariable varNode) { + varNode.expr = rewriteExpr(varNode.expr); + result = varNode; + } + + @Override + public void visit(BLangErrorVariable varNode) { + varNode.expr = rewriteExpr(varNode.expr); + result = varNode; + } + + @Override + public void visit(BLangTupleVariableDef varDefNode) { + varDefNode.var = rewrite(varDefNode.var, env); + result = varDefNode; + } + + @Override + public void visit(BLangRecordVariableDef varDefNode) { + varDefNode.var = rewrite(varDefNode.var, env); + result = varDefNode; + } + + @Override + public void visit(BLangErrorVariableDef varDefNode) { + varDefNode.errorVariable = rewrite(varDefNode.errorVariable, env); + result = varDefNode; + } + + @Override + public void visit(BLangAssignment assignNode) { + assignNode.varRef = rewriteExpr(assignNode.varRef); + assignNode.expr = rewriteExpr(assignNode.expr); + result = assignNode; + } + + @Override + public void visit(BLangTupleDestructure tupleDestructure) { + result = tupleDestructure; + } + + @Override + public void visit(BLangRecordDestructure recordDestructure) { + result = recordDestructure; + } + + @Override + public void visit(BLangErrorDestructure errorDestructure) { + result = errorDestructure; + } + + @Override + public void visit(BLangRetry retryNode) { + retryNode.retryBody = rewrite(retryNode.retryBody, env); + result = retryNode; + } + + @Override + public void visit(BLangRetryTransaction retryTransaction) { + retryTransaction.transaction = rewrite(retryTransaction.transaction, env); + result = retryTransaction; + } + + @Override + public void visit(BLangContinue nextNode) { + result = nextNode; + } + + @Override + public void visit(BLangBreak breakNode) { + result = breakNode; + } + + @Override + public void visit(BLangPanic panicNode) { + panicNode.expr = rewriteExpr(panicNode.expr); + result = panicNode; + } + + @Override + public void visit(BLangDo doNode) { + doNode.body = rewrite(doNode.body, env); + result = doNode; + } + + @Override + public void visit(BLangXMLNSStatement xmlnsStmtNode) { + xmlnsStmtNode.xmlnsDecl = rewrite(xmlnsStmtNode.xmlnsDecl, env); + result = xmlnsStmtNode; + } + + @Override + public void visit(BLangXMLNS xmlnsNode) { + xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); + result = xmlnsNode; + } + + @Override + public void visit(BLangExpressionStmt exprStmtNode) { + exprStmtNode.expr = rewriteExpr(exprStmtNode.expr); + result = exprStmtNode; + } + + @Override + public void visit(BLangFail failNode) { + if (failNode.exprStmt != null) { + failNode.exprStmt = rewrite(failNode.exprStmt, env); + } + result = failNode; + } + + @Override + public void visit(BLangIf ifNode) { + ifNode.expr = rewriteExpr(ifNode.expr); + ifNode.body = rewrite(ifNode.body, env); + ifNode.elseStmt = rewrite(ifNode.elseStmt, env); + result = ifNode; + } + + @Override + public void visit(BLangForeach foreach) { + result = foreach; + } + + @Override + public void visit(BLangWhile whileNode) { + whileNode.expr = rewriteExpr(whileNode.expr); + whileNode.body = rewrite(whileNode.body, env); + result = whileNode; + } + + @Override + public void visit(BLangLock lockNode) { + lockNode.body = rewrite(lockNode.body, env); + result = lockNode; + } + + @Override + public void visit(BLangLock.BLangLockStmt lockNode) { + result = lockNode; + } + + @Override + public void visit(BLangLock.BLangUnLockStmt unLockNode) { + result = unLockNode; + } + + @Override + public void visit(BLangTransaction transactionNode) { + transactionNode.transactionBody = rewrite(transactionNode.transactionBody, env); + result = transactionNode; + } + + @Override + public void visit(BLangRollback rollbackNode) { + rollbackNode.expr = rewriteExpr(rollbackNode.expr); + result = rollbackNode; + } + + @Override + public void visit(BLangTransactionalExpr transactionalExpr) { + result = transactionalExpr; + } + + @Override + public void visit(BLangCommitExpr commitExpr) { + result = commitExpr; + } + + @Override + public void visit(BLangForkJoin forkJoin) { + result = forkJoin; + } + + @Override + public void visit(BLangLiteral literalExpr) { + result = literalExpr; + } + + @Override + public void visit(BLangListConstructorExpr listConstructorExpr) { + listConstructorExpr.exprs = rewriteExprs(listConstructorExpr.exprs); + result = listConstructorExpr; + } + + @Override + public void visit(BLangTableConstructorExpr tableConstructorExpr) { + rewriteExprs(tableConstructorExpr.recordLiteralList); + result = tableConstructorExpr; + } + + @Override + public void visit(BLangListConstructorExpr.BLangJSONArrayLiteral jsonArrayLiteral) { + jsonArrayLiteral.exprs = rewriteExprs(jsonArrayLiteral.exprs); + result = jsonArrayLiteral; + } + + @Override + public void visit(BLangListConstructorExpr.BLangTupleLiteral tupleLiteral) { + tupleLiteral.exprs = rewriteExprs(tupleLiteral.exprs); + result = tupleLiteral; + } + + @Override + public void visit(BLangListConstructorExpr.BLangArrayLiteral arrayLiteral) { + arrayLiteral.exprs = rewriteExprs(arrayLiteral.exprs); + result = arrayLiteral; + } + + @Override + public void visit(BLangRecordLiteral recordLiteral) { + for (RecordLiteralNode.RecordField field : recordLiteral.fields) { + if (field.isKeyValueField()) { + BLangRecordLiteral.BLangRecordKeyValueField keyValueField = + (BLangRecordLiteral.BLangRecordKeyValueField) field; + keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); + keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); + } + } + result = recordLiteral; + } + + @Override + public void visit(BLangSimpleVarRef varRefExpr) { + if (varRefExpr.symbol == null) { + result = varRefExpr; + return; + } + + BLangInvokableNode encInvokable = env.enclInvokable; + if ((varRefExpr.symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { + BVarSymbol varSymbol = (BVarSymbol) varRefExpr.symbol; + if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && + encInvokable.flagSet.contains(Flag.LAMBDA)) { + SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); + BSymbol resolvedSymbol = + symResolver.lookupClosureVarSymbol(encInvokableEnv, varRefExpr.symbol.name, SymTag.VARIABLE); + if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { + varSymbol.closure = true; + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, + varRefExpr.pos)); + } + } + } + + result = varRefExpr; + } + + private void updateFunctionParams(BLangFunction funcNode, BLangSimpleVarRef varRefExpr) { + BInvokableSymbol funcSymbol = funcNode.symbol; + for (BVarSymbol varSymbol : funcSymbol.params) { + if (varSymbol.name.value.equals(varRefExpr.symbol.name.value)) { + varRefExpr.symbol = varSymbol; + return; + } + } + } + + private SymbolEnv findEnclosingInvokableEnv(SymbolEnv env, BLangInvokableNode encInvokable) { + if (env.enclEnv.node != null && env.enclEnv.node.getKind() == NodeKind.ARROW_EXPR) { + return env.enclEnv; + } + + if (env.enclEnv.node != null && (env.enclEnv.node.getKind() == NodeKind.ON_FAIL)) { + return env.enclEnv; + } + + if (env.enclInvokable != null && env.enclInvokable == encInvokable) { + return findEnclosingInvokableEnv(env.enclEnv, encInvokable); + } + return env; + } + + @Override + public void visit(BLangFieldBasedAccess fieldAccessExpr) { + fieldAccessExpr.expr = rewriteExpr(fieldAccessExpr.expr); + + result = fieldAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess indexAccessExpr) { + indexAccessExpr.indexExpr = rewriteExpr(indexAccessExpr.indexExpr); + indexAccessExpr.expr = rewriteExpr(indexAccessExpr.expr); + result = indexAccessExpr; + } + + @Override + public void visit(BLangCompoundAssignment compoundAssignment) { + result = compoundAssignment; + } + + @Override + public void visit(BLangInvocation invocation) { + rewriteInvocationExpr(invocation); + if (invocation.functionPointerInvocation) { + BLangInvokableNode encInvokable = env.enclInvokable; + if (encInvokable != null && encInvokable.flagSet.contains(Flag.LAMBDA)) { + BVarSymbol varSymbol = (BVarSymbol) invocation.symbol; + if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && + encInvokable.flagSet.contains(Flag.LAMBDA)) { + SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); + BSymbol resolvedSymbol = symResolver.lookupClosureVarSymbol(encInvokableEnv, invocation.symbol.name, + SymTag.VARIABLE); + if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { + varSymbol.closure = true; + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, + invocation.pos)); + } + } + } + } + } + + public void rewriteInvocationExpr(BLangInvocation invocation) { + invocation.requiredArgs = rewriteExprs(invocation.requiredArgs); + result = invocation; + + } + + @Override + public void visit(BLangQueryAction queryAction) { + result = queryAction; + } + + @Override + public void visit(BLangCheckPanickedExpr checkedExpr) { + result = checkedExpr; + } + + @Override + public void visit(BLangErrorConstructorExpr errorConstructorExpr) { + rewriteExprs(errorConstructorExpr.positionalArgs); + errorConstructorExpr.errorDetail = rewriteExpr(errorConstructorExpr.errorDetail); + result = errorConstructorExpr; + } + + @Override + public void visit(BLangTypeInit typeInitExpr) { + typeInitExpr.initInvocation = rewriteExpr(typeInitExpr.initInvocation); + result = typeInitExpr; + } + + @Override + public void visit(BLangTernaryExpr ternaryExpr) { + ternaryExpr.expr = rewriteExpr(ternaryExpr.expr); + ternaryExpr.thenExpr = rewriteExpr(ternaryExpr.thenExpr); + ternaryExpr.elseExpr = rewriteExpr(ternaryExpr.elseExpr); + result = ternaryExpr; + } + + @Override + public void visit(BLangWaitExpr waitExpr) { + List exprList = new ArrayList<>(); + waitExpr.exprList.forEach(expression -> exprList.add(rewriteExpr(expression))); + waitExpr.exprList = exprList; + result = waitExpr; + } + + @Override + public void visit(BLangWaitForAllExpr waitExpr) { + result = waitExpr; + } + + @Override + public void visit(BLangTrapExpr trapExpr) { + trapExpr.expr = rewriteExpr(trapExpr.expr); + result = trapExpr; + } + + @Override + public void visit(BLangBinaryExpr binaryExpr) { + binaryExpr.lhsExpr = rewriteExpr(binaryExpr.lhsExpr); + binaryExpr.rhsExpr = rewriteExpr(binaryExpr.rhsExpr); + result = binaryExpr; + } + + @Override + public void visit(BLangElvisExpr elvisExpr) { + result = elvisExpr; + } + + @Override + public void visit(BLangGroupExpr groupExpr) { + groupExpr.expression = rewriteExpr(groupExpr.expression); + result = groupExpr; + } + + @Override + public void visit(BLangUnaryExpr unaryExpr) { + unaryExpr.expr = rewriteExpr(unaryExpr.expr); + result = unaryExpr; + } + + @Override + public void visit(BLangTypeConversionExpr conversionExpr) { + conversionExpr.expr = rewriteExpr(conversionExpr.expr); + conversionExpr.typeNode = rewrite(conversionExpr.typeNode, env); + result = conversionExpr; + } + + @Override + public void visit(BLangLambdaFunction bLangLambdaFunction) { + bLangLambdaFunction.function = rewrite(bLangLambdaFunction.function, bLangLambdaFunction.capturedClosureEnv); + result = bLangLambdaFunction; + } + + @Override + public void visit(BLangArrowFunction bLangArrowFunction) { + result = bLangArrowFunction; + } + + @Override + public void visit(BLangXMLQName xmlQName) { + result = xmlQName; + } + + @Override + public void visit(BLangXMLAttribute xmlAttribute) { + xmlAttribute.name = rewriteExpr(xmlAttribute.name); + xmlAttribute.value = rewriteExpr(xmlAttribute.value); + result = xmlAttribute; + } + + @Override + public void visit(BLangRegExpTemplateLiteral regExpTemplateLiteral) { + List interpolationsList = + symResolver.getListOfInterpolations(regExpTemplateLiteral.reDisjunction.sequenceList); + interpolationsList.forEach(this::rewriteExpr); + result = regExpTemplateLiteral; + } + + @Override + public void visit(BLangXMLElementLiteral xmlElementLiteral) { + xmlElementLiteral.startTagName = rewriteExpr(xmlElementLiteral.startTagName); + xmlElementLiteral.endTagName = rewriteExpr(xmlElementLiteral.endTagName); + xmlElementLiteral.modifiedChildren = rewriteExprs(xmlElementLiteral.modifiedChildren); + xmlElementLiteral.attributes = rewriteExprs(xmlElementLiteral.attributes); + result = xmlElementLiteral; + } + + @Override + public void visit(BLangXMLTextLiteral xmlTextLiteral) { + xmlTextLiteral.textFragments.forEach(this::rewriteExpr); + xmlTextLiteral.concatExpr = rewriteExpr(xmlTextLiteral.concatExpr); + result = xmlTextLiteral; + } + + @Override + public void visit(BLangXMLCommentLiteral xmlCommentLiteral) { + xmlCommentLiteral.textFragments.forEach(this::rewriteExpr); + result = xmlCommentLiteral; + } + + @Override + public void visit(BLangXMLProcInsLiteral xmlProcInsLiteral) { + xmlProcInsLiteral.target = rewriteExpr(xmlProcInsLiteral.target); + xmlProcInsLiteral.dataFragments.forEach(this::rewriteExpr); + result = xmlProcInsLiteral; + } + + @Override + public void visit(BLangXMLQuotedString xmlQuotedString) { + xmlQuotedString.textFragments.forEach(this::rewriteExpr); + result = xmlQuotedString; + } + + @Override + public void visit(BLangStringTemplateLiteral stringTemplateLiteral) { + stringTemplateLiteral.exprs.forEach(this::rewriteExpr); + result = stringTemplateLiteral; + } + + @Override + public void visit(BLangWorkerSend workerSendNode) { + workerSendNode.expr = rewriteExpr(workerSendNode.expr); + result = workerSendNode; + } + + @Override + public void visit(BLangWorkerSyncSendExpr syncSendExpr) { + syncSendExpr.expr = rewriteExpr(syncSendExpr.expr); + result = syncSendExpr; + } + + @Override + public void visit(BLangWorkerReceive workerReceiveNode) { + result = workerReceiveNode; + } + + @Override + public void visit(BLangWorkerFlushExpr workerFlushExpr) { + result = workerFlushExpr; + } + + @Override + public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { + result = localVarRef; + } + + @Override + public void visit(BLangIgnoreExpr ignoreExpr) { + result = ignoreExpr; + } + + @Override + public void visit(BLangDynamicArgExpr dynamicParamExpr) { + dynamicParamExpr.condition = rewriteExpr(dynamicParamExpr.condition); + dynamicParamExpr.conditionalArgument = rewriteExpr(dynamicParamExpr.conditionalArgument); + result = dynamicParamExpr; + } + + @Override + public void visit(BLangSimpleVarRef.BLangPackageVarRef packageVarRef) { + result = packageVarRef; + } + + @Override + public void visit(BLangConstRef constRef) { + result = constRef; + } + + @Override + public void visit(BLangSimpleVarRef.BLangFunctionVarRef functionVarRef) { + result = functionVarRef; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangStructFieldAccessExpr fieldAccessExpr) { + fieldAccessExpr.indexExpr = rewriteExpr(fieldAccessExpr.indexExpr); + fieldAccessExpr.expr = rewriteExpr(fieldAccessExpr.expr); + result = fieldAccessExpr; + } + + @Override + public void visit(BLangFieldBasedAccess.BLangStructFunctionVarRef functionVarRef) { + functionVarRef.expr = rewriteExpr(functionVarRef.expr); + result = functionVarRef; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangMapAccessExpr mapKeyAccessExpr) { + mapKeyAccessExpr.indexExpr = rewriteExpr(mapKeyAccessExpr.indexExpr); + mapKeyAccessExpr.expr = rewriteExpr(mapKeyAccessExpr.expr); + result = mapKeyAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangTableAccessExpr tableKeyAccessExpr) { + tableKeyAccessExpr.indexExpr = rewriteExpr(tableKeyAccessExpr.indexExpr); + tableKeyAccessExpr.expr = rewriteExpr(tableKeyAccessExpr.expr); + result = tableKeyAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangArrayAccessExpr arrayIndexAccessExpr) { + arrayIndexAccessExpr.indexExpr = rewriteExpr(arrayIndexAccessExpr.indexExpr); + arrayIndexAccessExpr.expr = rewriteExpr(arrayIndexAccessExpr.expr); + result = arrayIndexAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangTupleAccessExpr arrayIndexAccessExpr) { + arrayIndexAccessExpr.indexExpr = rewriteExpr(arrayIndexAccessExpr.indexExpr); + arrayIndexAccessExpr.expr = rewriteExpr(arrayIndexAccessExpr.expr); + result = arrayIndexAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangXMLAccessExpr xmlIndexAccessExpr) { + xmlIndexAccessExpr.indexExpr = rewriteExpr(xmlIndexAccessExpr.indexExpr); + xmlIndexAccessExpr.expr = rewriteExpr(xmlIndexAccessExpr.expr); + result = xmlIndexAccessExpr; + } + + @Override + public void visit(BLangXMLElementAccess xmlElementAccess) { + xmlElementAccess.expr = rewriteExpr(xmlElementAccess.expr); + result = xmlElementAccess; + } + + @Override + public void visit(BLangXMLNavigationAccess xmlNavigation) { + xmlNavigation.expr = rewriteExpr(xmlNavigation.expr); + xmlNavigation.childIndex = rewriteExpr(xmlNavigation.childIndex); + result = xmlNavigation; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangJSONAccessExpr jsonAccessExpr) { + jsonAccessExpr.indexExpr = rewriteExpr(jsonAccessExpr.indexExpr); + jsonAccessExpr.expr = rewriteExpr(jsonAccessExpr.expr); + result = jsonAccessExpr; + } + + @Override + public void visit(BLangIndexBasedAccess.BLangStringAccessExpr stringAccessExpr) { + stringAccessExpr.indexExpr = rewriteExpr(stringAccessExpr.indexExpr); + stringAccessExpr.expr = rewriteExpr(stringAccessExpr.expr); + result = stringAccessExpr; + } + + @Override + public void visit(BLangRecordLiteral.BLangMapLiteral mapLiteral) { + for (RecordLiteralNode.RecordField field : mapLiteral.fields) { + if (field.isKeyValueField()) { + BLangRecordLiteral.BLangRecordKeyValueField keyValueField = + (BLangRecordLiteral.BLangRecordKeyValueField) field; + keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); + keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); + continue; + } + + BLangRecordLiteral.BLangRecordSpreadOperatorField spreadField = + (BLangRecordLiteral.BLangRecordSpreadOperatorField) field; + spreadField.expr = rewriteExpr(spreadField.expr); + } + result = mapLiteral; + } + + @Override + public void visit(BLangRecordLiteral.BLangStructLiteral structLiteral) { + for (RecordLiteralNode.RecordField field : structLiteral.fields) { + if (field.isKeyValueField()) { + BLangRecordLiteral.BLangRecordKeyValueField keyValueField = + (BLangRecordLiteral.BLangRecordKeyValueField) field; + keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); + keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); + continue; + } + + BLangRecordLiteral.BLangRecordSpreadOperatorField spreadField = + (BLangRecordLiteral.BLangRecordSpreadOperatorField) field; + spreadField.expr = rewriteExpr(spreadField.expr); + } + + result = structLiteral; + } + + @Override + public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { + waitLiteral.keyValuePairs.forEach(keyValue -> { + if (keyValue.valueExpr != null) { + keyValue.valueExpr = rewriteExpr(keyValue.valueExpr); + } else { + keyValue.keyExpr = rewriteExpr(keyValue.keyExpr); + } + }); + result = waitLiteral; + } + + @Override + public void visit(BLangIsAssignableExpr assignableExpr) { + assignableExpr.lhsExpr = rewriteExpr(assignableExpr.lhsExpr); + result = assignableExpr; + } + + @Override + public void visit(BLangInvocation.BFunctionPointerInvocation fpInvocation) { + fpInvocation.expr = rewriteExpr(fpInvocation.expr); + rewriteInvocationExpr(fpInvocation); + } + + @Override + public void visit(BLangTypedescExpr accessExpr) { + result = accessExpr; + } + + @Override + public void visit(BLangRestArgsExpression bLangVarArgsExpression) { + result = rewriteExpr(bLangVarArgsExpression.expr); + } + + @Override + public void visit(BLangNamedArgsExpression bLangNamedArgsExpression) { + bLangNamedArgsExpression.expr = rewriteExpr(bLangNamedArgsExpression.expr); + result = bLangNamedArgsExpression; + } + + @Override + public void visit(BLangCheckedExpr checkedExpr) { + result = checkedExpr; + } + + @Override + public void visit(BLangServiceConstructorExpr serviceConstructorExpr) { + result = serviceConstructorExpr; + } + + @Override + public void visit(BLangTypeTestExpr typeTestExpr) { + typeTestExpr.expr = rewriteExpr(typeTestExpr.expr); + result = typeTestExpr; + } + + @Override + public void visit(BLangIsLikeExpr isLikeExpr) { + isLikeExpr.expr = rewriteExpr(isLikeExpr.expr); + result = isLikeExpr; + } + + public void visit(BLangFieldBasedAccess.BLangNSPrefixedFieldBasedAccess nsPrefixedFieldBasedAccess) { + result = nsPrefixedFieldBasedAccess; + } + + @Override + public void visit(BLangLetExpression letExpression) { + for (BLangLetVariable letVariable : letExpression.letVarDeclarations) { + rewrite((BLangNode) letVariable.definitionNode, env); + } + letExpression.expr = rewriteExpr(letExpression.expr); + result = letExpression; + } + + @Override + public void visit(BLangAnnotAccessExpr annotAccessExpr) { + annotAccessExpr.expr = rewriteExpr(annotAccessExpr.expr); + result = annotAccessExpr; + } + + @Override + public void visit(BLangStatementExpression bLangStatementExpression) { + if (bLangStatementExpression.stmt.getKind() == NodeKind.BLOCK) { + BLangBlockStmt bLangBlockStmt = (BLangBlockStmt) bLangStatementExpression.stmt; + for (int i = 0; i < bLangBlockStmt.stmts.size(); i++) { + BLangStatement stmt = bLangBlockStmt.stmts.remove(i); + bLangBlockStmt.stmts.add(i, rewrite(stmt, env)); + } + } else { + bLangStatementExpression.stmt = rewrite(bLangStatementExpression.stmt, env); + } + bLangStatementExpression.expr = rewriteExpr(bLangStatementExpression.expr); + result = bLangStatementExpression; + } + + @Override + public void visit(BLangInvocation.BLangActionInvocation invocation) { + rewriteInvocationExpr(invocation); + } + + @Override + public void visit(BLangIdentifier identifierNode) { + /* ignore */ + } + + @Override + public void visit(BLangAnnotation annotationNode) { + /* ignore */ + } + + @Override + public void visit(BLangAnnotationAttachment annAttachmentNode) { + /* ignore */ + } + + @Override + public void visit(BLangConstant constant) { + result = constant; + } + + @Override + public void visit(BLangNumericLiteral literalExpr) { + result = literalExpr; + } + + @Override + public void visit(BLangTupleVarRef varRefExpr) { + result = varRefExpr; + } + + @Override + public void visit(BLangRecordVarRef varRefExpr) { + result = varRefExpr; + } + + @Override + public void visit(BLangErrorVarRef varRefExpr) { + result = varRefExpr; + } + + @Override + public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { + result = typeLoad; + } + + @Override + public void visit(BLangRecordLiteral.BLangChannelLiteral channelLiteral) { + channelLiteral.fields.forEach(field -> { + BLangRecordLiteral.BLangRecordKeyValueField keyValue = (BLangRecordLiteral.BLangRecordKeyValueField) field; + keyValue.key.expr = rewriteExpr(keyValue.key.expr); + keyValue.valueExpr = rewriteExpr(keyValue.valueExpr); + }); + result = channelLiteral; + } + + @Override + public void visit(BLangXMLNS.BLangLocalXMLNS xmlnsNode) { + xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); + result = xmlnsNode; + } + + @Override + public void visit(BLangXMLNS.BLangPackageXMLNS xmlnsNode) { + xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); + result = xmlnsNode; + } + + @Override + public void visit(BLangListConstructorExpr.BLangListConstructorSpreadOpExpr listConstructorSpreadOpExpr) { + listConstructorSpreadOpExpr.expr = rewriteExpr(listConstructorSpreadOpExpr.expr); + result = listConstructorSpreadOpExpr; + } + + @Override + public void visit(BLangQueryExpr queryExpr) { + result = queryExpr; + } + + @Override + public void visit(BLangMatchStatement matchStatement) { + result = matchStatement; + } + + @Override + public void visit(BLangXMLSequenceLiteral xmlSequenceLiteral) { + xmlSequenceLiteral.xmlItems.forEach(this::rewriteExpr); + result = xmlSequenceLiteral; + } + + @Override + public void visit(BLangMarkdownDocumentationLine bLangMarkdownDocumentationLine) { + /* Ignore */ + } + + @Override + public void visit(BLangMarkdownParameterDocumentation bLangDocumentationParameter) { + /* Ignore */ + } + + @Override + public void visit(BLangMarkdownReturnParameterDocumentation bLangMarkdownReturnParameterDocumentation) { + /* Ignore */ + } + + @Override + public void visit(BLangInferredTypedescDefaultNode inferTypedescExpr) { + result = inferTypedescExpr; + } + @Override + public void visit(BLangMarkdownDocumentation bLangMarkdownDocumentation) { + /* Ignore */ + } + + // Rewrite methods + + @SuppressWarnings("unchecked") + private E rewrite(E node, SymbolEnv env) { + if (node == null) { + return null; + } + + SymbolEnv previousEnv = this.env; + this.env = env; + + node.accept(this); + BLangNode resultNode = this.result; + this.result = null; + + this.env = previousEnv; + return (E) resultNode; + } + + public List rewrite(List nodeList, SymbolEnv env) { + for (int i = 0; i < nodeList.size(); i++) { + nodeList.set(i, rewrite(nodeList.get(i), env)); + } + return nodeList; + } + + @SuppressWarnings("unchecked") + public E rewriteExpr(E node) { + if (node == null) { + return null; + } + + node.accept(this); + BLangNode resultNode = this.result; + this.result = null; + return (E) resultNode; + } + + @SuppressWarnings("unchecked") + private List rewriteStmt(List nodeList, SymbolEnv env) { + Queue previousQueue = this.queue; + this.queue = new LinkedList<>(); + int size = nodeList.size(); + for (int i = 0; i < size; i++) { + E node = rewrite(nodeList.remove(0), env); + Iterator iterator = queue.iterator(); + while (iterator.hasNext()) { + nodeList.add(rewrite((E) queue.poll(), env)); + } + nodeList.add(node); + } + this.queue = previousQueue; + return nodeList; + } + + @SuppressWarnings("unchecked") + private List rewriteExprs(List nodeList) { + for (int i = 0; i < nodeList.size(); i++) { + rewriteExpr(nodeList.get(i)); + nodeList.set(i, rewriteExpr(nodeList.get(i))); + } + return nodeList; + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java index d0fb8ff8841a..1dd92b1314e7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java @@ -31,6 +31,7 @@ */ public class BRecordTypeSymbol extends BStructureTypeSymbol { + public BVarSymbol annotations; public BRecordTypeSymbol(int symTag, long flags, Name name, PackageID pkgID, BType type, BSymbol owner, Location pos, SymbolOrigin origin) { super(SymbolKind.RECORD, symTag, flags, name, pkgID, type, owner, pos, origin); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java index 3dba6a61f305..214849fafd0f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java @@ -80,6 +80,8 @@ public class BLangPackage extends BLangNode implements PackageNode { public Set completedPhases; // Queue to maintain lambda functions so that we can visit all lambdas at the end of the semantic phase public Queue lambdaFunctions = new ArrayDeque<>(); + // List to maintain lambda functions of annotations + public List anonFunctions; // Hold global variable dependencies identified in DataflowAnalyzer. public Map> globalVariableDependencies; @@ -101,6 +103,7 @@ public BLangPackage() { this.globalVars = new ArrayList<>(); this.services = new ArrayList<>(); this.functions = new ArrayList<>(); + this.anonFunctions = new ArrayList<>(); this.typeDefinitions = new ArrayList<>(); this.annotations = new ArrayList<>(); this.classDefinitions = new ArrayList<>(); From 9dd1884c5f4e00930d684d2292fa40ff8898d701 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 01:42:46 +0530 Subject: [PATCH 02/43] Introduce details of annotations to typedesc instruction --- .../ballerinalang/compiler/bir/BIRGen.java | 30 ++++++++++++------- .../compiler/bir/model/BIRNonTerminator.java | 5 +++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index a0552c05481a..f9d3ebd99a3c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -31,6 +31,7 @@ import org.ballerinalang.model.tree.OperatorKind; import org.ballerinalang.model.tree.TopLevelNode; import org.ballerinalang.model.tree.expressions.RecordLiteralNode; +import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRAnnotation; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRAnnotationAttachment; @@ -68,6 +69,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BObjectTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BResourceFunction; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BServiceSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; @@ -1549,7 +1551,7 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { - visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); + visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList(), null); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1580,7 +1582,16 @@ public void visit(BLangTypeConversionExpr astTypeConversionExpr) { @Override public void visit(BLangStructLiteral astStructLiteralExpr) { List varDcls = mapToVarDcls(astStructLiteralExpr.enclMapSymbols); - visitTypedesc(astStructLiteralExpr.pos, astStructLiteralExpr.getBType(), varDcls); + BIROperand anonMap = null; + if (astStructLiteralExpr.getBType().getKind() == TypeKind.RECORD) { + BRecordTypeSymbol typeSymbol = (BRecordTypeSymbol) astStructLiteralExpr.getBType().tsymbol; + if (typeSymbol.annotations != null) { + BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + anonMap = new BIROperand(varDcl); + } + } + visitTypedesc(astStructLiteralExpr.pos, astStructLiteralExpr.getBType(), varDcls, anonMap); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(astStructLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1940,7 +1951,7 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { - visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); + visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList(), null); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId(names)); addToTrapStack(thenBB); BIRVariableDcl tempVarDcl = new BIRVariableDcl(waitLiteral.getBType(), @@ -2168,7 +2179,7 @@ public void visit(BLangTypedescExpr accessExpr) { this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(accessExpr.pos, toVarRef, accessExpr.resolvedType, - Collections.emptyList())); + Collections.emptyList(), null)); this.env.targetOperand = toVarRef; } @@ -2217,16 +2228,15 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { BType type = typeLoad.symbol.tag == SymTag.TYPE_DEF ? ((BTypeDefinitionSymbol) typeLoad.symbol).referenceType : typeLoad.symbol.type; - visitTypedesc(typeLoad.pos, type, Collections.emptyList()); + visitTypedesc(typeLoad.pos, type, Collections.emptyList(), null); } - private void visitTypedesc(Location pos, BType type, List varDcls) { - BIRVariableDcl tempVarDcl = - new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind - .TEMP); + private void visitTypedesc(Location pos, BType type, List varDcls, BIROperand annotations) { + BIRVariableDcl tempVarDcl = new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); - setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls)); + setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls, annotations)); this.env.targetOperand = toVarRef; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java index 977a02bfd87e..218a1b0ecb4f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java @@ -808,12 +808,15 @@ public BIROperand[] getRhsOperands() { public static class NewTypeDesc extends BIRNonTerminator { public final List closureVars; public BType type; + public final BIROperand annotations; - public NewTypeDesc(Location pos, BIROperand lhsOp, BType type, List closureVars) { + public NewTypeDesc(Location pos, BIROperand lhsOp, BType type, List closureVars, + BIROperand annotations) { super(pos, InstructionKind.NEW_TYPEDESC); this.closureVars = closureVars; this.lhsOp = lhsOp; this.type = type; + this.annotations = annotations; } @Override From d1e1e7cdc1926f77b3258ab8d38be2bcb67cc307 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 01:45:55 +0530 Subject: [PATCH 03/43] Instantiate annotations using typedesc --- .../compiler/bir/codegen/JvmConstants.java | 1 + .../bir/codegen/JvmInstructionGen.java | 14 +++++--- .../compiler/bir/codegen/JvmSignatures.java | 2 ++ .../compiler/bir/codegen/JvmValueGen.java | 34 +++++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java index 7eeaa922f298..00b6af310e5b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java @@ -256,6 +256,7 @@ public class JvmConstants { // service objects, annotation processing related classes public static final String ANNOTATION_UTILS = "io/ballerina/runtime/internal/AnnotationUtils"; public static final String ANNOTATION_MAP_NAME = "$annotation_data"; + public static final String ANNOTATIONS_FIELD = "annotations"; public static final String DEFAULTABLE_ARGS_ANOT_NAME = "DefaultableArgs"; public static final String DEFAULTABLE_ARGS_ANOT_FIELD = "args"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java index e087d195e067..3397141dd2cc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java @@ -237,6 +237,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SET_ON_INIT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TWO_OBJECTS_ARGS; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.XML_ADD_CHILDREN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.XML_CHILDREN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.XML_CHILDREN_FROM_STRING; @@ -2105,7 +2106,7 @@ void generateNewTypedescIns(BIRNonTerminator.NewTypeDesc newTypeDesc) { String fieldName = jvmTypeGen.getTypedescFieldName(toNameString(type)); mv.visitFieldInsn(GETSTATIC, typeOwner, fieldName, GET_TYPEDESC); } else { - generateNewTypedescCreate(newTypeDesc.type, closureVars); + generateNewTypedescCreate(newTypeDesc.type, closureVars, newTypeDesc.annotations); } this.storeToVar(newTypeDesc.lhsOp.variableDcl); } @@ -2119,7 +2120,7 @@ private boolean isNonReferredRecord(BType type) { type.getQualifiedTypeName().equals(referredType.getQualifiedTypeName()); } - private void generateNewTypedescCreate(BType btype, List closureVars) { + private void generateNewTypedescCreate(BType btype, List closureVars, BIROperand annotation) { BType type = JvmCodeGenUtil.getReferredType(btype); String className = TYPEDESC_VALUE_IMPL; if (type.tag == TypeTags.RECORD) { @@ -2138,8 +2139,13 @@ private void generateNewTypedescCreate(BType btype, List closureVars this.loadVar(closureVar.variableDcl); mv.visitInsn(AASTORE); } - - this.mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR, false); + if (annotation != null) { + this.loadVar(annotation.variableDcl); + this.mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS, + false); + } else { + this.mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR, false); + } } void loadVar(BIRNode.BIRVariableDcl varDcl) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmSignatures.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmSignatures.java index 29516284123c..030b0c030d97 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmSignatures.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmSignatures.java @@ -443,6 +443,8 @@ public class JvmSignatures { public static final String TUPLE_SET_MEMBERS_METHOD = "(L" + LIST + ";L" + TYPE + ";)V"; public static final String TWO_OBJECTS_ARGS = "(L" + OBJECT + ";L" + OBJECT + ";)V"; public static final String TYPE_DESC_CONSTRUCTOR = "(L" + TYPE + ";[L" + MAP_VALUE + ";)V"; + public static final String TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS = + "(L" + TYPE + ";[L" + MAP_VALUE + ";L" + MAP_VALUE + ";)V"; public static final String TYPE_PARAMETER = "(L" + TYPE + ";)V"; public static final String UPDATE_CHANNEL_DETAILS = "([L" + CHANNEL_DETAILS + ";)V"; public static final String VALUE_CLASS_INIT = "(L" + STRAND_CLASS + ";L" + MAP_VALUE + ";)L" + OBJECT + ";"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java index 4397ec044db4..0d5ca08757a8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java @@ -86,6 +86,7 @@ import static org.objectweb.asm.Opcodes.V1_8; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmCodeGenUtil.toNameString; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.ABSTRACT_OBJECT_VALUE; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.ANNOTATIONS_FIELD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.BAL_OPTIONAL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.B_OBJECT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.JVM_INIT_METHOD; @@ -108,6 +109,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmPackageGen.computeLockNameFromString; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.CAST_B_MAPPING_INITIAL_VALUE_ENTRY; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_MAP_ARRAY; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.GET_MAP_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_TYPEDESC; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INSTANTIATE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.OBJECT_TYPE_IMPL_INIT; @@ -115,6 +117,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RECORD_INIT_WRAPPER; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RECORD_VALUE_CLASS; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.TYPE_PARAMETER; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.VALUE_CLASS_INIT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmTypeGen.getTypeDesc; @@ -245,7 +248,11 @@ private byte[] createRecordTypeDescClass(BRecordType recordType, String classNam } cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, className, null, TYPEDESC_VALUE_IMPL, new String[]{TYPEDESC_VALUE}); + FieldVisitor fv = cw.visitField(0, ANNOTATIONS_FIELD, GET_MAP_VALUE, null, null); + fv.visitEnd(); + this.createTypeDescConstructor(cw); + this.createNewTypeDescConstructor(cw, className); this.createInstantiateMethod(cw, recordType, typeDef); cw.visitEnd(); @@ -425,6 +432,33 @@ private void createTypeDescConstructor(ClassWriter cw) { mv.visitEnd(); } + private void createNewTypeDescConstructor(ClassWriter cw, String name) { + + String descriptor = TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS; + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, JVM_INIT_METHOD, descriptor, null, null); + mv.visitCode(); + + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 3); + mv.visitFieldInsn(PUTFIELD, name, ANNOTATIONS_FIELD, GET_MAP_VALUE); + + // load super + mv.visitVarInsn(ALOAD, 0); + // load type + mv.visitVarInsn(ALOAD, 1); + // load closures + mv.visitVarInsn(ALOAD, 2); + // load annotations + mv.visitVarInsn(ALOAD, 3); + // invoke `super(type)`; + mv.visitMethodInsn(INVOKESPECIAL, TYPEDESC_VALUE_IMPL, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS, + false); + + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + private void createRecordConstructor(ClassWriter cw, String argumentClass) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, JVM_INIT_METHOD, argumentClass, null, null); mv.visitCode(); From 1f2b606a4b2ff6d57b5689982d925fc3a8b828ee Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 01:52:36 +0530 Subject: [PATCH 04/43] Add support to access annotations using annotation map in typedesc --- .../io/ballerina/runtime/api/values/BTypedesc.java | 8 ++++++++ .../io/ballerina/runtime/internal/TypeChecker.java | 14 ++++++++++++++ .../runtime/internal/values/TypedescValueImpl.java | 13 +++++++++++++ 3 files changed, 35 insertions(+) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java index 99885b06312c..61cf15533c80 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java @@ -19,6 +19,7 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.internal.scheduling.Strand; +import io.ballerina.runtime.internal.values.MapValue; /** *

@@ -46,6 +47,13 @@ public interface BTypedesc extends BValue { */ Object instantiate(Strand strand); + /** + * Returns the annotations of the value describe by this type descriptor. + * + * @return annotations + */ + MapValue getAnnotations(); + /** * @param strand strand to be used to run the user-defined-type initialization code. * @param initialValues the initial values provided in the constructor expression diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java index c9fbabf5b9ef..bcc2226f037a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java @@ -584,6 +584,13 @@ public static TypedescValue getTypedesc(Object value) { * @return the annotation value if present, nil else */ public static Object getAnnotValue(TypedescValue typedescValue, String annotTag) { + MapValue annotMap = typedescValue.getAnnotations(); + if (annotMap != null) { + Object annotation = annotMap.get(annotTag); + if (annotation != null) { + return annotation; + } + } Type describingType = typedescValue.getDescribingType(); if (!(describingType instanceof BAnnotatableType)) { return null; @@ -592,6 +599,13 @@ public static Object getAnnotValue(TypedescValue typedescValue, String annotTag) } public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag) { + MapValue annotMap = typedescValue.getAnnotations(); + if (annotMap != null) { + Object annotation = annotMap.get(annotTag); + if (annotation != null) { + return annotation; + } + } Type describingType = typedescValue.getDescribingType(); if (!(describingType instanceof BAnnotatableType)) { return null; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 6c5aafb82583..f38ebcbc7694 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -51,6 +51,7 @@ public class TypedescValueImpl implements TypedescValue { final Type type; final Type describingType; // Type of the value describe by this typedesc. public MapValue[] closures; + public MapValue annotations; @Deprecated public TypedescValueImpl(Type describingType) { @@ -65,6 +66,14 @@ public TypedescValueImpl(Type describingType, MapValue[] closures) { this.closures = closures; } + @Deprecated + public TypedescValueImpl(Type describingType, MapValue[] closures, MapValue annotations) { + this.type = new BTypedescType(describingType); + this.describingType = describingType; + this.closures = closures; + this.annotations = annotations; + } + /** * Returns the {@code BType} of the value describe by this type descriptor. @@ -83,6 +92,10 @@ public Object instantiate(Strand s) { return instantiate(s, new BInitialValueEntry[0]); } + public MapValue getAnnotations() { + return annotations; + } + @Override public Object instantiate(Strand s, BInitialValueEntry[] initialValues) { Type referredType = getReferredType(this.describingType); From 8069fe1d446eee8c5bdeb7ba16d51403843eef98 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 01:55:04 +0530 Subject: [PATCH 05/43] Add tests for local record annotations --- .../GetLocalRecordAnnotations.java | 33 ++++ .../LocalRecordAnnotationTest.java | 44 +++++ .../local_record_annotation_test.bal | 182 ++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java new file mode 100644 index 000000000000..6564337fe000 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you 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. + */ +package org.ballerinalang.test.annotations; + +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.api.values.BValue; +import io.ballerina.runtime.internal.TypeChecker; +import io.ballerina.runtime.internal.values.TypedescValue; + +/** + * Class to get annotation of local record types. + * + * @since 2201.0.4 + */ +public class GetLocalRecordAnnotations { + public static BValue getLocalRecordAnnotations(TypedescValue typedescValue, BString annotName) { + return (BValue) TypeChecker.getAnnotValue(typedescValue, annotName); + } +} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java new file mode 100644 index 000000000000..39a3891752c1 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you 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. + */ +package org.ballerinalang.test.annotations; + +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * Class to test annotation evaluation within local record types. + * + * @since 2201.0.4 + */ +public class LocalRecordAnnotationTest { + private CompileResult result; + + @BeforeClass + public void setup() { + result = BCompileUtil.compile("test-src/annotations/local_record_annotation_test.bal"); + Assert.assertEquals(result.getErrorCount(), 0); + } + + @Test + public void testLocalServiceAnnotEvaluation() { + BRunUtil.invoke(result, "testLocalRecordAnnotations"); + } +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal new file mode 100644 index 000000000000..5b9c1ca845b4 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal @@ -0,0 +1,182 @@ +// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you 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. + +import ballerina/jballerina.java; + +type AnnotRecord record {| + string value; +|}; + +type Details record {| + string name; + int age; +|}; + + +annotation AnnotRecord annot on type, field; +annotation AnnotRecord annot1 on type, field; +annotation Details details on field; + +function testAnnotationOnLocalRecord() { + string k = "chiranS"; + record {@annot {value: k} string x;} r = {x : ""}; + + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); +} + +function testAnnotationWithMultipleFieldsOnLocalRecord() { + string k = "chiranS"; + record {@details {name: k, age: 26} string x;} r = {x : ""}; + + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"details\":{\"name\":\"chiranS\",\"age\":26}}", m.toString()); +} + +function testAnnotationOnLocalRecordWithMultipleFields() { + string k = "chiranS"; + record {@annot {value: k} string x; @annot {value: k} string y; } r = {x : "", y: ""}; + + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + + any y = getLocalRecordAnnotations(typeof r, "$field$.y"); + assertEquality("typedesc map", (typeof y).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", y.toString()); +} + + +string gVar = "foo"; +function testAnnotationOnLocalRecordWithGlobalVariable() { + record {@annot {value: gVar} string x;} r = {x : ""}; + + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"foo\"}}", m.toString()); +} + +function testAnnotationOnLocalRecordWithinLambdaFunction() { + string k = "chiranS"; + function() func = function () { + record {@annot {value: k} string x;} r = {x : ""}; + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + }; + func(); +} + +function testAnnotationOnLocalRecordWithinLambdaFunction1() { + string k = "chiranS"; + function(string) func = function (string value) { + record {@annot {value: value} string x;} r = {x : ""}; + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + }; + func(k); +} + +function testAnnotationOnLocalRecordWithinNestedLambdaFunctions() { + string k = "chiranS"; + function () returns function() var1 = function () returns function() { + function() func = function () { + record {@annot {value: k} string x;} r = {x : ""}; + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + }; + return func; + }; + function() func = var1(); + func(); +} + +function testAnnotationOnLocalRecordWithinNestedLambdaFunctions1() { + string k = "chiranS"; + function (string) returns function() var1 = function (string val) returns function() { + function() func = function () { + record {@annot {value: val} string x;} r = {x : ""}; + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + }; + return func; + }; + function() func = var1(k); + func(); +} + +function testAnnotationOnLocalRecordWithinNestedLambdaFunctions2() { + string k = "chiranS"; + function (string) returns function() var1 = function (string val) returns function() { + string name = "Name: "; + function() func = function () { + record {@annot {value: name + val} string x;} r = {x : ""}; + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); + assertEquality("{\"annot\":{\"value\":\"Name: chiranS\"}}", m.toString()); + }; + return func; + }; + function() func = var1(k); + func(); +} + +function testMultipleAnnotationsOnLocaRecord() { + string k = "chiran"; + record {@annot {value: k} @annot1 {value: k} string x;} r = {x : ""}; + + any m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality("typedesc map", (typeof m).toString()); +} + +function testLocalRecordAnnotations() { + testMultipleAnnotationsOnLocaRecord(); + testAnnotationOnLocalRecord(); + testAnnotationOnLocalRecordWithGlobalVariable(); + testAnnotationOnLocalRecordWithinLambdaFunction(); + testAnnotationOnLocalRecordWithinLambdaFunction1(); + testAnnotationOnLocalRecordWithinNestedLambdaFunctions(); + testAnnotationOnLocalRecordWithinNestedLambdaFunctions1(); + testAnnotationOnLocalRecordWithinNestedLambdaFunctions2(); + testAnnotationWithMultipleFieldsOnLocalRecord(); + testAnnotationOnLocalRecordWithMultipleFields(); +} + +function getLocalRecordAnnotations(typedesc obj, string annotName) returns any = +@java:Method { + 'class: "org/ballerinalang/test/annotations/GetLocalRecordAnnotations", + name: "getLocalRecordAnnotations" +} external; + +function assertEquality(any|error expected, any|error actual) { + if expected is anydata && actual is anydata && expected == actual { + return; + } + + if expected === actual { + return; + } + + string expectedValAsString = expected is error ? expected.toString() : expected.toString(); + string actualValAsString = actual is error ? actual.toString() : actual.toString(); + panic error("AssertionError", + message = "expected '" + expectedValAsString + "', found '" + actualValAsString + "'"); +} From 56968193c6f3cd1913ad3acd2ce41566c313b75c Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 1 Nov 2022 09:03:06 +0530 Subject: [PATCH 06/43] Update version --- .../ballerinalang/compiler/desugar/LocalAnnotationDesugar.java | 2 +- .../test/annotations/GetLocalRecordAnnotations.java | 2 +- .../test/annotations/LocalRecordAnnotationTest.java | 2 +- .../test-src/annotations/local_record_annotation_test.bal | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java index c6f312d2fc24..4e7aa6abac35 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java @@ -165,7 +165,7 @@ /** * Local annotation desugar for create closures for annotations. * - * @since 2.0.0 + * @since 2201.4.0 */ public class LocalAnnotationDesugar extends BLangNodeVisitor { private static final CompilerContext.Key LOCAL_ANNOTATION_DESUGAR_KEY = diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java index 6564337fe000..5d3fa729470a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java @@ -24,7 +24,7 @@ /** * Class to get annotation of local record types. * - * @since 2201.0.4 + * @since 2201.4.0 */ public class GetLocalRecordAnnotations { public static BValue getLocalRecordAnnotations(TypedescValue typedescValue, BString annotName) { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java index 39a3891752c1..aeae5f27ec32 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java @@ -26,7 +26,7 @@ /** * Class to test annotation evaluation within local record types. * - * @since 2201.0.4 + * @since 2201.4.0 */ public class LocalRecordAnnotationTest { private CompileResult result; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal index 5b9c1ca845b4..f8b29f88c1cb 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal @@ -25,7 +25,6 @@ type Details record {| int age; |}; - annotation AnnotRecord annot on type, field; annotation AnnotRecord annot1 on type, field; annotation Details details on field; From ebc4c182821564e618d7a3a9233b1aa933a0783f Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 14 Nov 2022 11:41:50 +0530 Subject: [PATCH 07/43] Move local annotation desugar logic to parameter desugar phase --- .../compiler/desugar/AnnotationDesugar.java | 8 +- .../compiler/desugar/Desugar.java | 12 +- .../desugar/LocalAnnotationDesugar.java | 1463 ----------------- .../compiler/desugar/ParameterDesugar.java | 68 +- .../compiler/tree/BLangPackage.java | 3 - 5 files changed, 74 insertions(+), 1480 deletions(-) delete mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 7e62b08f2803..7d61a4f1b774 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -139,7 +139,7 @@ public class AnnotationDesugar { private final Names names; private SymbolResolver symResolver; private ConstantValueResolver constantValueResolver; - private LocalAnnotationDesugar localAnnotationDesugar; + private ParameterDesugar parameterDesugar; public static AnnotationDesugar getInstance(CompilerContext context) { AnnotationDesugar annotationDesugar = context.get(ANNOTATION_DESUGAR_KEY); @@ -157,7 +157,7 @@ private AnnotationDesugar(CompilerContext context) { this.names = Names.getInstance(context); this.symResolver = SymbolResolver.getInstance(context); this.constantValueResolver = ConstantValueResolver.getInstance(context); - this.localAnnotationDesugar = LocalAnnotationDesugar.getInstance(context); + this.parameterDesugar = ParameterDesugar.getInstance(context); } /** @@ -648,7 +648,7 @@ public BLangLambdaFunction defineAnnotationsForLocalRecords(BLangRecordTypeNode pkgID, owner, false); if (fieldAnnotLambda != null) { BInvokableSymbol invokableSymbol = - localAnnotationDesugar.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); + parameterDesugar.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); env.scope.define(invokableSymbol.name, invokableSymbol); if (!annotFunctionDefined) { function = defineFunction(recordTypeNode.pos, pkgID, owner); @@ -852,7 +852,7 @@ private BLangLambdaFunction addReturnAndDefineLambda(BLangFunction function, BLa pkgNode.functions.add(function); pkgNode.topLevelNodes.add(function); - pkgNode.anonFunctions.add(lambdaFunction); + pkgNode.lambdaFunctions.add(lambdaFunction); return lambdaFunction; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index 502cd351b9a2..af12a8474f00 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -374,7 +374,6 @@ public class Desugar extends BLangNodeVisitor { private final SymbolEnter symbolEnter; private ClosureDesugar closureDesugar; private ParameterDesugar parameterDesugar; - private LocalAnnotationDesugar localAnnotationDesugar; private QueryDesugar queryDesugar; private TransactionDesugar transactionDesugar; private ObservabilityDesugar observabilityDesugar; @@ -448,7 +447,6 @@ private Desugar(CompilerContext context) { this.symbolEnter = SymbolEnter.getInstance(context); this.closureDesugar = ClosureDesugar.getInstance(context); this.parameterDesugar = ParameterDesugar.getInstance(context); - this.localAnnotationDesugar = LocalAnnotationDesugar.getInstance(context); this.queryDesugar = QueryDesugar.getInstance(context); this.transactionDesugar = TransactionDesugar.getInstance(context); this.observabilityDesugar = ObservabilityDesugar.getInstance(context); @@ -776,7 +774,6 @@ public void visit(BLangPackage pkgNode) { // create closures for default values parameterDesugar.visit(pkgNode); - localAnnotationDesugar.visit(pkgNode); // Initialize the annotation map annotationDesugar.initializeAnnotationMap(pkgNode); @@ -826,11 +823,6 @@ public void visit(BLangPackage pkgNode) { pkgNode.startFunction = rewrite(pkgNode.startFunction, env); pkgNode.stopFunction = rewrite(pkgNode.stopFunction, env); - for (int i = 0; i < pkgNode.anonFunctions.size(); i++) { - BLangLambdaFunction function = pkgNode.anonFunctions.get(i); - pkgNode.anonFunctions.set(i, rewrite(function, function.capturedClosureEnv)); - } - for (int i = 0; i < pkgNode.functions.size(); i++) { BLangFunction function = pkgNode.functions.get(i); if (!function.flagSet.contains(Flag.LAMBDA) || function.name.value.contains(MockDesugar.MOCK_FUNCTION)) { @@ -838,6 +830,10 @@ public void visit(BLangPackage pkgNode) { } } + for (BLangLambdaFunction lambdaFunction : pkgNode.lambdaFunctions) { + rewrite(lambdaFunction, lambdaFunction.capturedClosureEnv); + } + // Invoke closure desugar. closureDesugar.visit(pkgNode); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java deleted file mode 100644 index 4e7aa6abac35..000000000000 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/LocalAnnotationDesugar.java +++ /dev/null @@ -1,1463 +0,0 @@ -package org.wso2.ballerinalang.compiler.desugar; - -import org.ballerinalang.model.TreeBuilder; -import org.ballerinalang.model.elements.Flag; -import org.ballerinalang.model.elements.PackageID; -import org.ballerinalang.model.tree.NodeKind; -import org.ballerinalang.model.tree.expressions.RecordLiteralNode; -import org.wso2.ballerinalang.compiler.semantics.analyzer.SymbolResolver; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; -import org.wso2.ballerinalang.compiler.tree.BLangAnnotation; -import org.wso2.ballerinalang.compiler.tree.BLangAnnotationAttachment; -import org.wso2.ballerinalang.compiler.tree.BLangBlockFunctionBody; -import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; -import org.wso2.ballerinalang.compiler.tree.BLangErrorVariable; -import org.wso2.ballerinalang.compiler.tree.BLangExprFunctionBody; -import org.wso2.ballerinalang.compiler.tree.BLangExternalFunctionBody; -import org.wso2.ballerinalang.compiler.tree.BLangFunction; -import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; -import org.wso2.ballerinalang.compiler.tree.BLangInvokableNode; -import org.wso2.ballerinalang.compiler.tree.BLangMarkdownDocumentation; -import org.wso2.ballerinalang.compiler.tree.BLangNode; -import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; -import org.wso2.ballerinalang.compiler.tree.BLangPackage; -import org.wso2.ballerinalang.compiler.tree.BLangRecordVariable; -import org.wso2.ballerinalang.compiler.tree.BLangResourceFunction; -import org.wso2.ballerinalang.compiler.tree.BLangService; -import org.wso2.ballerinalang.compiler.tree.BLangSimpleVariable; -import org.wso2.ballerinalang.compiler.tree.BLangTableKeyTypeConstraint; -import org.wso2.ballerinalang.compiler.tree.BLangTupleVariable; -import org.wso2.ballerinalang.compiler.tree.BLangTypeDefinition; -import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangAnnotAccessExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangDynamicArgExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorConstructorExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorVarRef; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangFieldBasedAccess; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangGroupExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangIgnoreExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangIndexBasedAccess; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangInferredTypedescDefaultNode; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangIsAssignableExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangIsLikeExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLetExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownDocumentationLine; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangRawTemplateLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordVarRef; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangRegExpTemplateLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangRestArgsExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangServiceConstructorExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangStatementExpression; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangStringTemplateLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTableConstructorExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTernaryExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTransactionalExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTrapExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTupleVarRef; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeConversionExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeInit; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeTestExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypedescExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangUnaryExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangWaitExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangWaitForAllExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLCommentLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLElementAccess; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLElementLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLNavigationAccess; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLProcInsLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQName; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLQuotedString; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLSequenceLiteral; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLTextLiteral; -import org.wso2.ballerinalang.compiler.tree.statements.BLangAssignment; -import org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt; -import org.wso2.ballerinalang.compiler.tree.statements.BLangBreak; -import org.wso2.ballerinalang.compiler.tree.statements.BLangCompoundAssignment; -import org.wso2.ballerinalang.compiler.tree.statements.BLangContinue; -import org.wso2.ballerinalang.compiler.tree.statements.BLangDo; -import org.wso2.ballerinalang.compiler.tree.statements.BLangErrorDestructure; -import org.wso2.ballerinalang.compiler.tree.statements.BLangErrorVariableDef; -import org.wso2.ballerinalang.compiler.tree.statements.BLangExpressionStmt; -import org.wso2.ballerinalang.compiler.tree.statements.BLangFail; -import org.wso2.ballerinalang.compiler.tree.statements.BLangForeach; -import org.wso2.ballerinalang.compiler.tree.statements.BLangForkJoin; -import org.wso2.ballerinalang.compiler.tree.statements.BLangIf; -import org.wso2.ballerinalang.compiler.tree.statements.BLangLock; -import org.wso2.ballerinalang.compiler.tree.statements.BLangMatchStatement; -import org.wso2.ballerinalang.compiler.tree.statements.BLangPanic; -import org.wso2.ballerinalang.compiler.tree.statements.BLangRecordDestructure; -import org.wso2.ballerinalang.compiler.tree.statements.BLangRecordVariableDef; -import org.wso2.ballerinalang.compiler.tree.statements.BLangRetry; -import org.wso2.ballerinalang.compiler.tree.statements.BLangRetryTransaction; -import org.wso2.ballerinalang.compiler.tree.statements.BLangReturn; -import org.wso2.ballerinalang.compiler.tree.statements.BLangRollback; -import org.wso2.ballerinalang.compiler.tree.statements.BLangSimpleVariableDef; -import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; -import org.wso2.ballerinalang.compiler.tree.statements.BLangTransaction; -import org.wso2.ballerinalang.compiler.tree.statements.BLangTupleDestructure; -import org.wso2.ballerinalang.compiler.tree.statements.BLangTupleVariableDef; -import org.wso2.ballerinalang.compiler.tree.statements.BLangWhile; -import org.wso2.ballerinalang.compiler.tree.statements.BLangWorkerSend; -import org.wso2.ballerinalang.compiler.tree.statements.BLangXMLNSStatement; -import org.wso2.ballerinalang.compiler.tree.types.BLangArrayType; -import org.wso2.ballerinalang.compiler.tree.types.BLangBuiltInRefTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangConstrainedType; -import org.wso2.ballerinalang.compiler.tree.types.BLangErrorType; -import org.wso2.ballerinalang.compiler.tree.types.BLangFiniteTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangFunctionTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangIntersectionTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangLetVariable; -import org.wso2.ballerinalang.compiler.tree.types.BLangObjectTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangStreamType; -import org.wso2.ballerinalang.compiler.tree.types.BLangTableTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangTupleTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangType; -import org.wso2.ballerinalang.compiler.tree.types.BLangUnionTypeNode; -import org.wso2.ballerinalang.compiler.tree.types.BLangUserDefinedType; -import org.wso2.ballerinalang.compiler.tree.types.BLangValueType; -import org.wso2.ballerinalang.compiler.util.ClosureVarSymbol; -import org.wso2.ballerinalang.compiler.util.CompilerContext; -import org.wso2.ballerinalang.util.Flags; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -import static org.ballerinalang.model.symbols.SymbolOrigin.VIRTUAL; - -/** - * Local annotation desugar for create closures for annotations. - * - * @since 2201.4.0 - */ -public class LocalAnnotationDesugar extends BLangNodeVisitor { - private static final CompilerContext.Key LOCAL_ANNOTATION_DESUGAR_KEY = - new CompilerContext.Key<>(); - private Queue queue; - - private SymbolTable symTable; - private SymbolEnv env; - private BLangNode result; - private SymbolResolver symResolver; - private AnnotationDesugar annotationDesugar; - - public static LocalAnnotationDesugar getInstance(CompilerContext context) { - LocalAnnotationDesugar parameterDesugar = context.get(LOCAL_ANNOTATION_DESUGAR_KEY); - if (parameterDesugar == null) { - parameterDesugar = new LocalAnnotationDesugar(context); - } - - return parameterDesugar; - } - - private LocalAnnotationDesugar(CompilerContext context) { - context.put(LOCAL_ANNOTATION_DESUGAR_KEY, this); - this.symTable = SymbolTable.getInstance(context); - this.queue = new LinkedList<>(); - this.symResolver = SymbolResolver.getInstance(context); - this.annotationDesugar = AnnotationDesugar.getInstance(context); - } - - @Override - public void visit(BLangPackage pkgNode) { - SymbolEnv pkgEnv = this.symTable.pkgEnvMap.get(pkgNode.symbol); - - for (int i = 0; i < pkgNode.functions.size(); i++) { - BLangFunction bLangFunction = pkgNode.functions.get(i); - if (!bLangFunction.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(bLangFunction, bLangFunction.symbol.scope, pkgEnv); - rewriteParamsAndReturnTypeOfFunction(bLangFunction, funcEnv); - } - } - pkgNode.services.forEach(service -> rewrite(service, pkgEnv)); - pkgNode.typeDefinitions.forEach(typeDefinition -> rewrite(typeDefinition, pkgEnv)); - pkgNode.xmlnsList.forEach(xmlns -> rewrite(xmlns, pkgEnv)); - pkgNode.constants.forEach(constant -> rewrite(constant, pkgEnv)); - pkgNode.annotations.forEach(annotation -> rewrite(annotation, pkgEnv)); - pkgNode.initFunction = rewrite(pkgNode.initFunction, pkgEnv); - pkgNode.classDefinitions = rewrite(pkgNode.classDefinitions, pkgEnv); - pkgNode.globalVars.forEach(globalVar -> rewrite(globalVar, pkgEnv)); - addClosuresToGlobalVariableList(pkgEnv); - for (int i = 0; i < pkgNode.functions.size(); i++) { - BLangFunction bLangFunction = pkgNode.functions.get(i); - if (!bLangFunction.flagSet.contains(Flag.LAMBDA)) { - rewrite(bLangFunction, pkgEnv); - } - } - - result = pkgNode; - } - - private void addClosuresToGlobalVariableList(SymbolEnv pkgEnv) { - Iterator iterator = queue.iterator(); - while (iterator.hasNext()) { - BLangSimpleVariable simpleVariable = queue.poll().var; - simpleVariable.flagSet.add(Flag.PUBLIC); - simpleVariable.symbol.flags |= Flags.PUBLIC; - pkgEnv.enclPkg.globalVars.add(0, rewrite(simpleVariable, pkgEnv)); - } - } - - @Override - public void visit(BLangFunction funcNode) { - SymbolEnv funcEnv = SymbolEnv.createFunctionEnv(funcNode, funcNode.symbol.scope, env); - - if (funcNode.flagSet.contains(Flag.LAMBDA)) { - rewriteParamsAndReturnTypeOfFunction(funcNode, funcEnv); - } - funcNode.body = rewrite(funcNode.body, funcEnv); - result = funcNode; - } - - public void rewriteParamsAndReturnTypeOfFunction(BLangFunction funcNode, SymbolEnv funcEnv) { - for (BLangSimpleVariable bLangSimpleVariable : funcNode.requiredParams) { - rewrite(bLangSimpleVariable, funcEnv); - } - - if (funcNode.restParam != null) { - funcNode.restParam = rewrite(funcNode.restParam, funcEnv); - } - - if (funcNode.returnTypeNode != null && funcNode.returnTypeNode.getKind() != null) { - funcNode.returnTypeNode = rewrite(funcNode.returnTypeNode, funcEnv); - } - } - - @Override - public void visit(BLangBlockFunctionBody body) { - SymbolEnv blockEnv = SymbolEnv.createFuncBodyEnv(body, env); - body.stmts = rewriteStmt(body.stmts, blockEnv); - result = body; - } - - @Override - public void visit(BLangRawTemplateLiteral rawTemplateLiteral) { - result = rawTemplateLiteral; - } - - @Override - public void visit(BLangExprFunctionBody exprBody) { - exprBody.expr = rewriteExpr(exprBody.expr); - result = exprBody; - } - - @Override - public void visit(BLangResourceFunction resourceFunction) { - visit((BLangFunction) resourceFunction); - } - - @Override - public void visit(BLangExternalFunctionBody body) { - result = body; - } - - @Override - public void visit(BLangBlockStmt blockNode) { - SymbolEnv blockEnv = SymbolEnv.createBlockEnv(blockNode, env); - blockNode.stmts = rewriteStmt(blockNode.stmts, blockEnv); - - result = blockNode; - } - - @Override - public void visit(BLangService serviceNode) { - result = serviceNode; - } - - @Override - public void visit(BLangSimpleVariableDef varDefNode) { - varDefNode.var = rewrite(varDefNode.var, env); - result = varDefNode; - } - - @Override - public void visit(BLangReturn returnNode) { - if (returnNode.expr != null) { - returnNode.expr = rewriteExpr(returnNode.expr); - } - result = returnNode; - } - - @Override - public void visit(BLangTypeDefinition typeDef) { - typeDef.typeNode = rewrite(typeDef.typeNode, env); - result = typeDef; - } - - @Override - public void visit(BLangIntersectionTypeNode intersectionTypeNode) { - List rewrittenConstituents = new ArrayList<>(); - for (BLangType constituentTypeNode : intersectionTypeNode.constituentTypeNodes) { - rewrittenConstituents.add(rewrite(constituentTypeNode, env)); - } - intersectionTypeNode.constituentTypeNodes = rewrittenConstituents; - result = intersectionTypeNode; - } - - @Override - public void visit(BLangClassDefinition classDefinition) { - SymbolEnv classEnv = SymbolEnv.createClassEnv(classDefinition, classDefinition.symbol.scope, env); - for (BLangSimpleVariable bLangSimpleVariable : classDefinition.fields) { - bLangSimpleVariable.typeNode = rewrite(bLangSimpleVariable.typeNode, classEnv); - } - result = classDefinition; - } - - @Override - public void visit(BLangObjectTypeNode objectTypeNode) { - for (BLangSimpleVariable field : objectTypeNode.fields) { - rewrite(field, env); - } - result = objectTypeNode; - } - - @Override - public void visit(BLangObjectConstructorExpression objectConstructorExpression) { - objectConstructorExpression.typeInit = rewriteExpr(objectConstructorExpression.typeInit); - result = objectConstructorExpression; - } - - @Override - public void visit(BLangRecordTypeNode recordTypeNode) { - PackageID pkgID = recordTypeNode.symbol.pkgID; - BSymbol owner = recordTypeNode.symbol.owner; - - if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { - BLangLambdaFunction lambdaFunction = - annotationDesugar.defineAnnotationsForLocalRecords(recordTypeNode, env.enclPkg, env, pkgID, owner); - if (lambdaFunction != null) { - BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); - ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = - createSimpleVariable(invokableSymbol); - } - } - - for (BLangSimpleVariable field : recordTypeNode.fields) { - rewrite(field, env); - } - recordTypeNode.restFieldType = rewrite(recordTypeNode.restFieldType, env); - result = recordTypeNode; - } - - private BLangInvocation getInvocation(BInvokableSymbol symbol) { - BLangInvocation funcInvocation = (BLangInvocation) TreeBuilder.createInvocationNode(); - funcInvocation.setBType(symbol.retType); - funcInvocation.symbol = symbol; - funcInvocation.name = ASTBuilderUtil.createIdentifier(symbol.pos, symbol.name.value); - funcInvocation.functionPointerInvocation = true; - return funcInvocation; - } - - @Override - public void visit(BLangTupleTypeNode tupleTypeNode) { - List rewrittenMembers = new ArrayList<>(); - tupleTypeNode.memberTypeNodes.forEach(member -> rewrittenMembers.add(rewrite(member, env))); - tupleTypeNode.memberTypeNodes = rewrittenMembers; - tupleTypeNode.restParamType = rewrite(tupleTypeNode.restParamType, env); - result = tupleTypeNode; - } - - @Override - public void visit(BLangFiniteTypeNode finiteTypeNode) { - finiteTypeNode.valueSpace.forEach(param -> rewrite(param, env)); - result = finiteTypeNode; - } - - @Override - public void visit(BLangArrayType arrayType) { - arrayType.elemtype = rewrite(arrayType.elemtype, env); - result = arrayType; - } - - @Override - public void visit(BLangUserDefinedType userDefinedType) { - result = userDefinedType; - } - - @Override - public void visit(BLangUnionTypeNode unionTypeNode) { - List rewrittenMembers = new ArrayList<>(); - unionTypeNode.memberTypeNodes.forEach(typeNode -> rewrittenMembers.add(rewrite(typeNode, env))); - unionTypeNode.memberTypeNodes = rewrittenMembers; - result = unionTypeNode; - } - - @Override - public void visit(BLangValueType valueType) { - result = valueType; - } - - @Override - public void visit(BLangBuiltInRefTypeNode builtInRefTypeNode) { - result = builtInRefTypeNode; - } - - @Override - public void visit(BLangStreamType streamType) { - streamType.constraint = rewrite(streamType.constraint, env); - streamType.error = rewrite(streamType.error, env); - result = streamType; - } - - @Override - public void visit(BLangConstrainedType constrainedType) { - constrainedType.constraint = rewrite(constrainedType.constraint, env); - result = constrainedType; - } - - @Override - public void visit(BLangErrorType errorType) { - errorType.detailType = rewrite(errorType.detailType, env); - result = errorType; - } - - @Override - public void visit(BLangTableTypeNode tableTypeNode) { - tableTypeNode.constraint = rewrite(tableTypeNode.constraint, env); - tableTypeNode.tableKeyTypeConstraint = rewrite(tableTypeNode.tableKeyTypeConstraint, env); - result = tableTypeNode; - } - - @Override - public void visit(BLangInvocation.BLangResourceAccessInvocation resourceAccessInvocation) { - result = resourceAccessInvocation; - } - - @Override - public void visit(BLangTableKeyTypeConstraint keyTypeConstraint) { - keyTypeConstraint.keyType = rewrite(keyTypeConstraint.keyType, env); - result = keyTypeConstraint; - } - - @Override - public void visit(BLangFunctionTypeNode functionTypeNode) { - SymbolEnv funcEnv = SymbolEnv.createTypeEnv(functionTypeNode, functionTypeNode.getBType().tsymbol.scope, env); - for (BLangSimpleVariable param : functionTypeNode.params) { - rewrite(param, funcEnv); - } - if (functionTypeNode.restParam != null) { - functionTypeNode.restParam.typeNode = rewrite(functionTypeNode.restParam.typeNode, env); - } - if (functionTypeNode.returnTypeNode != null) { - functionTypeNode.returnTypeNode = rewrite(functionTypeNode.returnTypeNode, env); - } - - result = functionTypeNode; - } - - @Override - public void visit(BLangSimpleVariable varNode) { - if (varNode.typeNode != null && varNode.typeNode.getKind() != null) { - varNode.typeNode = rewrite(varNode.typeNode, env); - } - varNode.expr = rewriteExpr(varNode.expr); - result = varNode; - } - - private BSymbol getOwner(SymbolEnv symbolEnv) { - while (symbolEnv.node.getKind() != NodeKind.PACKAGE) { - NodeKind kind = symbolEnv.node.getKind(); - if (kind != NodeKind.BLOCK_FUNCTION_BODY && kind != NodeKind.BLOCK) { - symbolEnv = symbolEnv.enclEnv; - continue; - } - return symbolEnv.enclInvokable.symbol; - } - return symbolEnv.enclPkg.symbol; - } - - public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction) { - BInvokableSymbol invokableSymbol = function.symbol; - BType type = function.getBType(); - BInvokableSymbol varSymbol = new BInvokableSymbol(SymTag.VARIABLE, 0, invokableSymbol.name, - invokableSymbol.pkgID, type, - invokableSymbol.owner, function.pos, VIRTUAL); - varSymbol.params = invokableSymbol.params; - varSymbol.restParam = invokableSymbol.restParam; - varSymbol.retType = invokableSymbol.retType; - BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(function.pos, function.name.value, type, - lambdaFunction, varSymbol); - BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(function.pos); - variableDef.var = simpleVariable; - variableDef.setBType(type); - queue.add(variableDef); - - return varSymbol; - } - - public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol) { - BType type = invokableSymbol.retType; - BVarSymbol varSymbol = new BVarSymbol(0, invokableSymbol.name, invokableSymbol.originalName, - invokableSymbol.pkgID, type, invokableSymbol.owner, invokableSymbol.pos, - VIRTUAL); - BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(invokableSymbol.pos, - invokableSymbol.name.value, type, getInvocation(invokableSymbol), varSymbol); - BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(invokableSymbol.pos); - variableDef.var = simpleVariable; - variableDef.setBType(type); - queue.add(variableDef); - - return varSymbol; - } - - @Override - public void visit(BLangTupleVariable varNode) { - rewrite(varNode.restVariable, env); - result = varNode; - } - - @Override - public void visit(BLangRecordVariable varNode) { - varNode.expr = rewriteExpr(varNode.expr); - result = varNode; - } - - @Override - public void visit(BLangErrorVariable varNode) { - varNode.expr = rewriteExpr(varNode.expr); - result = varNode; - } - - @Override - public void visit(BLangTupleVariableDef varDefNode) { - varDefNode.var = rewrite(varDefNode.var, env); - result = varDefNode; - } - - @Override - public void visit(BLangRecordVariableDef varDefNode) { - varDefNode.var = rewrite(varDefNode.var, env); - result = varDefNode; - } - - @Override - public void visit(BLangErrorVariableDef varDefNode) { - varDefNode.errorVariable = rewrite(varDefNode.errorVariable, env); - result = varDefNode; - } - - @Override - public void visit(BLangAssignment assignNode) { - assignNode.varRef = rewriteExpr(assignNode.varRef); - assignNode.expr = rewriteExpr(assignNode.expr); - result = assignNode; - } - - @Override - public void visit(BLangTupleDestructure tupleDestructure) { - result = tupleDestructure; - } - - @Override - public void visit(BLangRecordDestructure recordDestructure) { - result = recordDestructure; - } - - @Override - public void visit(BLangErrorDestructure errorDestructure) { - result = errorDestructure; - } - - @Override - public void visit(BLangRetry retryNode) { - retryNode.retryBody = rewrite(retryNode.retryBody, env); - result = retryNode; - } - - @Override - public void visit(BLangRetryTransaction retryTransaction) { - retryTransaction.transaction = rewrite(retryTransaction.transaction, env); - result = retryTransaction; - } - - @Override - public void visit(BLangContinue nextNode) { - result = nextNode; - } - - @Override - public void visit(BLangBreak breakNode) { - result = breakNode; - } - - @Override - public void visit(BLangPanic panicNode) { - panicNode.expr = rewriteExpr(panicNode.expr); - result = panicNode; - } - - @Override - public void visit(BLangDo doNode) { - doNode.body = rewrite(doNode.body, env); - result = doNode; - } - - @Override - public void visit(BLangXMLNSStatement xmlnsStmtNode) { - xmlnsStmtNode.xmlnsDecl = rewrite(xmlnsStmtNode.xmlnsDecl, env); - result = xmlnsStmtNode; - } - - @Override - public void visit(BLangXMLNS xmlnsNode) { - xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); - result = xmlnsNode; - } - - @Override - public void visit(BLangExpressionStmt exprStmtNode) { - exprStmtNode.expr = rewriteExpr(exprStmtNode.expr); - result = exprStmtNode; - } - - @Override - public void visit(BLangFail failNode) { - if (failNode.exprStmt != null) { - failNode.exprStmt = rewrite(failNode.exprStmt, env); - } - result = failNode; - } - - @Override - public void visit(BLangIf ifNode) { - ifNode.expr = rewriteExpr(ifNode.expr); - ifNode.body = rewrite(ifNode.body, env); - ifNode.elseStmt = rewrite(ifNode.elseStmt, env); - result = ifNode; - } - - @Override - public void visit(BLangForeach foreach) { - result = foreach; - } - - @Override - public void visit(BLangWhile whileNode) { - whileNode.expr = rewriteExpr(whileNode.expr); - whileNode.body = rewrite(whileNode.body, env); - result = whileNode; - } - - @Override - public void visit(BLangLock lockNode) { - lockNode.body = rewrite(lockNode.body, env); - result = lockNode; - } - - @Override - public void visit(BLangLock.BLangLockStmt lockNode) { - result = lockNode; - } - - @Override - public void visit(BLangLock.BLangUnLockStmt unLockNode) { - result = unLockNode; - } - - @Override - public void visit(BLangTransaction transactionNode) { - transactionNode.transactionBody = rewrite(transactionNode.transactionBody, env); - result = transactionNode; - } - - @Override - public void visit(BLangRollback rollbackNode) { - rollbackNode.expr = rewriteExpr(rollbackNode.expr); - result = rollbackNode; - } - - @Override - public void visit(BLangTransactionalExpr transactionalExpr) { - result = transactionalExpr; - } - - @Override - public void visit(BLangCommitExpr commitExpr) { - result = commitExpr; - } - - @Override - public void visit(BLangForkJoin forkJoin) { - result = forkJoin; - } - - @Override - public void visit(BLangLiteral literalExpr) { - result = literalExpr; - } - - @Override - public void visit(BLangListConstructorExpr listConstructorExpr) { - listConstructorExpr.exprs = rewriteExprs(listConstructorExpr.exprs); - result = listConstructorExpr; - } - - @Override - public void visit(BLangTableConstructorExpr tableConstructorExpr) { - rewriteExprs(tableConstructorExpr.recordLiteralList); - result = tableConstructorExpr; - } - - @Override - public void visit(BLangListConstructorExpr.BLangJSONArrayLiteral jsonArrayLiteral) { - jsonArrayLiteral.exprs = rewriteExprs(jsonArrayLiteral.exprs); - result = jsonArrayLiteral; - } - - @Override - public void visit(BLangListConstructorExpr.BLangTupleLiteral tupleLiteral) { - tupleLiteral.exprs = rewriteExprs(tupleLiteral.exprs); - result = tupleLiteral; - } - - @Override - public void visit(BLangListConstructorExpr.BLangArrayLiteral arrayLiteral) { - arrayLiteral.exprs = rewriteExprs(arrayLiteral.exprs); - result = arrayLiteral; - } - - @Override - public void visit(BLangRecordLiteral recordLiteral) { - for (RecordLiteralNode.RecordField field : recordLiteral.fields) { - if (field.isKeyValueField()) { - BLangRecordLiteral.BLangRecordKeyValueField keyValueField = - (BLangRecordLiteral.BLangRecordKeyValueField) field; - keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); - keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); - } - } - result = recordLiteral; - } - - @Override - public void visit(BLangSimpleVarRef varRefExpr) { - if (varRefExpr.symbol == null) { - result = varRefExpr; - return; - } - - BLangInvokableNode encInvokable = env.enclInvokable; - if ((varRefExpr.symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { - BVarSymbol varSymbol = (BVarSymbol) varRefExpr.symbol; - if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && - encInvokable.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); - BSymbol resolvedSymbol = - symResolver.lookupClosureVarSymbol(encInvokableEnv, varRefExpr.symbol.name, SymTag.VARIABLE); - if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { - varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, - varRefExpr.pos)); - } - } - } - - result = varRefExpr; - } - - private void updateFunctionParams(BLangFunction funcNode, BLangSimpleVarRef varRefExpr) { - BInvokableSymbol funcSymbol = funcNode.symbol; - for (BVarSymbol varSymbol : funcSymbol.params) { - if (varSymbol.name.value.equals(varRefExpr.symbol.name.value)) { - varRefExpr.symbol = varSymbol; - return; - } - } - } - - private SymbolEnv findEnclosingInvokableEnv(SymbolEnv env, BLangInvokableNode encInvokable) { - if (env.enclEnv.node != null && env.enclEnv.node.getKind() == NodeKind.ARROW_EXPR) { - return env.enclEnv; - } - - if (env.enclEnv.node != null && (env.enclEnv.node.getKind() == NodeKind.ON_FAIL)) { - return env.enclEnv; - } - - if (env.enclInvokable != null && env.enclInvokable == encInvokable) { - return findEnclosingInvokableEnv(env.enclEnv, encInvokable); - } - return env; - } - - @Override - public void visit(BLangFieldBasedAccess fieldAccessExpr) { - fieldAccessExpr.expr = rewriteExpr(fieldAccessExpr.expr); - - result = fieldAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess indexAccessExpr) { - indexAccessExpr.indexExpr = rewriteExpr(indexAccessExpr.indexExpr); - indexAccessExpr.expr = rewriteExpr(indexAccessExpr.expr); - result = indexAccessExpr; - } - - @Override - public void visit(BLangCompoundAssignment compoundAssignment) { - result = compoundAssignment; - } - - @Override - public void visit(BLangInvocation invocation) { - rewriteInvocationExpr(invocation); - if (invocation.functionPointerInvocation) { - BLangInvokableNode encInvokable = env.enclInvokable; - if (encInvokable != null && encInvokable.flagSet.contains(Flag.LAMBDA)) { - BVarSymbol varSymbol = (BVarSymbol) invocation.symbol; - if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && - encInvokable.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); - BSymbol resolvedSymbol = symResolver.lookupClosureVarSymbol(encInvokableEnv, invocation.symbol.name, - SymTag.VARIABLE); - if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { - varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, - invocation.pos)); - } - } - } - } - } - - public void rewriteInvocationExpr(BLangInvocation invocation) { - invocation.requiredArgs = rewriteExprs(invocation.requiredArgs); - result = invocation; - - } - - @Override - public void visit(BLangQueryAction queryAction) { - result = queryAction; - } - - @Override - public void visit(BLangCheckPanickedExpr checkedExpr) { - result = checkedExpr; - } - - @Override - public void visit(BLangErrorConstructorExpr errorConstructorExpr) { - rewriteExprs(errorConstructorExpr.positionalArgs); - errorConstructorExpr.errorDetail = rewriteExpr(errorConstructorExpr.errorDetail); - result = errorConstructorExpr; - } - - @Override - public void visit(BLangTypeInit typeInitExpr) { - typeInitExpr.initInvocation = rewriteExpr(typeInitExpr.initInvocation); - result = typeInitExpr; - } - - @Override - public void visit(BLangTernaryExpr ternaryExpr) { - ternaryExpr.expr = rewriteExpr(ternaryExpr.expr); - ternaryExpr.thenExpr = rewriteExpr(ternaryExpr.thenExpr); - ternaryExpr.elseExpr = rewriteExpr(ternaryExpr.elseExpr); - result = ternaryExpr; - } - - @Override - public void visit(BLangWaitExpr waitExpr) { - List exprList = new ArrayList<>(); - waitExpr.exprList.forEach(expression -> exprList.add(rewriteExpr(expression))); - waitExpr.exprList = exprList; - result = waitExpr; - } - - @Override - public void visit(BLangWaitForAllExpr waitExpr) { - result = waitExpr; - } - - @Override - public void visit(BLangTrapExpr trapExpr) { - trapExpr.expr = rewriteExpr(trapExpr.expr); - result = trapExpr; - } - - @Override - public void visit(BLangBinaryExpr binaryExpr) { - binaryExpr.lhsExpr = rewriteExpr(binaryExpr.lhsExpr); - binaryExpr.rhsExpr = rewriteExpr(binaryExpr.rhsExpr); - result = binaryExpr; - } - - @Override - public void visit(BLangElvisExpr elvisExpr) { - result = elvisExpr; - } - - @Override - public void visit(BLangGroupExpr groupExpr) { - groupExpr.expression = rewriteExpr(groupExpr.expression); - result = groupExpr; - } - - @Override - public void visit(BLangUnaryExpr unaryExpr) { - unaryExpr.expr = rewriteExpr(unaryExpr.expr); - result = unaryExpr; - } - - @Override - public void visit(BLangTypeConversionExpr conversionExpr) { - conversionExpr.expr = rewriteExpr(conversionExpr.expr); - conversionExpr.typeNode = rewrite(conversionExpr.typeNode, env); - result = conversionExpr; - } - - @Override - public void visit(BLangLambdaFunction bLangLambdaFunction) { - bLangLambdaFunction.function = rewrite(bLangLambdaFunction.function, bLangLambdaFunction.capturedClosureEnv); - result = bLangLambdaFunction; - } - - @Override - public void visit(BLangArrowFunction bLangArrowFunction) { - result = bLangArrowFunction; - } - - @Override - public void visit(BLangXMLQName xmlQName) { - result = xmlQName; - } - - @Override - public void visit(BLangXMLAttribute xmlAttribute) { - xmlAttribute.name = rewriteExpr(xmlAttribute.name); - xmlAttribute.value = rewriteExpr(xmlAttribute.value); - result = xmlAttribute; - } - - @Override - public void visit(BLangRegExpTemplateLiteral regExpTemplateLiteral) { - List interpolationsList = - symResolver.getListOfInterpolations(regExpTemplateLiteral.reDisjunction.sequenceList); - interpolationsList.forEach(this::rewriteExpr); - result = regExpTemplateLiteral; - } - - @Override - public void visit(BLangXMLElementLiteral xmlElementLiteral) { - xmlElementLiteral.startTagName = rewriteExpr(xmlElementLiteral.startTagName); - xmlElementLiteral.endTagName = rewriteExpr(xmlElementLiteral.endTagName); - xmlElementLiteral.modifiedChildren = rewriteExprs(xmlElementLiteral.modifiedChildren); - xmlElementLiteral.attributes = rewriteExprs(xmlElementLiteral.attributes); - result = xmlElementLiteral; - } - - @Override - public void visit(BLangXMLTextLiteral xmlTextLiteral) { - xmlTextLiteral.textFragments.forEach(this::rewriteExpr); - xmlTextLiteral.concatExpr = rewriteExpr(xmlTextLiteral.concatExpr); - result = xmlTextLiteral; - } - - @Override - public void visit(BLangXMLCommentLiteral xmlCommentLiteral) { - xmlCommentLiteral.textFragments.forEach(this::rewriteExpr); - result = xmlCommentLiteral; - } - - @Override - public void visit(BLangXMLProcInsLiteral xmlProcInsLiteral) { - xmlProcInsLiteral.target = rewriteExpr(xmlProcInsLiteral.target); - xmlProcInsLiteral.dataFragments.forEach(this::rewriteExpr); - result = xmlProcInsLiteral; - } - - @Override - public void visit(BLangXMLQuotedString xmlQuotedString) { - xmlQuotedString.textFragments.forEach(this::rewriteExpr); - result = xmlQuotedString; - } - - @Override - public void visit(BLangStringTemplateLiteral stringTemplateLiteral) { - stringTemplateLiteral.exprs.forEach(this::rewriteExpr); - result = stringTemplateLiteral; - } - - @Override - public void visit(BLangWorkerSend workerSendNode) { - workerSendNode.expr = rewriteExpr(workerSendNode.expr); - result = workerSendNode; - } - - @Override - public void visit(BLangWorkerSyncSendExpr syncSendExpr) { - syncSendExpr.expr = rewriteExpr(syncSendExpr.expr); - result = syncSendExpr; - } - - @Override - public void visit(BLangWorkerReceive workerReceiveNode) { - result = workerReceiveNode; - } - - @Override - public void visit(BLangWorkerFlushExpr workerFlushExpr) { - result = workerFlushExpr; - } - - @Override - public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { - result = localVarRef; - } - - @Override - public void visit(BLangIgnoreExpr ignoreExpr) { - result = ignoreExpr; - } - - @Override - public void visit(BLangDynamicArgExpr dynamicParamExpr) { - dynamicParamExpr.condition = rewriteExpr(dynamicParamExpr.condition); - dynamicParamExpr.conditionalArgument = rewriteExpr(dynamicParamExpr.conditionalArgument); - result = dynamicParamExpr; - } - - @Override - public void visit(BLangSimpleVarRef.BLangPackageVarRef packageVarRef) { - result = packageVarRef; - } - - @Override - public void visit(BLangConstRef constRef) { - result = constRef; - } - - @Override - public void visit(BLangSimpleVarRef.BLangFunctionVarRef functionVarRef) { - result = functionVarRef; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangStructFieldAccessExpr fieldAccessExpr) { - fieldAccessExpr.indexExpr = rewriteExpr(fieldAccessExpr.indexExpr); - fieldAccessExpr.expr = rewriteExpr(fieldAccessExpr.expr); - result = fieldAccessExpr; - } - - @Override - public void visit(BLangFieldBasedAccess.BLangStructFunctionVarRef functionVarRef) { - functionVarRef.expr = rewriteExpr(functionVarRef.expr); - result = functionVarRef; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangMapAccessExpr mapKeyAccessExpr) { - mapKeyAccessExpr.indexExpr = rewriteExpr(mapKeyAccessExpr.indexExpr); - mapKeyAccessExpr.expr = rewriteExpr(mapKeyAccessExpr.expr); - result = mapKeyAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangTableAccessExpr tableKeyAccessExpr) { - tableKeyAccessExpr.indexExpr = rewriteExpr(tableKeyAccessExpr.indexExpr); - tableKeyAccessExpr.expr = rewriteExpr(tableKeyAccessExpr.expr); - result = tableKeyAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangArrayAccessExpr arrayIndexAccessExpr) { - arrayIndexAccessExpr.indexExpr = rewriteExpr(arrayIndexAccessExpr.indexExpr); - arrayIndexAccessExpr.expr = rewriteExpr(arrayIndexAccessExpr.expr); - result = arrayIndexAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangTupleAccessExpr arrayIndexAccessExpr) { - arrayIndexAccessExpr.indexExpr = rewriteExpr(arrayIndexAccessExpr.indexExpr); - arrayIndexAccessExpr.expr = rewriteExpr(arrayIndexAccessExpr.expr); - result = arrayIndexAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangXMLAccessExpr xmlIndexAccessExpr) { - xmlIndexAccessExpr.indexExpr = rewriteExpr(xmlIndexAccessExpr.indexExpr); - xmlIndexAccessExpr.expr = rewriteExpr(xmlIndexAccessExpr.expr); - result = xmlIndexAccessExpr; - } - - @Override - public void visit(BLangXMLElementAccess xmlElementAccess) { - xmlElementAccess.expr = rewriteExpr(xmlElementAccess.expr); - result = xmlElementAccess; - } - - @Override - public void visit(BLangXMLNavigationAccess xmlNavigation) { - xmlNavigation.expr = rewriteExpr(xmlNavigation.expr); - xmlNavigation.childIndex = rewriteExpr(xmlNavigation.childIndex); - result = xmlNavigation; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangJSONAccessExpr jsonAccessExpr) { - jsonAccessExpr.indexExpr = rewriteExpr(jsonAccessExpr.indexExpr); - jsonAccessExpr.expr = rewriteExpr(jsonAccessExpr.expr); - result = jsonAccessExpr; - } - - @Override - public void visit(BLangIndexBasedAccess.BLangStringAccessExpr stringAccessExpr) { - stringAccessExpr.indexExpr = rewriteExpr(stringAccessExpr.indexExpr); - stringAccessExpr.expr = rewriteExpr(stringAccessExpr.expr); - result = stringAccessExpr; - } - - @Override - public void visit(BLangRecordLiteral.BLangMapLiteral mapLiteral) { - for (RecordLiteralNode.RecordField field : mapLiteral.fields) { - if (field.isKeyValueField()) { - BLangRecordLiteral.BLangRecordKeyValueField keyValueField = - (BLangRecordLiteral.BLangRecordKeyValueField) field; - keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); - keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); - continue; - } - - BLangRecordLiteral.BLangRecordSpreadOperatorField spreadField = - (BLangRecordLiteral.BLangRecordSpreadOperatorField) field; - spreadField.expr = rewriteExpr(spreadField.expr); - } - result = mapLiteral; - } - - @Override - public void visit(BLangRecordLiteral.BLangStructLiteral structLiteral) { - for (RecordLiteralNode.RecordField field : structLiteral.fields) { - if (field.isKeyValueField()) { - BLangRecordLiteral.BLangRecordKeyValueField keyValueField = - (BLangRecordLiteral.BLangRecordKeyValueField) field; - keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); - keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); - continue; - } - - BLangRecordLiteral.BLangRecordSpreadOperatorField spreadField = - (BLangRecordLiteral.BLangRecordSpreadOperatorField) field; - spreadField.expr = rewriteExpr(spreadField.expr); - } - - result = structLiteral; - } - - @Override - public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { - waitLiteral.keyValuePairs.forEach(keyValue -> { - if (keyValue.valueExpr != null) { - keyValue.valueExpr = rewriteExpr(keyValue.valueExpr); - } else { - keyValue.keyExpr = rewriteExpr(keyValue.keyExpr); - } - }); - result = waitLiteral; - } - - @Override - public void visit(BLangIsAssignableExpr assignableExpr) { - assignableExpr.lhsExpr = rewriteExpr(assignableExpr.lhsExpr); - result = assignableExpr; - } - - @Override - public void visit(BLangInvocation.BFunctionPointerInvocation fpInvocation) { - fpInvocation.expr = rewriteExpr(fpInvocation.expr); - rewriteInvocationExpr(fpInvocation); - } - - @Override - public void visit(BLangTypedescExpr accessExpr) { - result = accessExpr; - } - - @Override - public void visit(BLangRestArgsExpression bLangVarArgsExpression) { - result = rewriteExpr(bLangVarArgsExpression.expr); - } - - @Override - public void visit(BLangNamedArgsExpression bLangNamedArgsExpression) { - bLangNamedArgsExpression.expr = rewriteExpr(bLangNamedArgsExpression.expr); - result = bLangNamedArgsExpression; - } - - @Override - public void visit(BLangCheckedExpr checkedExpr) { - result = checkedExpr; - } - - @Override - public void visit(BLangServiceConstructorExpr serviceConstructorExpr) { - result = serviceConstructorExpr; - } - - @Override - public void visit(BLangTypeTestExpr typeTestExpr) { - typeTestExpr.expr = rewriteExpr(typeTestExpr.expr); - result = typeTestExpr; - } - - @Override - public void visit(BLangIsLikeExpr isLikeExpr) { - isLikeExpr.expr = rewriteExpr(isLikeExpr.expr); - result = isLikeExpr; - } - - public void visit(BLangFieldBasedAccess.BLangNSPrefixedFieldBasedAccess nsPrefixedFieldBasedAccess) { - result = nsPrefixedFieldBasedAccess; - } - - @Override - public void visit(BLangLetExpression letExpression) { - for (BLangLetVariable letVariable : letExpression.letVarDeclarations) { - rewrite((BLangNode) letVariable.definitionNode, env); - } - letExpression.expr = rewriteExpr(letExpression.expr); - result = letExpression; - } - - @Override - public void visit(BLangAnnotAccessExpr annotAccessExpr) { - annotAccessExpr.expr = rewriteExpr(annotAccessExpr.expr); - result = annotAccessExpr; - } - - @Override - public void visit(BLangStatementExpression bLangStatementExpression) { - if (bLangStatementExpression.stmt.getKind() == NodeKind.BLOCK) { - BLangBlockStmt bLangBlockStmt = (BLangBlockStmt) bLangStatementExpression.stmt; - for (int i = 0; i < bLangBlockStmt.stmts.size(); i++) { - BLangStatement stmt = bLangBlockStmt.stmts.remove(i); - bLangBlockStmt.stmts.add(i, rewrite(stmt, env)); - } - } else { - bLangStatementExpression.stmt = rewrite(bLangStatementExpression.stmt, env); - } - bLangStatementExpression.expr = rewriteExpr(bLangStatementExpression.expr); - result = bLangStatementExpression; - } - - @Override - public void visit(BLangInvocation.BLangActionInvocation invocation) { - rewriteInvocationExpr(invocation); - } - - @Override - public void visit(BLangIdentifier identifierNode) { - /* ignore */ - } - - @Override - public void visit(BLangAnnotation annotationNode) { - /* ignore */ - } - - @Override - public void visit(BLangAnnotationAttachment annAttachmentNode) { - /* ignore */ - } - - @Override - public void visit(BLangConstant constant) { - result = constant; - } - - @Override - public void visit(BLangNumericLiteral literalExpr) { - result = literalExpr; - } - - @Override - public void visit(BLangTupleVarRef varRefExpr) { - result = varRefExpr; - } - - @Override - public void visit(BLangRecordVarRef varRefExpr) { - result = varRefExpr; - } - - @Override - public void visit(BLangErrorVarRef varRefExpr) { - result = varRefExpr; - } - - @Override - public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { - result = typeLoad; - } - - @Override - public void visit(BLangRecordLiteral.BLangChannelLiteral channelLiteral) { - channelLiteral.fields.forEach(field -> { - BLangRecordLiteral.BLangRecordKeyValueField keyValue = (BLangRecordLiteral.BLangRecordKeyValueField) field; - keyValue.key.expr = rewriteExpr(keyValue.key.expr); - keyValue.valueExpr = rewriteExpr(keyValue.valueExpr); - }); - result = channelLiteral; - } - - @Override - public void visit(BLangXMLNS.BLangLocalXMLNS xmlnsNode) { - xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); - result = xmlnsNode; - } - - @Override - public void visit(BLangXMLNS.BLangPackageXMLNS xmlnsNode) { - xmlnsNode.namespaceURI = rewriteExpr(xmlnsNode.namespaceURI); - result = xmlnsNode; - } - - @Override - public void visit(BLangListConstructorExpr.BLangListConstructorSpreadOpExpr listConstructorSpreadOpExpr) { - listConstructorSpreadOpExpr.expr = rewriteExpr(listConstructorSpreadOpExpr.expr); - result = listConstructorSpreadOpExpr; - } - - @Override - public void visit(BLangQueryExpr queryExpr) { - result = queryExpr; - } - - @Override - public void visit(BLangMatchStatement matchStatement) { - result = matchStatement; - } - - @Override - public void visit(BLangXMLSequenceLiteral xmlSequenceLiteral) { - xmlSequenceLiteral.xmlItems.forEach(this::rewriteExpr); - result = xmlSequenceLiteral; - } - - @Override - public void visit(BLangMarkdownDocumentationLine bLangMarkdownDocumentationLine) { - /* Ignore */ - } - - @Override - public void visit(BLangMarkdownParameterDocumentation bLangDocumentationParameter) { - /* Ignore */ - } - - @Override - public void visit(BLangMarkdownReturnParameterDocumentation bLangMarkdownReturnParameterDocumentation) { - /* Ignore */ - } - - @Override - public void visit(BLangInferredTypedescDefaultNode inferTypedescExpr) { - result = inferTypedescExpr; - } - @Override - public void visit(BLangMarkdownDocumentation bLangMarkdownDocumentation) { - /* Ignore */ - } - - // Rewrite methods - - @SuppressWarnings("unchecked") - private E rewrite(E node, SymbolEnv env) { - if (node == null) { - return null; - } - - SymbolEnv previousEnv = this.env; - this.env = env; - - node.accept(this); - BLangNode resultNode = this.result; - this.result = null; - - this.env = previousEnv; - return (E) resultNode; - } - - public List rewrite(List nodeList, SymbolEnv env) { - for (int i = 0; i < nodeList.size(); i++) { - nodeList.set(i, rewrite(nodeList.get(i), env)); - } - return nodeList; - } - - @SuppressWarnings("unchecked") - public E rewriteExpr(E node) { - if (node == null) { - return null; - } - - node.accept(this); - BLangNode resultNode = this.result; - this.result = null; - return (E) resultNode; - } - - @SuppressWarnings("unchecked") - private List rewriteStmt(List nodeList, SymbolEnv env) { - Queue previousQueue = this.queue; - this.queue = new LinkedList<>(); - int size = nodeList.size(); - for (int i = 0; i < size; i++) { - E node = rewrite(nodeList.remove(0), env); - Iterator iterator = queue.iterator(); - while (iterator.hasNext()) { - nodeList.add(rewrite((E) queue.poll(), env)); - } - nodeList.add(node); - } - this.queue = previousQueue; - return nodeList; - } - - @SuppressWarnings("unchecked") - private List rewriteExprs(List nodeList) { - for (int i = 0; i < nodeList.size(); i++) { - rewriteExpr(nodeList.get(i)); - nodeList.set(i, rewriteExpr(nodeList.get(i))); - } - return nodeList; - } -} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java index e96e1f9b756d..be1a7ab369b9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java @@ -30,6 +30,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; @@ -202,6 +203,7 @@ public class ParameterDesugar extends BLangNodeVisitor { private SymbolEnv env; private BLangNode result; private SymbolResolver symResolver; + private AnnotationDesugar annotationDesugar; public static ParameterDesugar getInstance(CompilerContext context) { ParameterDesugar parameterDesugar = context.get(PARAMETER_DESUGAR_KEY); @@ -217,6 +219,7 @@ private ParameterDesugar(CompilerContext context) { this.symTable = SymbolTable.getInstance(context); this.queue = new LinkedList<>(); this.symResolver = SymbolResolver.getInstance(context); + this.annotationDesugar = AnnotationDesugar.getInstance(context); } @Override @@ -380,6 +383,18 @@ public void visit(BLangObjectConstructorExpression objectConstructorExpression) @Override public void visit(BLangRecordTypeNode recordTypeNode) { + PackageID pkgID = recordTypeNode.symbol.pkgID; + BSymbol owner = recordTypeNode.symbol.owner; + + if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { + BLangLambdaFunction lambdaFunction = + annotationDesugar.defineAnnotationsForLocalRecords(recordTypeNode, env.enclPkg, env, pkgID, owner); + if (lambdaFunction != null) { + BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); + ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = + createSimpleVariable(invokableSymbol); + } + } for (BLangSimpleVariable field : recordTypeNode.fields) { rewrite(field, env); } @@ -557,7 +572,7 @@ BLangLambdaFunction createLambdaFunction(BLangFunction function) { return lambdaFunction; } - private BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction) { + public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction) { BInvokableSymbol invokableSymbol = function.symbol; BType type = function.getBType(); BInvokableSymbol varSymbol = new BInvokableSymbol(SymTag.VARIABLE, 0, invokableSymbol.name, @@ -576,6 +591,30 @@ private BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambd return varSymbol; } + public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol) { + BType type = invokableSymbol.retType; + BVarSymbol varSymbol = new BVarSymbol(0, invokableSymbol.name, invokableSymbol.originalName, + invokableSymbol.pkgID, type, invokableSymbol.owner, invokableSymbol.pos, + VIRTUAL); + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(invokableSymbol.pos, + invokableSymbol.name.value, type, getInvocation(invokableSymbol), varSymbol); + BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(invokableSymbol.pos); + variableDef.var = simpleVariable; + variableDef.setBType(type); + queue.add(variableDef); + + return varSymbol; + } + + private BLangInvocation getInvocation(BInvokableSymbol symbol) { + BLangInvocation funcInvocation = (BLangInvocation) TreeBuilder.createInvocationNode(); + funcInvocation.setBType(symbol.retType); + funcInvocation.symbol = symbol; + funcInvocation.name = ASTBuilderUtil.createIdentifier(symbol.pos, symbol.name.value); + funcInvocation.functionPointerInvocation = true; + return funcInvocation; + } + private BLangFunction createFunction(String funcName, Location pos, PackageID pkgID, BSymbol owner, BType bType) { BLangFunction function = ASTBuilderUtil.createFunction(pos, funcName); function.flagSet.add(Flag.PUBLIC); @@ -845,6 +884,14 @@ public void visit(BLangListConstructorExpr.BLangArrayLiteral arrayLiteral) { @Override public void visit(BLangRecordLiteral recordLiteral) { + for (RecordLiteralNode.RecordField field : recordLiteral.fields) { + if (field.isKeyValueField()) { + BLangRecordLiteral.BLangRecordKeyValueField keyValueField = + (BLangRecordLiteral.BLangRecordKeyValueField) field; + keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); + keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); + } + } result = recordLiteral; } @@ -953,6 +1000,23 @@ public void visit(BLangCompoundAssignment compoundAssignment) { @Override public void visit(BLangInvocation invocation) { rewriteInvocationExpr(invocation); + if (invocation.functionPointerInvocation) { + BLangInvokableNode encInvokable = env.enclInvokable; + if (encInvokable != null && encInvokable.flagSet.contains(Flag.LAMBDA)) { + BVarSymbol varSymbol = (BVarSymbol) invocation.symbol; + if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && + encInvokable.flagSet.contains(Flag.LAMBDA)) { + SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); + BSymbol resolvedSymbol = symResolver.lookupClosureVarSymbol(encInvokableEnv, invocation.symbol.name, + SymTag.VARIABLE); + if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { + varSymbol.closure = true; + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, + invocation.pos)); + } + } + } + } } public void rewriteInvocationExpr(BLangInvocation invocation) { @@ -1130,7 +1194,7 @@ public void visit(BLangWorkerFlushExpr workerFlushExpr) { @Override public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { - + result = localVarRef; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java index 214849fafd0f..3dba6a61f305 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangPackage.java @@ -80,8 +80,6 @@ public class BLangPackage extends BLangNode implements PackageNode { public Set completedPhases; // Queue to maintain lambda functions so that we can visit all lambdas at the end of the semantic phase public Queue lambdaFunctions = new ArrayDeque<>(); - // List to maintain lambda functions of annotations - public List anonFunctions; // Hold global variable dependencies identified in DataflowAnalyzer. public Map> globalVariableDependencies; @@ -103,7 +101,6 @@ public BLangPackage() { this.globalVars = new ArrayList<>(); this.services = new ArrayList<>(); this.functions = new ArrayList<>(); - this.anonFunctions = new ArrayList<>(); this.typeDefinitions = new ArrayList<>(); this.annotations = new ArrayList<>(); this.classDefinitions = new ArrayList<>(); From d66a17c4a0989cfb0aef6d5756eb9dc929281f39 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 3 Nov 2022 12:37:01 +0530 Subject: [PATCH 08/43] fix `getting unused variable warning` --- .../compiler/semantics/analyzer/DataflowAnalyzer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java index c8d51313f4c3..31e0862a2e79 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java @@ -2010,6 +2010,9 @@ public void visit(BLangRecordTypeNode recordTypeNode) { for (BLangSimpleVariable field : recordTypeNode.fields) { addTypeDependency(tsymbol, Types.getReferredType(field.getBType()), new HashSet<>()); analyzeNode(field, env); + for (BLangAnnotationAttachment annotationAttachment : field.annAttachments) { + analyzeNode(annotationAttachment.expr, env); + } recordGlobalVariableReferenceRelationship(field.symbol); } } From e084377c11eca530ca9d36dd09e08d22083e12dd Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 10 Nov 2022 11:48:25 +0530 Subject: [PATCH 09/43] fix review suggestions --- .../internal/values/TypedescValueImpl.java | 5 +---- .../wso2/ballerinalang/compiler/bir/BIRGen.java | 17 +++++++++++++---- .../compiler/bir/model/BIRNonTerminator.java | 10 +++++++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index f38ebcbc7694..feccd6b1e7d6 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -68,13 +68,10 @@ public TypedescValueImpl(Type describingType, MapValue[] closures) { @Deprecated public TypedescValueImpl(Type describingType, MapValue[] closures, MapValue annotations) { - this.type = new BTypedescType(describingType); - this.describingType = describingType; - this.closures = closures; + this(describingType, closures); this.annotations = annotations; } - /** * Returns the {@code BType} of the value describe by this type descriptor. * @return describing type diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index f9d3ebd99a3c..1fce3f1ed5d2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -1551,7 +1551,7 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { - visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList(), null); + visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1951,7 +1951,7 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { - visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList(), null); + visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId(names)); addToTrapStack(thenBB); BIRVariableDcl tempVarDcl = new BIRVariableDcl(waitLiteral.getBType(), @@ -2179,7 +2179,7 @@ public void visit(BLangTypedescExpr accessExpr) { this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(accessExpr.pos, toVarRef, accessExpr.resolvedType, - Collections.emptyList(), null)); + Collections.emptyList())); this.env.targetOperand = toVarRef; } @@ -2228,7 +2228,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { BType type = typeLoad.symbol.tag == SymTag.TYPE_DEF ? ((BTypeDefinitionSymbol) typeLoad.symbol).referenceType : typeLoad.symbol.type; - visitTypedesc(typeLoad.pos, type, Collections.emptyList(), null); + visitTypedesc(typeLoad.pos, type, Collections.emptyList()); } private void visitTypedesc(Location pos, BType type, List varDcls, BIROperand annotations) { @@ -2240,6 +2240,15 @@ private void visitTypedesc(Location pos, BType type, List varDcls, B this.env.targetOperand = toVarRef; } + private void visitTypedesc(Location pos, BType type, List varDcls) { + BIRVariableDcl tempVarDcl = new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(tempVarDcl); + BIROperand toVarRef = new BIROperand(tempVarDcl); + setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls)); + this.env.targetOperand = toVarRef; + } + @Override public void visit(BLangBreak breakStmt) { BIRLockDetailsHolder toUnlock = this.env.unlockVars.peek(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java index 218a1b0ecb4f..1481d7a60c8b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRNonTerminator.java @@ -808,14 +808,18 @@ public BIROperand[] getRhsOperands() { public static class NewTypeDesc extends BIRNonTerminator { public final List closureVars; public BType type; - public final BIROperand annotations; + public BIROperand annotations; - public NewTypeDesc(Location pos, BIROperand lhsOp, BType type, List closureVars, - BIROperand annotations) { + public NewTypeDesc(Location pos, BIROperand lhsOp, BType type, List closureVars) { super(pos, InstructionKind.NEW_TYPEDESC); this.closureVars = closureVars; this.lhsOp = lhsOp; this.type = type; + } + + public NewTypeDesc(Location pos, BIROperand lhsOp, BType type, List closureVars, + BIROperand annotations) { + this(pos, lhsOp, type, closureVars); this.annotations = annotations; } From b88ddd0d9abef93cca71c87203230c45ba1a2457 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 14 Nov 2022 11:50:39 +0530 Subject: [PATCH 10/43] Rename `ParameterDesugar` class as `ClosureGenerator` --- .../compiler/desugar/AnnotationDesugar.java | 6 +++--- ...meterDesugar.java => ClosureGenerator.java} | 18 +++++++++--------- .../compiler/desugar/Desugar.java | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) rename compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/{ParameterDesugar.java => ClosureGenerator.java} (99%) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 7d61a4f1b774..201b0d09a657 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -139,7 +139,7 @@ public class AnnotationDesugar { private final Names names; private SymbolResolver symResolver; private ConstantValueResolver constantValueResolver; - private ParameterDesugar parameterDesugar; + private ClosureGenerator closureGenerator; public static AnnotationDesugar getInstance(CompilerContext context) { AnnotationDesugar annotationDesugar = context.get(ANNOTATION_DESUGAR_KEY); @@ -157,7 +157,7 @@ private AnnotationDesugar(CompilerContext context) { this.names = Names.getInstance(context); this.symResolver = SymbolResolver.getInstance(context); this.constantValueResolver = ConstantValueResolver.getInstance(context); - this.parameterDesugar = ParameterDesugar.getInstance(context); + this.closureGenerator = ClosureGenerator.getInstance(context); } /** @@ -648,7 +648,7 @@ public BLangLambdaFunction defineAnnotationsForLocalRecords(BLangRecordTypeNode pkgID, owner, false); if (fieldAnnotLambda != null) { BInvokableSymbol invokableSymbol = - parameterDesugar.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); + closureGenerator.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); env.scope.define(invokableSymbol.name, invokableSymbol); if (!annotFunctionDefined) { function = defineFunction(recordTypeNode.pos, pkgID, owner); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java similarity index 99% rename from compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java rename to compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index be1a7ab369b9..51150b2beb15 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ParameterDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -195,8 +195,8 @@ * * @since 2201.3.0 */ -public class ParameterDesugar extends BLangNodeVisitor { - private static final CompilerContext.Key PARAMETER_DESUGAR_KEY = new CompilerContext.Key<>(); +public class ClosureGenerator extends BLangNodeVisitor { + private static final CompilerContext.Key CLOSURE_GENERATOR_KEY = new CompilerContext.Key<>(); private Queue queue; private SymbolTable symTable; @@ -205,17 +205,17 @@ public class ParameterDesugar extends BLangNodeVisitor { private SymbolResolver symResolver; private AnnotationDesugar annotationDesugar; - public static ParameterDesugar getInstance(CompilerContext context) { - ParameterDesugar parameterDesugar = context.get(PARAMETER_DESUGAR_KEY); - if (parameterDesugar == null) { - parameterDesugar = new ParameterDesugar(context); + public static ClosureGenerator getInstance(CompilerContext context) { + ClosureGenerator closureGenerator = context.get(CLOSURE_GENERATOR_KEY); + if (closureGenerator == null) { + closureGenerator = new ClosureGenerator(context); } - return parameterDesugar; + return closureGenerator; } - private ParameterDesugar(CompilerContext context) { - context.put(PARAMETER_DESUGAR_KEY, this); + private ClosureGenerator(CompilerContext context) { + context.put(CLOSURE_GENERATOR_KEY, this); this.symTable = SymbolTable.getInstance(context); this.queue = new LinkedList<>(); this.symResolver = SymbolResolver.getInstance(context); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java index af12a8474f00..62d42c5acdd2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/Desugar.java @@ -373,7 +373,7 @@ public class Desugar extends BLangNodeVisitor { private SymbolResolver symResolver; private final SymbolEnter symbolEnter; private ClosureDesugar closureDesugar; - private ParameterDesugar parameterDesugar; + private ClosureGenerator closureGenerator; private QueryDesugar queryDesugar; private TransactionDesugar transactionDesugar; private ObservabilityDesugar observabilityDesugar; @@ -446,7 +446,7 @@ private Desugar(CompilerContext context) { this.symResolver = SymbolResolver.getInstance(context); this.symbolEnter = SymbolEnter.getInstance(context); this.closureDesugar = ClosureDesugar.getInstance(context); - this.parameterDesugar = ParameterDesugar.getInstance(context); + this.closureGenerator = ClosureGenerator.getInstance(context); this.queryDesugar = QueryDesugar.getInstance(context); this.transactionDesugar = TransactionDesugar.getInstance(context); this.observabilityDesugar = ObservabilityDesugar.getInstance(context); @@ -773,7 +773,7 @@ public void visit(BLangPackage pkgNode) { } // create closures for default values - parameterDesugar.visit(pkgNode); + closureGenerator.visit(pkgNode); // Initialize the annotation map annotationDesugar.initializeAnnotationMap(pkgNode); From 542901575c5e45847c518cc843f73eaf3c242c0c Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 14 Nov 2022 20:22:26 +0530 Subject: [PATCH 11/43] Add annotation details to BIR --- .../compiler/BIRPackageSymbolEnter.java | 12 ++++++++++++ .../compiler/bir/writer/BIRTypeWriter.java | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java index 834793a6d261..c7b904d21e3c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java @@ -1314,6 +1314,18 @@ public BType readType(int cpI) throws IOException { } recordType.typeInclusions = readTypeInclusions(); + boolean hasAnnotations = inputStream.readBoolean(); + if (hasAnnotations) { + String fieldName = getStringCPEntryValue(inputStream); + var fieldFlags = inputStream.readLong(); + byte[] docBytes = readDocBytes(inputStream); + BType fieldType = readTypeFromCp(); + BVarSymbol varSymbol = new BVarSymbol(fieldFlags, Names.fromString(fieldName), + recordSymbol.pkgID, fieldType, recordSymbol, + symTable.builtinPos, COMPILED_SOURCE); + defineMarkDownDocAttachment(varSymbol, docBytes); + recordSymbol.annotations = varSymbol; + } // setDocumentation(varSymbol, attrData); // TODO fix diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java index 3f97170c039f..b4e6c0a4f1e3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java @@ -424,6 +424,15 @@ public void visit(BRecordType bRecordType) { writeTypeCpIndex(initializerFunc.type); writeTypeInclusions(bRecordType.typeInclusions); + BVarSymbol annotations = tsymbol.annotations; + boolean annotationsExist = annotations != null; + buff.writeBoolean(annotationsExist); + if (annotationsExist) { + buff.writeInt(addStringCPEntry(annotations.name.value)); + buff.writeLong(annotations.flags); + writeMarkdownDocAttachment(buff, annotations.markdownDocumentation); + writeTypeCpIndex(annotations.type); + } } @Override From 097c3eb64fc91bef8ddf9cb8d6fd7dfce82ba0c8 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 14 Nov 2022 20:23:09 +0530 Subject: [PATCH 12/43] Update bir spec with annotation details --- docs/bir-spec/src/main/resources/kaitai/bir.ksy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/bir-spec/src/main/resources/kaitai/bir.ksy b/docs/bir-spec/src/main/resources/kaitai/bir.ksy index 9d67d8fc1283..203c5d368b00 100644 --- a/docs/bir-spec/src/main/resources/kaitai/bir.ksy +++ b/docs/bir-spec/src/main/resources/kaitai/bir.ksy @@ -472,6 +472,11 @@ types: type: s4 repeat: expr repeat-expr: type_inclusions_count + - id: has_annotations + type: u1 + - id: annotations_cp_index + type: s4 + if: has_annotations != 0 record_field: seq: - id: name_cp_index From b34390d20fac3cdddf08d003157e2dbc6b01c46f Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 11 Jan 2023 10:55:26 +0530 Subject: [PATCH 13/43] Fix review suggestions --- .../runtime/api/values/BTypedesc.java | 2 +- .../runtime/internal/TypeChecker.java | 20 +---- .../GetLocalRecordAnnotations.java | 33 -------- .../LocalRecordAnnotationTest.java | 31 +++++++- .../test/bala/annotation/AnnotationTests.java | 5 ++ .../local_record_annotation_test.bal | 75 ++++++++----------- .../bala/test_bala/annotations/annotation.bal | 12 +++ .../test_project/annotations.bal | 11 +++ 8 files changed, 88 insertions(+), 101 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java index 61cf15533c80..9ad3561d1d52 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java @@ -48,7 +48,7 @@ public interface BTypedesc extends BValue { Object instantiate(Strand strand); /** - * Returns the annotations of the value describe by this type descriptor. + * Returns the annotations specified on this type descriptor. * * @return annotations */ diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java index c20a21481ced..48a7865bdbbe 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java @@ -584,28 +584,10 @@ public static TypedescValue getTypedesc(Object value) { * @param annotTag The annot-tag-reference * @return the annotation value if present, nil else */ - public static Object getAnnotValue(TypedescValue typedescValue, String annotTag) { - MapValue annotMap = typedescValue.getAnnotations(); - if (annotMap != null) { - Object annotation = annotMap.get(annotTag); - if (annotation != null) { - return annotation; - } - } - Type describingType = typedescValue.getDescribingType(); - if (!(describingType instanceof BAnnotatableType)) { - return null; - } - return ((BAnnotatableType) describingType).getAnnotation(StringUtils.fromString(annotTag)); - } - public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag) { MapValue annotMap = typedescValue.getAnnotations(); if (annotMap != null) { - Object annotation = annotMap.get(annotTag); - if (annotation != null) { - return annotation; - } + return annotMap.get(annotTag); } Type describingType = typedescValue.getDescribingType(); if (!(describingType instanceof BAnnotatableType)) { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java deleted file mode 100644 index 5d3fa729470a..000000000000 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/GetLocalRecordAnnotations.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. - * - * WSO2 Inc. licenses this file to you 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. - */ -package org.ballerinalang.test.annotations; - -import io.ballerina.runtime.api.values.BString; -import io.ballerina.runtime.api.values.BValue; -import io.ballerina.runtime.internal.TypeChecker; -import io.ballerina.runtime.internal.values.TypedescValue; - -/** - * Class to get annotation of local record types. - * - * @since 2201.4.0 - */ -public class GetLocalRecordAnnotations { - public static BValue getLocalRecordAnnotations(TypedescValue typedescValue, BString annotName) { - return (BValue) TypeChecker.getAnnotValue(typedescValue, annotName); - } -} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java index aeae5f27ec32..e7c3cd7ff1cc 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java @@ -16,11 +16,16 @@ */ package org.ballerinalang.test.annotations; +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.internal.TypeChecker; +import io.ballerina.runtime.internal.values.TypedescValue; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; import org.testng.Assert; import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** @@ -37,8 +42,28 @@ public void setup() { Assert.assertEquals(result.getErrorCount(), 0); } - @Test - public void testLocalServiceAnnotEvaluation() { - BRunUtil.invoke(result, "testLocalRecordAnnotations"); + @Test(dataProvider = "dataToTestAnnotationsOfLocalRecord") + public void testLocalRecordAnnotations(String function) { + BRunUtil.invoke(result, function); + } + + @DataProvider(name = "dataToTestAnnotationsOfLocalRecord") + public Object[] dataToTestAnnotationsOfLocalRecord() { + return new String[]{ + "testMultipleAnnotationsOnLocaRecord", + "testAnnotationOnLocalRecord", + "testAnnotationOnLocalRecordWithGlobalVariable", + "testAnnotationOnLocalRecordWithinLambdaFunction", + "testAnnotationOnLocalRecordWithinLambdaFunction1", + "testAnnotationOnLocalRecordWithinNestedLambdaFunctions", + "testAnnotationOnLocalRecordWithinNestedLambdaFunctions1", + "testAnnotationOnLocalRecordWithinNestedLambdaFunctions2", + "testAnnotationWithMultipleFieldsOnLocalRecord", + "testAnnotationOnLocalRecordWithMultipleFields" + }; + } + + public static BMap getLocalRecordAnnotations(TypedescValue typedescValue, BString annotName) { + return (BMap) TypeChecker.getAnnotValue(typedescValue, annotName); } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java index f2f84e54f6f8..d946e623b797 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java @@ -65,6 +65,11 @@ public void setup() { birTestResult = BCompileUtil.compile("test-src/bala/test_bala/annotations/annot_attachments_bala_test.bal"); } + @Test + public void testAnnotationsOnRecordFields() { + BRunUtil.invoke(result, "testAnnotOnRecordFields"); + } + @Test(description = "Test the deprecated construct from external module") public void testDeprecation() { CompileResult result = BCompileUtil.compile("test-src/bala/test_bala/annotations/deprecation_annotation.bal"); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal index f8b29f88c1cb..489973462701 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal @@ -33,50 +33,44 @@ function testAnnotationOnLocalRecord() { string k = "chiranS"; record {@annot {value: k} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); } function testAnnotationWithMultipleFieldsOnLocalRecord() { string k = "chiranS"; record {@details {name: k, age: 26} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"details\":{\"name\":\"chiranS\",\"age\":26}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({name: "chiranS", age: 26}, >m["details"]); } function testAnnotationOnLocalRecordWithMultipleFields() { string k = "chiranS"; record {@annot {value: k} string x; @annot {value: k} string y; } r = {x : "", y: ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); - any y = getLocalRecordAnnotations(typeof r, "$field$.y"); - assertEquality("typedesc map", (typeof y).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", y.toString()); + map y = getLocalRecordAnnotations(typeof r, "$field$.y"); + assertEquality({value: "chiranS"}, >y["annot"]); } - string gVar = "foo"; + function testAnnotationOnLocalRecordWithGlobalVariable() { record {@annot {value: gVar} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"foo\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "foo"}, >m["annot"]); } function testAnnotationOnLocalRecordWithinLambdaFunction() { string k = "chiranS"; function() func = function () { record {@annot {value: k} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"} , >m["annot"]); }; func(); } @@ -85,9 +79,8 @@ function testAnnotationOnLocalRecordWithinLambdaFunction1() { string k = "chiranS"; function(string) func = function (string value) { record {@annot {value: value} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); }; func(k); } @@ -97,9 +90,8 @@ function testAnnotationOnLocalRecordWithinNestedLambdaFunctions() { function () returns function() var1 = function () returns function() { function() func = function () { record {@annot {value: k} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); }; return func; }; @@ -112,9 +104,8 @@ function testAnnotationOnLocalRecordWithinNestedLambdaFunctions1() { function (string) returns function() var1 = function (string val) returns function() { function() func = function () { record {@annot {value: val} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); }; return func; }; @@ -128,9 +119,8 @@ function testAnnotationOnLocalRecordWithinNestedLambdaFunctions2() { string name = "Name: "; function() func = function () { record {@annot {value: name + val} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); - assertEquality("{\"annot\":{\"value\":\"Name: chiranS\"}}", m.toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "Name: chiranS"}, >m["annot"]); }; return func; }; @@ -139,11 +129,12 @@ function testAnnotationOnLocalRecordWithinNestedLambdaFunctions2() { } function testMultipleAnnotationsOnLocaRecord() { - string k = "chiran"; + string k = "chiranS"; record {@annot {value: k} @annot1 {value: k} string x;} r = {x : ""}; - any m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality("typedesc map", (typeof m).toString()); + map m = getLocalRecordAnnotations(typeof r, "$field$.x"); + assertEquality({value: "chiranS"}, >m["annot"]); + assertEquality({value: "chiranS"}, >m["annot1"]); } function testLocalRecordAnnotations() { @@ -159,23 +150,17 @@ function testLocalRecordAnnotations() { testAnnotationOnLocalRecordWithMultipleFields(); } -function getLocalRecordAnnotations(typedesc obj, string annotName) returns any = +function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = @java:Method { - 'class: "org/ballerinalang/test/annotations/GetLocalRecordAnnotations", + 'class: "org/ballerinalang/test/annotations/LocalRecordAnnotationTest", name: "getLocalRecordAnnotations" } external; -function assertEquality(any|error expected, any|error actual) { - if expected is anydata && actual is anydata && expected == actual { - return; - } +function assertEquality(anydata expected, anydata actual) { - if expected === actual { + if expected == actual { return; } - string expectedValAsString = expected is error ? expected.toString() : expected.toString(); - string actualValAsString = actual is error ? actual.toString() : actual.toString(); - panic error("AssertionError", - message = "expected '" + expectedValAsString + "', found '" + actualValAsString + "'"); + panic error("AssertionError", message = "expected '" + expected.toString() + "', found '" + actual.toString() + "'"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal index 8eb3b382c830..6c9d5377c7c8 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal @@ -1,4 +1,5 @@ import testorg/foo; +import ballerina/jballerina.java; @foo:ConfigAnnotation { numVal: 10, @@ -27,6 +28,17 @@ function testAnnotOnBoundMethod() { assertEquality(102, rec.i); } +function testAnnotOnRecordFields() { + map m = getLocalRecordAnnotations(typeof foo:testAnnotationsOnLocalRecordFields(), "$field$.x"); + assertEquality({value : "10"} , >m["testorg/foo:1:annotOne"]); +} + +function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = +@java:Method { + 'class: "org/ballerinalang/test/annotations/GetLocalRecordAnnotations", + name: "getLocalRecordAnnotations" +} external; + function assertEquality(anydata expected, anydata actual) { if expected == actual { return; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal index ab78e1c88165..0d10ac16652c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal @@ -21,3 +21,14 @@ public class MyClass { @ObjMethodAnnot {i: 102} public function bar(int i) returns string => i.toString(); } + +type AnnotRecordOne record {| + string value; +|}; + +annotation AnnotRecordOne annotOne on type, field; + +public function testAnnotationsOnLocalRecordFields() returns record {string x; string y;} { + record {@annotOne {value: "10"} string x; string y;} r = {x : "", y: ""}; + return r; +} From 482b1601b83e5f4c69c58be822ec0e46f1d91b84 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:16:10 +0530 Subject: [PATCH 14/43] Add support for TupleValueImpl constructor, including TypedescValueImpl --- .../io/ballerina/runtime/internal/values/TupleValueImpl.java | 5 +++++ .../ballerina/runtime/internal/values/TypedescValueImpl.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 4db430b27195..5d5e1e293f8d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -200,6 +200,11 @@ public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues) { this.typedesc = getTypedescValue(type, this); } + public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues, TypedescValueImpl typedescValue) { + this(type, initialValues); + this.typedesc = typedescValue; + } + @Override public BTypedesc getTypedesc() { return typedesc; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 31e54a368f55..701d092d7427 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -100,7 +100,7 @@ public Object instantiate(Strand s, BInitialValueEntry[] initialValues) { if (referredType.getTag() == TypeTags.MAP_TAG) { return new MapValueImpl(this.describingType, (BMapInitialValueEntry[]) initialValues); } else if (referredType.getTag() == TypeTags.TUPLE_TAG) { - return new TupleValueImpl(this.describingType, (BListInitialValueEntry[]) initialValues); + return new TupleValueImpl(this.describingType, (BListInitialValueEntry[]) initialValues, this); } // This method will be overridden for user-defined types, therefor this line shouldn't be reached. throw new BallerinaException("Given type can't be instantiated at runtime : " + this.describingType); From 7b3fd03b6d56a20d0cc24c65706e1a4677108602 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:17:40 +0530 Subject: [PATCH 15/43] Add annotations field to BTypeSymbol --- .../compiler/semantics/model/symbols/BRecordTypeSymbol.java | 1 - .../compiler/semantics/model/symbols/BTypeSymbol.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java index 1dd92b1314e7..d0fb8ff8841a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BRecordTypeSymbol.java @@ -31,7 +31,6 @@ */ public class BRecordTypeSymbol extends BStructureTypeSymbol { - public BVarSymbol annotations; public BRecordTypeSymbol(int symTag, long flags, Name name, PackageID pkgID, BType type, BSymbol owner, Location pos, SymbolOrigin origin) { super(SymbolKind.RECORD, symTag, flags, name, pkgID, type, owner, pos, origin); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BTypeSymbol.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BTypeSymbol.java index 7989e49b2087..ba75e1a5d6a9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BTypeSymbol.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BTypeSymbol.java @@ -32,6 +32,7 @@ public class BTypeSymbol extends BSymbol implements TypeSymbol { public boolean isTypeParamResolved; public BTypeSymbol typeParamTSymbol; + public BVarSymbol annotations; public BTypeSymbol(int symTag, long flags, Name name, PackageID pkgID, BType type, BSymbol owner, Location pos, SymbolOrigin origin) { From 49c57727d2be663436c1436135119029fddc2303 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:18:24 +0530 Subject: [PATCH 16/43] Update class name --- .../test-src/bala/test_bala/annotations/annotation.bal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal index 6c9d5377c7c8..858ccb32db82 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal @@ -35,7 +35,7 @@ function testAnnotOnRecordFields() { function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = @java:Method { - 'class: "org/ballerinalang/test/annotations/GetLocalRecordAnnotations", + 'class: "org/ballerinalang/test/annotations/LocalRecordAnnotationTest", name: "getLocalRecordAnnotations" } external; From 788a8acf5bef2b83c45ca06a0f7f23faefdab718 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:21:54 +0530 Subject: [PATCH 17/43] Implement method to mark closure variables --- .../compiler/desugar/ClosureGenerator.java | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index e013b1daa71b..18b3379f812f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -907,23 +907,7 @@ public void visit(BLangSimpleVarRef varRefExpr) { result = varRefExpr; return; } - - BLangInvokableNode encInvokable = env.enclInvokable; - if ((varRefExpr.symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { - BVarSymbol varSymbol = (BVarSymbol) varRefExpr.symbol; - if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && - encInvokable.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); - BSymbol resolvedSymbol = - symResolver.lookupClosureVarSymbol(encInvokableEnv, varRefExpr.symbol.name, SymTag.VARIABLE); - if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { - varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, - varRefExpr.pos)); - } - } - } - + markClosureVariable(varRefSym, env, varRefSym.pos); result = varRefExpr; } @@ -1192,9 +1176,32 @@ public void visit(BLangWorkerFlushExpr workerFlushExpr) { @Override public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { + BSymbol symbol = localVarRef.symbol; + if (symbol == null) { + result = localVarRef; + return; + } + markClosureVariable(symbol, env, symbol.pos); result = localVarRef; } + private void markClosureVariable(BSymbol symbol, SymbolEnv env, Location pos) { + BLangInvokableNode encInvokable = env.enclInvokable; + if ((symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { + BVarSymbol varSymbol = (BVarSymbol) symbol; + if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && + encInvokable.flagSet.contains(Flag.LAMBDA)) { + SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); + BSymbol resolvedSymbol = + symResolver.lookupClosureVarSymbol(encInvokableEnv, symbol.name, SymTag.VARIABLE); + if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { + varSymbol.closure = true; + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, pos)); + } + } + } + } + @Override public void visit(BLangIgnoreExpr ignoreExpr) { result = ignoreExpr; From ecbcd6e10c1d67c7f078f59b2f4edd3b2c859730 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:32:53 +0530 Subject: [PATCH 18/43] Add support for defining field annotations in tuple types --- .../ballerinalang/compiler/bir/BIRGen.java | 24 ++++++++++++++++--- .../compiler/desugar/AnnotationDesugar.java | 13 ++++------ .../compiler/desugar/ClosureGenerator.java | 18 ++++++++++---- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index 508924ffbb1e..3c4ca5752230 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -1669,14 +1669,26 @@ public void visit(BLangSimpleVarRef.BLangFieldVarRef fieldVarRef) { public void visit(BLangArrayLiteral astArrayLiteralExpr) { BType bType = astArrayLiteralExpr.getBType(); if (bType.tag == TypeTags.TUPLE) { - visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList()); + BTypeSymbol typeSymbol = bType.tsymbol; + BIROperand anonMap = null; + if (typeSymbol != null && typeSymbol.annotations != null) { + BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + anonMap = new BIROperand(varDcl); + } + visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); } generateListConstructorExpr(astArrayLiteralExpr); } @Override public void visit(BLangTupleLiteral tupleLiteral) { - visitTypedesc(tupleLiteral.pos, tupleLiteral.getBType(), Collections.emptyList()); + BIROperand anonMap = null; + BTypeSymbol typeSymbol = tupleLiteral.getBType().tsymbol; + if (typeSymbol != null && typeSymbol.annotations != null) { + BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + anonMap = new BIROperand(varDcl); + } + visitTypedesc(tupleLiteral.pos, tupleLiteral.getBType(), Collections.emptyList(), anonMap); generateListConstructorExpr(tupleLiteral); } @@ -1689,7 +1701,13 @@ public void visit(BLangGroupExpr groupExpr) { public void visit(BLangJSONArrayLiteral jsonArrayLiteralExpr) { BType bType = jsonArrayLiteralExpr.getBType(); if (bType.tag == TypeTags.TUPLE) { - visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList()); + BIROperand anonMap = null; + BTypeSymbol typeSymbol = jsonArrayLiteralExpr.getBType().tsymbol; + if (typeSymbol != null && typeSymbol.annotations != null) { + BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + anonMap = new BIROperand(varDcl); + } + visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); } generateListConstructorExpr(jsonArrayLiteralExpr); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 5b9fd18fc920..54acc7f5ed7b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -81,7 +81,6 @@ import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; import org.wso2.ballerinalang.compiler.tree.types.BLangBuiltInRefTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangConstrainedType; -import org.wso2.ballerinalang.compiler.tree.types.BLangRecordTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangStructureTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangTupleTypeNode; import org.wso2.ballerinalang.compiler.tree.types.BLangType; @@ -630,18 +629,16 @@ private BLangLambdaFunction defineAnnotations(BLangTypeDefinition typeDef, BLang return addReturnAndDefineLambda(function, mapLiteral, pkgNode, env, pkgID, owner); } - - public BLangLambdaFunction defineAnnotationsForLocalRecords(BLangRecordTypeNode recordTypeNode, - BLangPackage pkgNode, SymbolEnv env, PackageID pkgID, - BSymbol owner) { + public BLangLambdaFunction defineFieldAnnotations(List fields, Location pos, + BLangPackage pkgNode, SymbolEnv env, PackageID pkgID, + BSymbol owner) { BLangFunction function = null; BLangRecordLiteral mapLiteral = null; BLangLambdaFunction lambdaFunction = null; boolean annotFunctionDefined = false; - for (BLangSimpleVariable field : recordTypeNode.fields) { - + for (BLangSimpleVariable field : fields) { BLangLambdaFunction fieldAnnotLambda = defineAnnotations(field.annAttachments, field.pos, pkgNode, env, pkgID, owner, false); if (fieldAnnotLambda != null) { @@ -649,7 +646,7 @@ public BLangLambdaFunction defineAnnotationsForLocalRecords(BLangRecordTypeNode closureGenerator.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); env.scope.define(invokableSymbol.name, invokableSymbol); if (!annotFunctionDefined) { - function = defineFunction(recordTypeNode.pos, pkgID, owner); + function = defineFunction(pos, pkgID, owner); mapLiteral = ASTBuilderUtil.createEmptyRecordLiteral(function.pos, symTable.mapType); annotFunctionDefined = true; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 18b3379f812f..3239511b2df5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -385,8 +385,8 @@ public void visit(BLangRecordTypeNode recordTypeNode) { BSymbol owner = recordTypeNode.symbol.owner; if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { - BLangLambdaFunction lambdaFunction = - annotationDesugar.defineAnnotationsForLocalRecords(recordTypeNode, env.enclPkg, env, pkgID, owner); + BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(recordTypeNode.fields, + recordTypeNode.pos, env.enclPkg, env, pkgID, owner); if (lambdaFunction != null) { BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = @@ -402,6 +402,17 @@ public void visit(BLangRecordTypeNode recordTypeNode) { @Override public void visit(BLangTupleTypeNode tupleTypeNode) { + PackageID pkgID = tupleTypeNode.getBType().tsymbol.pkgID; + BSymbol owner = tupleTypeNode.getBType().tsymbol.owner; + + if (owner.getKind() != SymbolKind.PACKAGE) { + BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(tupleTypeNode.memberTypeNodes, + tupleTypeNode.pos, env.enclPkg, env, pkgID, owner); + if (lambdaFunction != null) { + BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); + tupleTypeNode.getBType().tsymbol.annotations = createSimpleVariable(invokableSymbol); + } + } List rewrittenMembers = new ArrayList<>(); tupleTypeNode.memberTypeNodes.forEach(member -> rewrittenMembers.add(rewrite(member, env))); tupleTypeNode.memberTypeNodes = rewrittenMembers; @@ -903,7 +914,7 @@ public void visit(BLangSimpleVarRef varRefExpr) { updateFunctionParamsOfClosures(env, varRefExpr); } } - if (varRefExpr.symbol == null) { + if (varRefSym == null) { result = varRefExpr; return; } @@ -1621,7 +1632,6 @@ private List rewriteStmt(List nodeList, SymbolE @SuppressWarnings("unchecked") private List rewriteExprs(List nodeList) { for (int i = 0; i < nodeList.size(); i++) { - rewriteExpr(nodeList.get(i)); nodeList.set(i, rewriteExpr(nodeList.get(i))); } return nodeList; From 30617b3ea064f29f525a967350c71961abf817ba Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Thu, 12 Jan 2023 12:50:07 +0530 Subject: [PATCH 19/43] Add test cases for local tuple annotations --- .../annotations/LocalTupleAnnotationTest.java | 63 ++++++++++++++ .../local_tuple_annotation_test.bal | 82 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java new file mode 100644 index 000000000000..0930ce7b8657 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you 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. + */ +package org.ballerinalang.test.annotations; + +import io.ballerina.runtime.api.values.BMap; +import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.internal.TypeChecker; +import io.ballerina.runtime.internal.values.TypedescValue; +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * Class to test annotation evaluation within local tuple types. + * + * @since 2201.4.0 + */ +public class LocalTupleAnnotationTest { + private CompileResult result; + + @BeforeClass + public void setup() { + result = BCompileUtil.compile("test-src/annotations/local_tuple_annotation_test.bal"); + Assert.assertEquals(result.getErrorCount(), 0); + } + + @Test(dataProvider = "dataToTestAnnotationsOfLocalTuple") + public void testLocalRecordAnnotations(String function) { + BRunUtil.invoke(result, function); + } + + @DataProvider(name = "dataToTestAnnotationsOfLocalTuple") + public Object[] dataToTestAnnotationsOfLocalTuple() { + return new String[]{ + "testAnnotationOnTupleFields", + "testAnnotationOnTupleFields2", + "testAnnotationOnTupleWithGlobalVariable", + "testMultipleAnnotationsOnLocalTuple" + }; + } + + public static BMap getLocalTupleAnnotations(TypedescValue typedescValue, BString annotName) { + return (BMap) TypeChecker.getAnnotValue(typedescValue, annotName); + } +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal new file mode 100644 index 000000000000..ac5775254bd0 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal @@ -0,0 +1,82 @@ +// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// +// WSO2 Inc. licenses this file to you 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. + +import ballerina/jballerina.java; + +type AnnotTupleOne record {| + string value; +|}; + +type Details record {| + string name; + int age; +|}; + +annotation AnnotTupleOne annotOne on type, field; +annotation AnnotTupleOne annotTwo on type, field; +annotation Details details on field; + +function testAnnotationOnTupleFields() { + string k = "chiranS"; + [@annotOne {value: "10"} int, @annotOne {value: k} int, string...] x1 = [1, 2, "hello", "world"]; + map m1 = getLocalTupleAnnotations(typeof x1, "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof x1, "$field$.1"); + assertEquality({value: "10"}, >m1["annotOne"]); + assertEquality({value: "chiranS"}, >m2["annotOne"]); +} + +function testAnnotationOnTupleFields2() { + string name = "chiranS"; + int age = 26; + [@details {name: name, age: age} int, @details {name: "name", age: 0} int, string...] x1 = [1, 2, "hello", "world"]; + map m1 = getLocalTupleAnnotations(typeof x1, "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof x1, "$field$.1"); + assertEquality({name: "chiranS", age: 26}, >m1["details"]); + assertEquality({name: "name", age: 0}, >m2["details"]); +} + +string gVar = "foo"; + +function testAnnotationOnTupleWithGlobalVariable() { + [@annotOne {value: gVar} int, int, string...] x1 = [1, 2, "hello", "world"]; + map m = getLocalTupleAnnotations(typeof x1, "$field$.0"); + assertEquality({value: "foo"}, >m["annotOne"]); +} + +function testMultipleAnnotationsOnLocalTuple() { + string k = "chiranS"; + [@annotOne {value: "foo"} @annotTwo {value: "bar"} int, @details {name: k, age: 0} int, string...] x1 = [1, 2, "hello", "world"]; + map m1 = getLocalTupleAnnotations(typeof x1, "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof x1, "$field$.1"); + assertEquality({value: "foo"}, >m1["annotOne"]); + assertEquality({value: "bar"}, >m1["annotTwo"]); + assertEquality({name: "chiranS", age: 0}, >m2["details"]); +} + +function getLocalTupleAnnotations(typedesc obj, string annotName) returns map = +@java:Method { + 'class: "org/ballerinalang/test/annotations/LocalTupleAnnotationTest", + name: "getLocalTupleAnnotations" +} external; + +function assertEquality(anydata expected, anydata actual) { + + if expected == actual { + return; + } + + panic error("AssertionError", message = "expected '" + expected.toString() + "', found '" + actual.toString() + "'"); +} From 3bcf5c20ac1c8d97dc425bc9cd84ea0cefcc1d38 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Fri, 13 Jan 2023 00:47:47 +0530 Subject: [PATCH 20/43] Support field annotation on function return type and parameters --- .../ballerinalang/compiler/bir/BIRGen.java | 16 +++++++++---- .../compiler/desugar/ClosureGenerator.java | 24 +++++++++---------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index 3c4ca5752230..d367d7374c19 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -1601,7 +1601,7 @@ public void visit(BLangStructLiteral astStructLiteralExpr) { if (astStructLiteralExpr.getBType().getKind() == TypeKind.RECORD) { BRecordTypeSymbol typeSymbol = (BRecordTypeSymbol) astStructLiteralExpr.getBType().tsymbol; if (typeSymbol.annotations != null) { - BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); anonMap = new BIROperand(varDcl); } } @@ -1672,7 +1672,7 @@ public void visit(BLangArrayLiteral astArrayLiteralExpr) { BTypeSymbol typeSymbol = bType.tsymbol; BIROperand anonMap = null; if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); anonMap = new BIROperand(varDcl); } visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); @@ -1685,13 +1685,21 @@ public void visit(BLangTupleLiteral tupleLiteral) { BIROperand anonMap = null; BTypeSymbol typeSymbol = tupleLiteral.getBType().tsymbol; if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); anonMap = new BIROperand(varDcl); } visitTypedesc(tupleLiteral.pos, tupleLiteral.getBType(), Collections.emptyList(), anonMap); generateListConstructorExpr(tupleLiteral); } + private BIRVariableDcl getAnnotations(BVarSymbol annotations, BIRGenEnv env) { + if (env.symbolVarMap.containsKey(annotations)) { + return env.symbolVarMap.get(annotations); + } else { + return globalVarMap.get(annotations); + } + } + @Override public void visit(BLangGroupExpr groupExpr) { groupExpr.expression.accept(this); @@ -1704,7 +1712,7 @@ public void visit(BLangJSONArrayLiteral jsonArrayLiteralExpr) { BIROperand anonMap = null; BTypeSymbol typeSymbol = jsonArrayLiteralExpr.getBType().tsymbol; if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = this.env.symbolVarMap.get(typeSymbol.annotations); + BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); anonMap = new BIROperand(varDcl); } visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 3239511b2df5..df63ad7478f1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -256,7 +256,7 @@ private void addClosuresToGlobalVariableList(SymbolEnv pkgEnv) { BLangSimpleVariable simpleVariable = queue.poll().var; simpleVariable.flagSet.add(Flag.PUBLIC); simpleVariable.symbol.flags |= Flags.PUBLIC; - pkgEnv.enclPkg.globalVars.add(0, rewrite(simpleVariable, pkgEnv)); + pkgEnv.enclPkg.globalVars.add(rewrite(simpleVariable, pkgEnv)); } } @@ -402,10 +402,10 @@ public void visit(BLangRecordTypeNode recordTypeNode) { @Override public void visit(BLangTupleTypeNode tupleTypeNode) { - PackageID pkgID = tupleTypeNode.getBType().tsymbol.pkgID; BSymbol owner = tupleTypeNode.getBType().tsymbol.owner; - if (owner.getKind() != SymbolKind.PACKAGE) { + PackageID pkgID = tupleTypeNode.getBType().tsymbol.pkgID; + owner = getOwner(env); BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(tupleTypeNode.memberTypeNodes, tupleTypeNode.pos, env.enclPkg, env, pkgID, owner); if (lambdaFunction != null) { @@ -918,8 +918,7 @@ public void visit(BLangSimpleVarRef varRefExpr) { result = varRefExpr; return; } - markClosureVariable(varRefSym, env, varRefSym.pos); - result = varRefExpr; + result = markClosureVariable(varRefExpr, env); } private void updateFunctionParamsOfClosures(SymbolEnv symbolEnv, BLangSimpleVarRef varRefExpr) { @@ -1192,25 +1191,26 @@ public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { result = localVarRef; return; } - markClosureVariable(symbol, env, symbol.pos); - result = localVarRef; + result = markClosureVariable(localVarRef, env); } - private void markClosureVariable(BSymbol symbol, SymbolEnv env, Location pos) { + private BLangSimpleVarRef markClosureVariable(BLangSimpleVarRef varRefExpr, SymbolEnv env) { BLangInvokableNode encInvokable = env.enclInvokable; - if ((symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { - BVarSymbol varSymbol = (BVarSymbol) symbol; + if ((varRefExpr.symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { + BVarSymbol varSymbol = (BVarSymbol) varRefExpr.symbol; if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && encInvokable.flagSet.contains(Flag.LAMBDA)) { SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); BSymbol resolvedSymbol = - symResolver.lookupClosureVarSymbol(encInvokableEnv, symbol.name, SymTag.VARIABLE); + symResolver.lookupClosureVarSymbol(encInvokableEnv, varRefExpr.symbol.name, SymTag.VARIABLE); if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, pos)); + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, + varRefExpr.pos)); } } } + return varRefExpr; } @Override From c3b7bc1633fd4e585eabe57ac4b70618e6f43025 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Fri, 13 Jan 2023 00:49:03 +0530 Subject: [PATCH 21/43] Add test cases for local tuple annotations --- .../annotations/LocalTupleAnnotationTest.java | 5 +- .../local_tuple_annotation_test.bal | 67 +++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java index 0930ce7b8657..8a351e0e8c79 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java @@ -53,7 +53,10 @@ public Object[] dataToTestAnnotationsOfLocalTuple() { "testAnnotationOnTupleFields", "testAnnotationOnTupleFields2", "testAnnotationOnTupleWithGlobalVariable", - "testMultipleAnnotationsOnLocalTuple" + "testMultipleAnnotationsOnLocalTuple", + "testGlobalAnnotationsOnFunctionPointerReturnType", + "testGlobalAnnotationsOnFunctionReturnType", + "testGlobalAnnotationsOnFunctionParameterType" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal index ac5775254bd0..6d616fadf432 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal @@ -49,6 +49,7 @@ function testAnnotationOnTupleFields2() { } string gVar = "foo"; +string gVar1 = "bar"; function testAnnotationOnTupleWithGlobalVariable() { [@annotOne {value: gVar} int, int, string...] x1 = [1, 2, "hello", "world"]; @@ -66,6 +67,72 @@ function testMultipleAnnotationsOnLocalTuple() { assertEquality({name: "chiranS", age: 0}, >m2["details"]); } +function() returns [int] x = function() returns [@annotOne {value: "foo"} int] {return [1];}; +function() returns [int] x2 = function() returns [@annotOne {value: gVar1} @annotTwo {value: gVar2} int] {return [1];}; +function() returns [int, int] x3 = function() returns [@annotOne {value: gVar1} int, @details {name: "name", age: gVar3} int] {return [1, 1];}; + +function testGlobalAnnotationsOnFunctionPointerReturnType() { + map m1 = getLocalTupleAnnotations(typeof x(), "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof x2(), "$field$.0"); + map m3 = getLocalTupleAnnotations(typeof x3(), "$field$.0"); + map m4 = getLocalTupleAnnotations(typeof x3(), "$field$.1"); + assertEquality({value: "foo"}, >m1["annotOne"]); + assertEquality({value: "bar"}, >m2["annotOne"]); + assertEquality({value: "baz"}, >m2["annotTwo"]); + assertEquality({value: "bar"}, >m3["annotOne"]); + assertEquality({name: "name", age: 10}, >m4["details"]); +} + +string gVar2 = "baz"; +int gVar3 = 10; + +function func() returns [@annotOne {value: "foo"} int] { + return [1]; +} + +function func1() returns [@annotOne {value: "foo"} @annotTwo {value: gVar2} int] { + return [1]; +} + +function func2() returns [@details {name: "name", age: gVar4} int, @annotTwo {value: gVar2} int] { + return [1, 1]; +} + +function testGlobalAnnotationsOnFunctionReturnType() { + map m1 = getLocalTupleAnnotations(typeof func(), "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof func1(), "$field$.0"); + map m3 = getLocalTupleAnnotations(typeof func2(), "$field$.0"); + map m4 = getLocalTupleAnnotations(typeof func2(), "$field$.1"); + assertEquality({value: "foo"}, >m1["annotOne"]); + assertEquality({value: "foo"}, >m2["annotOne"]); + assertEquality({value: "baz"}, >m2["annotTwo"]); + assertEquality({value: "baz"}, >m2["annotTwo"]); + assertEquality({value: "baz"}, >m2["annotTwo"]); + assertEquality({name: "name", age: 15}, >m3["details"]); + assertEquality({value: "baz"}, >m4["annotTwo"]); +} + +int gVar4 = 15; + +function func3([@annotOne {value: "foo"} int] a) { + map m1 = getLocalTupleAnnotations(typeof a, "$field$.0"); + assertEquality({value: "foo"}, >m1["annotOne"]); +} + +function func4([@annotOne {value: "foo"} int, @annotTwo {value: "foo"} @details {name: "name", age: gVar4} int] a) { + map m1 = getLocalTupleAnnotations(typeof a, "$field$.0"); + map m2 = getLocalTupleAnnotations(typeof a, "$field$.1"); + + assertEquality({value: "foo"}, >m1["annotOne"]); + assertEquality({value: "foo"}, >m2["annotTwo"]); + assertEquality({name: "name", age: 15}, >m2["details"]); +} + +function testGlobalAnnotationsOnFunctionParameterType() { + func3([10]); + func4([10, 10]); +} + function getLocalTupleAnnotations(typedesc obj, string annotName) returns map = @java:Method { 'class: "org/ballerinalang/test/annotations/LocalTupleAnnotationTest", From b619783fe064c4c9c923c834394eb508d0cb60ea Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 17 Jan 2023 20:29:23 +0530 Subject: [PATCH 22/43] Add method for providing typedesc value based on value immutability --- .../io/ballerina/runtime/internal/ValueUtils.java | 15 +++++++++++++++ .../runtime/internal/values/TupleValueImpl.java | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java index a97f599035a3..e26a45442dd1 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java @@ -241,4 +241,19 @@ public static BTypedesc getTypedescValue(Type type, BValue value) { return new TypedescValueImpl(type); } + /** + * Provide the Typedesc Value depending on the immutability of a value. + * @param isReadOnly Indicates that the type is a read-only + * @param value Ballerina value + * @param typedescValue typedesc value + * @return typedesc with the suitable type + */ + public static BTypedesc getTypedescValue(Boolean isReadOnly, BValue value, TypedescValueImpl typedescValue) { + if (isReadOnly) { + TypedescValueImpl typedesc = (TypedescValueImpl) createSingletonTypedesc(value); + typedesc.annotations = typedescValue.annotations; + return typedesc; + } + return typedescValue; + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 5d5e1e293f8d..9e79c1d5e11d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -202,7 +202,7 @@ public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues) { public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues, TypedescValueImpl typedescValue) { this(type, initialValues); - this.typedesc = typedescValue; + this.typedesc = getTypedescValue(type.isReadOnly(), this, typedescValue); } @Override From 604f11887cffa47b618c5cd10356559fa8465717 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 17 Jan 2023 20:41:05 +0530 Subject: [PATCH 23/43] Add a new list to keep references for package-level closures --- .../compiler/desugar/AnnotationDesugar.java | 3 +- .../compiler/desugar/ClosureGenerator.java | 43 +++++++++++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 54acc7f5ed7b..dcb202c67efd 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -643,7 +643,8 @@ public BLangLambdaFunction defineFieldAnnotations(List fiel pkgID, owner, false); if (fieldAnnotLambda != null) { BInvokableSymbol invokableSymbol = - closureGenerator.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda); + closureGenerator.createSimpleVariable(fieldAnnotLambda.function, fieldAnnotLambda, + owner.getKind() == SymbolKind.PACKAGE); env.scope.define(invokableSymbol.name, invokableSymbol); if (!annotFunctionDefined) { function = defineFunction(pos, pkgID, owner); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index df63ad7478f1..3f32582b34ee 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -196,7 +196,7 @@ public class ClosureGenerator extends BLangNodeVisitor { private static final CompilerContext.Key CLOSURE_GENERATOR_KEY = new CompilerContext.Key<>(); private Queue queue; - + private List annotationClosureReferences; private SymbolTable symTable; private SymbolEnv env; private BLangNode result; @@ -216,6 +216,7 @@ private ClosureGenerator(CompilerContext context) { context.put(CLOSURE_GENERATOR_KEY, this); this.symTable = SymbolTable.getInstance(context); this.queue = new LinkedList<>(); + this.annotationClosureReferences = new ArrayList<>(); this.symResolver = SymbolResolver.getInstance(context); this.annotationDesugar = AnnotationDesugar.getInstance(context); } @@ -256,7 +257,10 @@ private void addClosuresToGlobalVariableList(SymbolEnv pkgEnv) { BLangSimpleVariable simpleVariable = queue.poll().var; simpleVariable.flagSet.add(Flag.PUBLIC); simpleVariable.symbol.flags |= Flags.PUBLIC; - pkgEnv.enclPkg.globalVars.add(rewrite(simpleVariable, pkgEnv)); + pkgEnv.enclPkg.globalVars.add(0, rewrite(simpleVariable, pkgEnv)); + } + for (BLangSimpleVariableDef closureReference : annotationClosureReferences) { + pkgEnv.enclPkg.globalVars.add(rewrite(closureReference.var, pkgEnv)); } } @@ -381,16 +385,18 @@ public void visit(BLangObjectConstructorExpression objectConstructorExpression) @Override public void visit(BLangRecordTypeNode recordTypeNode) { - PackageID pkgID = recordTypeNode.symbol.pkgID; BSymbol owner = recordTypeNode.symbol.owner; - - if (recordTypeNode.isAnonymous && recordTypeNode.isLocal) { + if (owner.getKind() != SymbolKind.PACKAGE) { + owner = getOwner(env); + PackageID pkgID = recordTypeNode.symbol.pkgID; BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(recordTypeNode.fields, recordTypeNode.pos, env.enclPkg, env, pkgID, owner); if (lambdaFunction != null) { - BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); + boolean isPackageLevel = owner.getKind() == SymbolKind.PACKAGE; + BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction, + isPackageLevel); ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = - createSimpleVariable(invokableSymbol); + createSimpleVariable(invokableSymbol, isPackageLevel); } } for (BLangSimpleVariable field : recordTypeNode.fields) { @@ -409,8 +415,10 @@ public void visit(BLangTupleTypeNode tupleTypeNode) { BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(tupleTypeNode.memberTypeNodes, tupleTypeNode.pos, env.enclPkg, env, pkgID, owner); if (lambdaFunction != null) { - BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction); - tupleTypeNode.getBType().tsymbol.annotations = createSimpleVariable(invokableSymbol); + boolean isPackageLevel = owner.getKind() == SymbolKind.PACKAGE; + BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction, + isPackageLevel); + tupleTypeNode.getBType().tsymbol.annotations = createSimpleVariable(invokableSymbol, isPackageLevel); } } List rewrittenMembers = new ArrayList<>(); @@ -546,7 +554,7 @@ private BLangExpression createClosureForDefaultValue(String closureName, String returnStmt.expr = varNode.expr; BLangLambdaFunction lambdaFunction = createLambdaFunction(function); lambdaFunction.capturedClosureEnv = env.createClone(); - BInvokableSymbol varSymbol = createSimpleVariable(function, lambdaFunction); + BInvokableSymbol varSymbol = createSimpleVariable(function, lambdaFunction, false); env.enclPkg.symbol.scope.define(function.symbol.name, function.symbol); env.enclPkg.functions.add(function); env.enclPkg.topLevelNodes.add(function); @@ -581,7 +589,8 @@ BLangLambdaFunction createLambdaFunction(BLangFunction function) { return lambdaFunction; } - public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction) { + public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambdaFunction lambdaFunction, + boolean isAnnotationClosure) { BInvokableSymbol invokableSymbol = function.symbol; BType type = function.getBType(); BInvokableSymbol varSymbol = new BInvokableSymbol(SymTag.VARIABLE, 0, invokableSymbol.name, @@ -595,12 +604,15 @@ public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambda BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(function.pos); variableDef.var = simpleVariable; variableDef.setBType(type); + if (isAnnotationClosure) { + annotationClosureReferences.add(variableDef); + return varSymbol; + } queue.add(variableDef); - return varSymbol; } - public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol) { + public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol, boolean isAnnotationClosure) { BType type = invokableSymbol.retType; BVarSymbol varSymbol = new BVarSymbol(0, invokableSymbol.name, invokableSymbol.originalName, invokableSymbol.pkgID, type, invokableSymbol.owner, invokableSymbol.pos, @@ -610,8 +622,11 @@ public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol) { BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(invokableSymbol.pos); variableDef.var = simpleVariable; variableDef.setBType(type); + if (isAnnotationClosure) { + annotationClosureReferences.add(variableDef); + return varSymbol; + } queue.add(variableDef); - return varSymbol; } From 144b904e84600f24b7ae67a210961c52ff6fc8b9 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 11:21:31 +0530 Subject: [PATCH 24/43] Fix review suggestions --- .../io/ballerina/runtime/internal/ValueUtils.java | 12 ++++++------ .../runtime/internal/values/TupleValueImpl.java | 4 ++-- .../runtime/internal/values/TypedescValueImpl.java | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java index e26a45442dd1..0adf6f41c8d1 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ValueUtils.java @@ -243,17 +243,17 @@ public static BTypedesc getTypedescValue(Type type, BValue value) { /** * Provide the Typedesc Value depending on the immutability of a value. - * @param isReadOnly Indicates that the type is a read-only + * @param readOnly Indicates that the type is a subtype of readonly * @param value Ballerina value - * @param typedescValue typedesc value + * @param inherentType Inherent type of the value * @return typedesc with the suitable type */ - public static BTypedesc getTypedescValue(Boolean isReadOnly, BValue value, TypedescValueImpl typedescValue) { - if (isReadOnly) { + public static BTypedesc getTypedescValue(Boolean readOnly, BValue value, TypedescValueImpl inherentType) { + if (readOnly) { TypedescValueImpl typedesc = (TypedescValueImpl) createSingletonTypedesc(value); - typedesc.annotations = typedescValue.annotations; + typedesc.annotations = inherentType.annotations; return typedesc; } - return typedescValue; + return inherentType; } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 9e79c1d5e11d..00a992d8270f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -200,9 +200,9 @@ public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues) { this.typedesc = getTypedescValue(type, this); } - public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues, TypedescValueImpl typedescValue) { + public TupleValueImpl(Type type, BListInitialValueEntry[] initialValues, TypedescValueImpl inherentType) { this(type, initialValues); - this.typedesc = getTypedescValue(type.isReadOnly(), this, typedescValue); + this.typedesc = getTypedescValue(type.isReadOnly(), this, inherentType); } @Override diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 701d092d7427..54e64fdcd876 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -90,6 +90,7 @@ public Object instantiate(Strand s) { return instantiate(s, new BInitialValueEntry[0]); } + @Override public MapValue getAnnotations() { return annotations; } From f00c676c52f0658d47a108da426d9036a26a3534 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 11:29:09 +0530 Subject: [PATCH 25/43] Refactor `getAnnotations` function --- .../ballerinalang/compiler/bir/BIRGen.java | 71 +++++++------------ 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index d367d7374c19..d0c8941d4fb4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -31,7 +31,6 @@ import org.ballerinalang.model.tree.OperatorKind; import org.ballerinalang.model.tree.TopLevelNode; import org.ballerinalang.model.tree.expressions.RecordLiteralNode; -import org.ballerinalang.model.types.TypeKind; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRAnnotation; import org.wso2.ballerinalang.compiler.bir.model.BIRNode.BIRAnnotationAttachment; @@ -68,7 +67,6 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BObjectTypeSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BResourceFunction; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BServiceSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; @@ -1566,7 +1564,7 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { - visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); + visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList(), null); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1597,16 +1595,8 @@ public void visit(BLangTypeConversionExpr astTypeConversionExpr) { @Override public void visit(BLangStructLiteral astStructLiteralExpr) { List varDcls = mapToVarDcls(astStructLiteralExpr.enclMapSymbols); - BIROperand anonMap = null; - if (astStructLiteralExpr.getBType().getKind() == TypeKind.RECORD) { - BRecordTypeSymbol typeSymbol = (BRecordTypeSymbol) astStructLiteralExpr.getBType().tsymbol; - if (typeSymbol.annotations != null) { - BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); - anonMap = new BIROperand(varDcl); - } - } - visitTypedesc(astStructLiteralExpr.pos, astStructLiteralExpr.getBType(), varDcls, anonMap); - + BType type = astStructLiteralExpr.getBType(); + visitTypedesc(astStructLiteralExpr.pos, type, varDcls, getAnnotations(type.tsymbol, this.env)); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astStructLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1669,35 +1659,31 @@ public void visit(BLangSimpleVarRef.BLangFieldVarRef fieldVarRef) { public void visit(BLangArrayLiteral astArrayLiteralExpr) { BType bType = astArrayLiteralExpr.getBType(); if (bType.tag == TypeTags.TUPLE) { - BTypeSymbol typeSymbol = bType.tsymbol; - BIROperand anonMap = null; - if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); - anonMap = new BIROperand(varDcl); - } - visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); + visitTypedesc(astArrayLiteralExpr.pos, bType, Collections.emptyList(), + getAnnotations(bType.tsymbol, this.env)); } generateListConstructorExpr(astArrayLiteralExpr); } @Override public void visit(BLangTupleLiteral tupleLiteral) { - BIROperand anonMap = null; - BTypeSymbol typeSymbol = tupleLiteral.getBType().tsymbol; - if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); - anonMap = new BIROperand(varDcl); - } - visitTypedesc(tupleLiteral.pos, tupleLiteral.getBType(), Collections.emptyList(), anonMap); + BType type = tupleLiteral.getBType(); + visitTypedesc(tupleLiteral.pos, type, Collections.emptyList(), getAnnotations(type.tsymbol, this.env)); generateListConstructorExpr(tupleLiteral); } + private BIROperand getAnnotations(BTypeSymbol typeSymbol, BIRGenEnv env) { + if (typeSymbol == null || typeSymbol.annotations == null) { + return null; + } + return new BIROperand(getAnnotations(typeSymbol.annotations, env)); + } + private BIRVariableDcl getAnnotations(BVarSymbol annotations, BIRGenEnv env) { if (env.symbolVarMap.containsKey(annotations)) { return env.symbolVarMap.get(annotations); - } else { - return globalVarMap.get(annotations); } + return globalVarMap.get(annotations); } @Override @@ -1709,13 +1695,8 @@ public void visit(BLangGroupExpr groupExpr) { public void visit(BLangJSONArrayLiteral jsonArrayLiteralExpr) { BType bType = jsonArrayLiteralExpr.getBType(); if (bType.tag == TypeTags.TUPLE) { - BIROperand anonMap = null; - BTypeSymbol typeSymbol = jsonArrayLiteralExpr.getBType().tsymbol; - if (typeSymbol != null && typeSymbol.annotations != null) { - BIRVariableDcl varDcl = getAnnotations(typeSymbol.annotations, this.env); - anonMap = new BIROperand(varDcl); - } - visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList(), anonMap); + visitTypedesc(jsonArrayLiteralExpr.pos, bType, Collections.emptyList(), + getAnnotations(bType.tsymbol, this.env)); } generateListConstructorExpr(jsonArrayLiteralExpr); } @@ -1999,7 +1980,7 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { - visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); + visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList(), null); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId(names)); addToTrapStack(thenBB); BIRVariableDcl tempVarDcl = new BIRVariableDcl(waitLiteral.getBType(), @@ -2269,7 +2250,7 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { BType type = typeLoad.symbol.tag == SymTag.TYPE_DEF ? ((BTypeDefinitionSymbol) typeLoad.symbol).referenceType : typeLoad.symbol.type; - visitTypedesc(typeLoad.pos, type, Collections.emptyList()); + visitTypedesc(typeLoad.pos, type, Collections.emptyList(), null); } private void visitTypedesc(Location pos, BType type, List varDcls, BIROperand annotations) { @@ -2277,15 +2258,11 @@ private void visitTypedesc(Location pos, BType type, List varDcls, B VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand toVarRef = new BIROperand(tempVarDcl); - setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls, annotations)); - this.env.targetOperand = toVarRef; - } - - private void visitTypedesc(Location pos, BType type, List varDcls) { - BIRVariableDcl tempVarDcl = new BIRVariableDcl(symTable.typeDesc, this.env.nextLocalVarId(names), - VarScope.FUNCTION, VarKind.TEMP); - this.env.enclFunc.localVars.add(tempVarDcl); - BIROperand toVarRef = new BIROperand(tempVarDcl); + if (annotations != null) { + setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls, annotations)); + this.env.targetOperand = toVarRef; + return; + } setScopeAndEmit(new BIRNonTerminator.NewTypeDesc(pos, toVarRef, type, varDcls)); this.env.targetOperand = toVarRef; } From 84b1b8bbdd67210fa307a254855b4a28481b6018 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 11:33:52 +0530 Subject: [PATCH 26/43] Desugar field annotations --- .../compiler/desugar/ClosureGenerator.java | 123 ++++++++---------- 1 file changed, 54 insertions(+), 69 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 3f32582b34ee..485b3099d06f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -30,8 +30,8 @@ import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableTypeSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BRecordTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.SymTag; import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; @@ -183,6 +183,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Queue; +import java.util.Set; import static io.ballerina.runtime.api.constants.RuntimeConstants.DOLLAR; import static io.ballerina.runtime.api.constants.RuntimeConstants.UNDERSCORE; @@ -385,20 +386,9 @@ public void visit(BLangObjectConstructorExpression objectConstructorExpression) @Override public void visit(BLangRecordTypeNode recordTypeNode) { - BSymbol owner = recordTypeNode.symbol.owner; - if (owner.getKind() != SymbolKind.PACKAGE) { - owner = getOwner(env); - PackageID pkgID = recordTypeNode.symbol.pkgID; - BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(recordTypeNode.fields, - recordTypeNode.pos, env.enclPkg, env, pkgID, owner); - if (lambdaFunction != null) { - boolean isPackageLevel = owner.getKind() == SymbolKind.PACKAGE; - BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction, - isPackageLevel); - ((BRecordTypeSymbol) recordTypeNode.getBType().tsymbol).annotations = - createSimpleVariable(invokableSymbol, isPackageLevel); - } - } + BTypeSymbol typeSymbol = recordTypeNode.getBType().tsymbol; + BSymbol owner = typeSymbol.owner; + desugarFieldAnnotations(owner, typeSymbol, recordTypeNode.fields, recordTypeNode.pos); for (BLangSimpleVariable field : recordTypeNode.fields) { rewrite(field, env); } @@ -408,24 +398,29 @@ public void visit(BLangRecordTypeNode recordTypeNode) { @Override public void visit(BLangTupleTypeNode tupleTypeNode) { - BSymbol owner = tupleTypeNode.getBType().tsymbol.owner; + BTypeSymbol typeSymbol = tupleTypeNode.getBType().tsymbol; + BSymbol owner = typeSymbol.owner; + desugarFieldAnnotations(owner, typeSymbol, tupleTypeNode.memberTypeNodes, tupleTypeNode.pos); + List rewrittenMembers = new ArrayList<>(); + tupleTypeNode.memberTypeNodes.forEach(member -> rewrittenMembers.add(rewrite(member, env))); + tupleTypeNode.memberTypeNodes = rewrittenMembers; + tupleTypeNode.restParamType = rewrite(tupleTypeNode.restParamType, env); + result = tupleTypeNode; + } + + private void desugarFieldAnnotations(BSymbol owner, BTypeSymbol typeSymbol, List fields, + Location pos) { if (owner.getKind() != SymbolKind.PACKAGE) { - PackageID pkgID = tupleTypeNode.getBType().tsymbol.pkgID; owner = getOwner(env); - BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(tupleTypeNode.memberTypeNodes, - tupleTypeNode.pos, env.enclPkg, env, pkgID, owner); + BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(fields, pos, env.enclPkg, env, + typeSymbol.pkgID, owner); if (lambdaFunction != null) { boolean isPackageLevel = owner.getKind() == SymbolKind.PACKAGE; BInvokableSymbol invokableSymbol = createSimpleVariable(lambdaFunction.function, lambdaFunction, isPackageLevel); - tupleTypeNode.getBType().tsymbol.annotations = createSimpleVariable(invokableSymbol, isPackageLevel); + typeSymbol.annotations = createSimpleVariable(invokableSymbol, isPackageLevel); } } - List rewrittenMembers = new ArrayList<>(); - tupleTypeNode.memberTypeNodes.forEach(member -> rewrittenMembers.add(rewrite(member, env))); - tupleTypeNode.memberTypeNodes = rewrittenMembers; - tupleTypeNode.restParamType = rewrite(tupleTypeNode.restParamType, env); - result = tupleTypeNode; } @Override @@ -614,12 +609,13 @@ public BInvokableSymbol createSimpleVariable(BLangFunction function, BLangLambda public BVarSymbol createSimpleVariable(BInvokableSymbol invokableSymbol, boolean isAnnotationClosure) { BType type = invokableSymbol.retType; - BVarSymbol varSymbol = new BVarSymbol(0, invokableSymbol.name, invokableSymbol.originalName, - invokableSymbol.pkgID, type, invokableSymbol.owner, invokableSymbol.pos, - VIRTUAL); - BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(invokableSymbol.pos, - invokableSymbol.name.value, type, getInvocation(invokableSymbol), varSymbol); - BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(invokableSymbol.pos); + Location pos = invokableSymbol.pos; + Name name = invokableSymbol.name; + BVarSymbol varSymbol = new BVarSymbol(0, name, invokableSymbol.originalName, invokableSymbol.pkgID, type, + invokableSymbol.owner, pos, VIRTUAL); + BLangSimpleVariable simpleVariable = ASTBuilderUtil.createVariable(pos, name.value, type, + getInvocation(invokableSymbol), varSymbol); + BLangSimpleVariableDef variableDef = ASTBuilderUtil.createVariableDef(pos); variableDef.var = simpleVariable; variableDef.setBType(type); if (isAnnotationClosure) { @@ -911,7 +907,7 @@ public void visit(BLangRecordLiteral recordLiteral) { for (RecordLiteralNode.RecordField field : recordLiteral.fields) { if (field.isKeyValueField()) { BLangRecordLiteral.BLangRecordKeyValueField keyValueField = - (BLangRecordLiteral.BLangRecordKeyValueField) field; + (BLangRecordLiteral.BLangRecordKeyValueField) field; keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); } @@ -929,11 +925,14 @@ public void visit(BLangSimpleVarRef varRefExpr) { updateFunctionParamsOfClosures(env, varRefExpr); } } - if (varRefSym == null) { + BLangInvokableNode encInvokable = env.enclInvokable; + BSymbol symbol = varRefExpr.symbol; + if (varRefSym == null || encInvokable == null || (symbol.tag & SymTag.VARIABLE) != SymTag.VARIABLE) { result = varRefExpr; return; } - result = markClosureVariable(varRefExpr, env); + updateClosureVariable((BVarSymbol) symbol, encInvokable, varRefExpr.pos); + result = varRefExpr; } private void updateFunctionParamsOfClosures(SymbolEnv symbolEnv, BLangSimpleVarRef varRefExpr) { @@ -1007,23 +1006,11 @@ public void visit(BLangCompoundAssignment compoundAssignment) { @Override public void visit(BLangInvocation invocation) { rewriteInvocationExpr(invocation); - if (invocation.functionPointerInvocation) { - BLangInvokableNode encInvokable = env.enclInvokable; - if (encInvokable != null && encInvokable.flagSet.contains(Flag.LAMBDA)) { - BVarSymbol varSymbol = (BVarSymbol) invocation.symbol; - if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && - encInvokable.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); - BSymbol resolvedSymbol = symResolver.lookupClosureVarSymbol(encInvokableEnv, invocation.symbol.name, - SymTag.VARIABLE); - if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { - varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, - invocation.pos)); - } - } - } + BLangInvokableNode encInvokable = env.enclInvokable; + if (encInvokable == null || !invocation.functionPointerInvocation) { + return; } + updateClosureVariable((BVarSymbol) invocation.symbol, encInvokable, invocation.pos); } public void rewriteInvocationExpr(BLangInvocation invocation) { @@ -1201,31 +1188,29 @@ public void visit(BLangWorkerFlushExpr workerFlushExpr) { @Override public void visit(BLangSimpleVarRef.BLangLocalVarRef localVarRef) { + BLangInvokableNode encInvokable = env.enclInvokable; BSymbol symbol = localVarRef.symbol; - if (symbol == null) { + if (encInvokable == null || (symbol.tag & SymTag.VARIABLE) != SymTag.VARIABLE) { result = localVarRef; return; } - result = markClosureVariable(localVarRef, env); - } - - private BLangSimpleVarRef markClosureVariable(BLangSimpleVarRef varRefExpr, SymbolEnv env) { - BLangInvokableNode encInvokable = env.enclInvokable; - if ((varRefExpr.symbol.tag & SymTag.VARIABLE) == SymTag.VARIABLE) { - BVarSymbol varSymbol = (BVarSymbol) varRefExpr.symbol; - if (!varSymbol.closure && encInvokable != null && !encInvokable.flagSet.contains(Flag.QUERY_LAMBDA) && - encInvokable.flagSet.contains(Flag.LAMBDA)) { - SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); - BSymbol resolvedSymbol = - symResolver.lookupClosureVarSymbol(encInvokableEnv, varRefExpr.symbol.name, SymTag.VARIABLE); - if (resolvedSymbol != symTable.notFoundSymbol && !encInvokable.flagSet.contains(Flag.ATTACHED)) { - varSymbol.closure = true; - ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, - varRefExpr.pos)); - } + updateClosureVariable((BVarSymbol) symbol, encInvokable, localVarRef.pos); + result = localVarRef; + } + + private void updateClosureVariable(BVarSymbol varSymbol, BLangInvokableNode encInvokable, Location pos) { + Set flagSet = encInvokable.flagSet; + boolean isClosure = !flagSet.contains(Flag.QUERY_LAMBDA) && flagSet.contains(Flag.LAMBDA) && + !flagSet.contains(Flag.ATTACHED); + if (!varSymbol.closure && isClosure) { + SymbolEnv encInvokableEnv = findEnclosingInvokableEnv(env, encInvokable); + BSymbol resolvedSymbol = + symResolver.lookupClosureVarSymbol(encInvokableEnv, varSymbol.name, SymTag.VARIABLE); + if (resolvedSymbol != symTable.notFoundSymbol) { + varSymbol.closure = true; + ((BLangFunction) encInvokable).closureVarSymbols.add(new ClosureVarSymbol(varSymbol, pos)); } } - return varRefExpr; } @Override From 28bf26de940bcbefe381915fe206749e4813081d Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 12:11:24 +0530 Subject: [PATCH 27/43] Add annotation support to bir --- .../compiler/BIRPackageSymbolEnter.java | 28 +++++++++++-------- .../compiler/bir/writer/BIRTypeWriter.java | 11 +++++++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java index 3430806a36cd..59b229369d06 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java @@ -1215,7 +1215,6 @@ public BType readType(int cpI) throws IOException { // Read the type flags to identify if type reference types are nullable. int typeFlags = inputStream.readInt(); - switch (tag) { case TypeTags.INT: return typeParamAnalyzer.getNominalType(symTable.intType, name, flags); @@ -1317,17 +1316,8 @@ public BType readType(int cpI) throws IOException { } recordType.typeInclusions = readTypeInclusions(); - boolean hasAnnotations = inputStream.readBoolean(); - if (hasAnnotations) { - String fieldName = getStringCPEntryValue(inputStream); - var fieldFlags = inputStream.readLong(); - byte[] docBytes = readDocBytes(inputStream); - BType fieldType = readTypeFromCp(); - BVarSymbol varSymbol = new BVarSymbol(fieldFlags, Names.fromString(fieldName), - recordSymbol.pkgID, fieldType, recordSymbol, - symTable.builtinPos, COMPILED_SOURCE); - defineMarkDownDocAttachment(varSymbol, docBytes); - recordSymbol.annotations = varSymbol; + if (inputStream.readBoolean()) { + readFieldAnnotations(recordSymbol); } // setDocumentation(varSymbol, attrData); // TODO fix @@ -1606,6 +1596,9 @@ public BType readType(int cpI) throws IOException { if (inputStream.readBoolean()) { bTupleType.restType = readTypeFromCp(); } + if (inputStream.readBoolean()) { + readFieldAnnotations(tupleTypeSymbol); + } return bTupleType; case TypeTags.FUTURE: @@ -1757,6 +1750,17 @@ public BType readType(int cpI) throws IOException { return null; } + private void readFieldAnnotations(BTypeSymbol typeSymbol) throws IOException { + String fieldName = getStringCPEntryValue(inputStream); + var fieldFlags = inputStream.readLong(); + byte[] docBytes = readDocBytes(inputStream); + BType fieldType = readTypeFromCp(); + BVarSymbol varSymbol = new BVarSymbol(fieldFlags, Names.fromString(fieldName), typeSymbol.pkgID, fieldType, + typeSymbol, symTable.builtinPos, COMPILED_SOURCE); + defineMarkDownDocAttachment(varSymbol, docBytes); + typeSymbol.annotations = varSymbol; + } + private BTypeIdSet readTypeIdSet(DataInputStream inputStream) throws IOException { Set primary = new HashSet<>(); int primaryTypeIdCount = inputStream.readInt(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java index 9ddcd09480aa..d9b6ee449ccc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java @@ -345,6 +345,7 @@ public void visit(BTupleType bTupleType) { } else { buff.writeBoolean(false); } + writeFieldAnnotations(bTupleType.tsymbol); } @Override @@ -434,7 +435,15 @@ public void visit(BRecordType bRecordType) { writeTypeCpIndex(initializerFunc.type); writeTypeInclusions(bRecordType.typeInclusions); - BVarSymbol annotations = tsymbol.annotations; + writeFieldAnnotations(tsymbol); + } + + private void writeFieldAnnotations(BTypeSymbol typeSymbol) { + if (typeSymbol == null) { + buff.writeBoolean(false); + return; + } + BVarSymbol annotations = typeSymbol.annotations; boolean annotationsExist = annotations != null; buff.writeBoolean(annotationsExist); if (annotationsExist) { From c15e4a9aea896160f77087e238129156bc27aea1 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 12:11:44 +0530 Subject: [PATCH 28/43] Update BIR spec --- docs/bir-spec/src/main/resources/kaitai/bir.ksy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/bir-spec/src/main/resources/kaitai/bir.ksy b/docs/bir-spec/src/main/resources/kaitai/bir.ksy index 5715f59c7031..1bf74759678b 100644 --- a/docs/bir-spec/src/main/resources/kaitai/bir.ksy +++ b/docs/bir-spec/src/main/resources/kaitai/bir.ksy @@ -409,6 +409,11 @@ types: - id: rest_type_cp_index type: s4 if: has_rest_type == 1 + - id: has_annotations + type: u1 + - id: annotations_cp_index + type: s4 + if: has_annotations != 0 tuple_member: seq: - id: name_cp_index From ba469c5cdba87c52fd7b2b96331346059cd6159b Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Wed, 18 Jan 2023 12:14:04 +0530 Subject: [PATCH 29/43] Rename function `createNewTypeDescConstructor` to `createTypeDescConstructorWithAnnotations` --- .../compiler/bir/codegen/JvmInstructionGen.java | 6 +++--- .../ballerinalang/compiler/bir/codegen/JvmValueGen.java | 4 ++-- .../ballerinalang/compiler/desugar/AnnotationDesugar.java | 3 --- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java index 1cbd72f0a425..1c1cd3743dd5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmInstructionGen.java @@ -2109,7 +2109,7 @@ private boolean isNonReferredRecord(BType type) { type.getQualifiedTypeName().equals(referredType.getQualifiedTypeName()); } - private void generateNewTypedescCreate(BType btype, List closureVars, BIROperand annotation) { + private void generateNewTypedescCreate(BType btype, List closureVars, BIROperand annotations) { BType type = JvmCodeGenUtil.getReferredType(btype); String className = TYPEDESC_VALUE_IMPL; if (type.tag == TypeTags.RECORD) { @@ -2128,8 +2128,8 @@ private void generateNewTypedescCreate(BType btype, List closureVars this.loadVar(closureVar.variableDcl); mv.visitInsn(AASTORE); } - if (annotation != null) { - this.loadVar(annotation.variableDcl); + if (annotations != null) { + this.loadVar(annotations.variableDcl); this.mv.visitMethodInsn(INVOKESPECIAL, className, JVM_INIT_METHOD, TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS, false); } else { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java index 29a77350dfd0..48975e1fffe7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java @@ -256,7 +256,7 @@ private byte[] createRecordTypeDescClass(BRecordType recordType, String classNam fv.visitEnd(); this.createTypeDescConstructor(cw); - this.createNewTypeDescConstructor(cw, className); + this.createTypeDescConstructorWithAnnotations(cw, className); this.createInstantiateMethod(cw, recordType, typeDef); cw.visitEnd(); @@ -436,7 +436,7 @@ private void createTypeDescConstructor(ClassWriter cw) { mv.visitEnd(); } - private void createNewTypeDescConstructor(ClassWriter cw, String name) { + private void createTypeDescConstructorWithAnnotations(ClassWriter cw, String name) { String descriptor = TYPE_DESC_CONSTRUCTOR_WITH_ANNOTATIONS; MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, JVM_INIT_METHOD, descriptor, null, null); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index dcb202c67efd..febf6423a4da 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -657,9 +657,6 @@ public BLangLambdaFunction defineFieldAnnotations(List fiel } if (annotFunctionDefined) { - if (mapLiteral.fields.isEmpty()) { - return null; - } lambdaFunction = addReturnAndDefineLambda(function, mapLiteral, pkgNode, env, pkgID, owner); } From dd11149a3f7859ed5884d7ff04c9759531d05f60 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Sun, 22 Jan 2023 18:28:25 +0530 Subject: [PATCH 30/43] Resolve conflicts --- .../wso2/ballerinalang/compiler/desugar/ClosureGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 7e7c16fbe95f..b8fe651dd9b9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -400,7 +400,7 @@ public void visit(BLangRecordTypeNode recordTypeNode) { public void visit(BLangTupleTypeNode tupleTypeNode) { BTypeSymbol typeSymbol = tupleTypeNode.getBType().tsymbol; BSymbol owner = typeSymbol.owner; - desugarFieldAnnotations(owner, typeSymbol, tupleTypeNode.memberTypeNodes, tupleTypeNode.pos); + desugarFieldAnnotations(owner, typeSymbol, tupleTypeNode.members, tupleTypeNode.pos); List rewrittenMembers = new ArrayList<>(); tupleTypeNode.members.forEach(member -> rewrittenMembers.add(rewrite(member, env))); tupleTypeNode.members = rewrittenMembers; From a5accfff0f1750d4d4b309756a57a61f4d614a5e Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 08:10:21 +0530 Subject: [PATCH 31/43] Fix review suggestions --- .../java/io/ballerina/runtime/api/values/BTypedesc.java | 8 -------- .../ballerina/runtime/internal/values/TypedescValue.java | 7 ++++++- .../test-src/annotations/local_record_annotation_test.bal | 4 ++-- .../test-src/annotations/local_tuple_annotation_test.bal | 4 ++-- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java index 9ad3561d1d52..99885b06312c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/values/BTypedesc.java @@ -19,7 +19,6 @@ import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.internal.scheduling.Strand; -import io.ballerina.runtime.internal.values.MapValue; /** *

@@ -47,13 +46,6 @@ public interface BTypedesc extends BValue { */ Object instantiate(Strand strand); - /** - * Returns the annotations specified on this type descriptor. - * - * @return annotations - */ - MapValue getAnnotations(); - /** * @param strand strand to be used to run the user-defined-type initialization code. * @param initialValues the initial values provided in the constructor expression diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java index bd44801f1455..bc139e2ce38a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java @@ -26,5 +26,10 @@ * @since 1.3.0 */ public interface TypedescValue extends RefValue, BTypedesc { - + /** + * Returns the annotations specified on this type descriptor. + * + * @return annotations + */ + MapValue getAnnotations(); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal index 489973462701..30019b4d89db 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal @@ -1,6 +1,6 @@ -// Copyright (c) 2022, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you 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 diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal index 6d616fadf432..edd7cee0557d 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal @@ -1,6 +1,6 @@ -// Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +// Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. // -// WSO2 Inc. licenses this file to you under the Apache License, +// WSO2 LLC. licenses this file to you 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 From 0a93d03e2b45a8e87b5b05c8c8625363e4d9be20 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 15:07:00 +0530 Subject: [PATCH 32/43] Set annotation to the type --- .../ballerina/runtime/internal/values/TupleValueImpl.java | 1 - .../runtime/internal/values/TypedescValueImpl.java | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 00a992d8270f..5aebd780d192 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -36,7 +36,6 @@ import io.ballerina.runtime.internal.util.exceptions.BallerinaErrorReasons; import io.ballerina.runtime.internal.util.exceptions.BallerinaException; import io.ballerina.runtime.internal.util.exceptions.RuntimeErrors; - import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 54e64fdcd876..5774156dc191 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -25,9 +25,9 @@ import io.ballerina.runtime.api.values.BMapInitialValueEntry; import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.internal.scheduling.Strand; +import io.ballerina.runtime.internal.types.BAnnotatableType; import io.ballerina.runtime.internal.types.BTypedescType; import io.ballerina.runtime.internal.util.exceptions.BallerinaException; - import java.util.Map; import static io.ballerina.runtime.api.utils.TypeUtils.getReferredType; @@ -65,12 +65,16 @@ public TypedescValueImpl(Type describingType, MapValue[] closures) { this.type = new BTypedescType(describingType); this.describingType = describingType; this.closures = closures; + if (describingType instanceof BAnnotatableType) { + this.annotations = (MapValue) ((BAnnotatableType) describingType).getAnnotations(); + } } @Deprecated public TypedescValueImpl(Type describingType, MapValue[] closures, MapValue annotations) { this(describingType, closures); this.annotations = annotations; + ((BAnnotatableType) describingType).setAnnotations(annotations); } /** From 65b7432a2140f2b3b130353e3c6eb4d88f118839 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 15:07:38 +0530 Subject: [PATCH 33/43] Add unit test --- .../annotations/LocalTupleAnnotationTest.java | 25 +++++++++++++++++++ .../local_tuple_annotation_test.bal | 8 ++++++ 2 files changed, 33 insertions(+) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java index 8a351e0e8c79..137e50f59e03 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalTupleAnnotationTest.java @@ -16,9 +16,12 @@ */ package org.ballerinalang.test.annotations; +import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.TypeChecker; +import io.ballerina.runtime.internal.types.BAnnotatableType; +import io.ballerina.runtime.internal.values.TupleValueImpl; import io.ballerina.runtime.internal.values.TypedescValue; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; @@ -47,6 +50,28 @@ public void testLocalRecordAnnotations(String function) { BRunUtil.invoke(result, function); } + @Test(description = "Test annotations of tuple members from the type") + public void testTupleAnnotations1() { + Object returns = BRunUtil.invoke(result, "testTupleMemberAnnotations1", new Object[]{}); + TupleValueImpl returnTuple = (TupleValueImpl) returns; + + Object annot1 = ((BAnnotatableType) returnTuple.getType()).getAnnotation(StringUtils.fromString("$field$.0")); + Object annot2 = ((BAnnotatableType) returnTuple.getType()).getAnnotation(StringUtils.fromString("$field$.1")); + + Assert.assertTrue(annot1 instanceof BMap); + Assert.assertTrue(annot2 instanceof BMap); + } + + @Test(description = "Test annotations of tuple members from the type") + public void testTupleAnnotations2() { + Object returns = BRunUtil.invoke(result, "testTupleMemberAnnotations2", new Object[]{}); + TupleValueImpl returnTuple = (TupleValueImpl) returns; + + Object annot1 = ((BAnnotatableType) returnTuple.getType()).getAnnotation(StringUtils.fromString("$field$.0")); + + Assert.assertTrue(annot1 instanceof BMap); + } + @DataProvider(name = "dataToTestAnnotationsOfLocalTuple") public Object[] dataToTestAnnotationsOfLocalTuple() { return new String[]{ diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal index edd7cee0557d..4dbd757c67e5 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_tuple_annotation_test.bal @@ -83,6 +83,14 @@ function testGlobalAnnotationsOnFunctionPointerReturnType() { assertEquality({name: "name", age: 10}, >m4["details"]); } +function testTupleMemberAnnotations1() returns [@annotOne {value: "foo"} int, @details {name: "name", age: gVar3} int] { + return [1, 1]; +} + +function testTupleMemberAnnotations2() returns [@annotOne {value: gVar1} @annotTwo {value: gVar2} int] { + return [1]; +} + string gVar2 = "baz"; int gVar3 = 10; From 85a4717457c13a9e83707506830dbbc8e65d21ad Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 16:23:46 +0530 Subject: [PATCH 34/43] Add annotation for anonymous records --- .../wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java | 2 +- .../wso2/ballerinalang/compiler/desugar/ClosureGenerator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 9f0c4fef4832..13292a50f3da 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -457,7 +457,7 @@ void defineStatementAnnotations(List attachments, private void defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { for (BLangTypeDefinition typeDef : pkgNode.typeDefinitions) { - if (typeDef.isBuiltinTypeDef) { + if (typeDef.isBuiltinTypeDef || typeDef.flagSet.contains(Flag.ANONYMOUS)) { continue; } PackageID pkgID = typeDef.symbol.pkgID; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index b8fe651dd9b9..38a5fa3fae9c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -410,7 +410,7 @@ public void visit(BLangTupleTypeNode tupleTypeNode) { private void desugarFieldAnnotations(BSymbol owner, BTypeSymbol typeSymbol, List fields, Location pos) { - if (owner.getKind() != SymbolKind.PACKAGE) { + if (Symbols.isFlagOn(typeSymbol.flags, Flags.ANONYMOUS) || owner.getKind() != SymbolKind.PACKAGE) { owner = getOwner(env); BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(fields, pos, env.enclPkg, env, typeSymbol.pkgID, owner); From 04d040341b3e6cc216c9f26b7e85ad7bce9c6c78 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 16:26:39 +0530 Subject: [PATCH 35/43] Retrieved annotation from type --- .../main/java/io/ballerina/runtime/internal/TypeChecker.java | 4 ---- .../ballerina/runtime/internal/values/TypedescValueImpl.java | 3 --- 2 files changed, 7 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java index 48a7865bdbbe..79b820b10e5b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java @@ -585,10 +585,6 @@ public static TypedescValue getTypedesc(Object value) { * @return the annotation value if present, nil else */ public static Object getAnnotValue(TypedescValue typedescValue, BString annotTag) { - MapValue annotMap = typedescValue.getAnnotations(); - if (annotMap != null) { - return annotMap.get(annotTag); - } Type describingType = typedescValue.getDescribingType(); if (!(describingType instanceof BAnnotatableType)) { return null; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 5774156dc191..0485d989484c 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -65,9 +65,6 @@ public TypedescValueImpl(Type describingType, MapValue[] closures) { this.type = new BTypedescType(describingType); this.describingType = describingType; this.closures = closures; - if (describingType instanceof BAnnotatableType) { - this.annotations = (MapValue) ((BAnnotatableType) describingType).getAnnotations(); - } } @Deprecated From ffa50c36601e9a4b41718c8464339a1c4e4b51d0 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 17:02:06 +0530 Subject: [PATCH 36/43] Add unit tests --- .../internal/values/TupleValueImpl.java | 1 + .../internal/values/TypedescValueImpl.java | 1 + .../LocalRecordAnnotationTest.java | 8 +- .../local_record_annotation_test.bal | 166 +++++++++++------- 4 files changed, 107 insertions(+), 69 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index 5aebd780d192..00a992d8270f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -36,6 +36,7 @@ import io.ballerina.runtime.internal.util.exceptions.BallerinaErrorReasons; import io.ballerina.runtime.internal.util.exceptions.BallerinaException; import io.ballerina.runtime.internal.util.exceptions.RuntimeErrors; + import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index 0485d989484c..cc7f6ca98b00 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -28,6 +28,7 @@ import io.ballerina.runtime.internal.types.BAnnotatableType; import io.ballerina.runtime.internal.types.BTypedescType; import io.ballerina.runtime.internal.util.exceptions.BallerinaException; + import java.util.Map; import static io.ballerina.runtime.api.utils.TypeUtils.getReferredType; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java index e7c3cd7ff1cc..0c5e1f1625f5 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/LocalRecordAnnotationTest.java @@ -53,13 +53,13 @@ public Object[] dataToTestAnnotationsOfLocalRecord() { "testMultipleAnnotationsOnLocaRecord", "testAnnotationOnLocalRecord", "testAnnotationOnLocalRecordWithGlobalVariable", - "testAnnotationOnLocalRecordWithinLambdaFunction", - "testAnnotationOnLocalRecordWithinLambdaFunction1", "testAnnotationOnLocalRecordWithinNestedLambdaFunctions", "testAnnotationOnLocalRecordWithinNestedLambdaFunctions1", - "testAnnotationOnLocalRecordWithinNestedLambdaFunctions2", + "testAnnotationOnLocalRecordWithinLambdaFunction", + "testAnnotationOnLocalRecordWithinLambdaFunction1", "testAnnotationWithMultipleFieldsOnLocalRecord", - "testAnnotationOnLocalRecordWithMultipleFields" + "testAnnotationOnLocalRecordWithMultipleFields", + "testGlobalAnnotationsOnFunctionPointerReturnType" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal index 30019b4d89db..7811b521e5b2 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/local_record_annotation_test.bal @@ -26,12 +26,17 @@ type Details record {| |}; annotation AnnotRecord annot on type, field; + annotation AnnotRecord annot1 on type, field; + annotation Details details on field; function testAnnotationOnLocalRecord() { string k = "chiranS"; - record {@annot {value: k} string x;} r = {x : ""}; + record { + @annot {value: k} + string x; + } r = {x: ""}; map m = getLocalRecordAnnotations(typeof r, "$field$.x"); assertEquality({value: "chiranS"}, >m["annot"]); @@ -39,15 +44,23 @@ function testAnnotationOnLocalRecord() { function testAnnotationWithMultipleFieldsOnLocalRecord() { string k = "chiranS"; - record {@details {name: k, age: 26} string x;} r = {x : ""}; + record { + @details {name: k, age: 26} + string x; + } r = {x: ""}; map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({name: "chiranS", age: 26}, >m["details"]); + assertEquality({name: "chiranS", age: 26}, >m["details"]); } function testAnnotationOnLocalRecordWithMultipleFields() { string k = "chiranS"; - record {@annot {value: k} string x; @annot {value: k} string y; } r = {x : "", y: ""}; + record { + @annot {value: k} + string x; + @annot {value: k} + string y; + } r = {x: "", y: ""}; map m = getLocalRecordAnnotations(typeof r, "$field$.x"); assertEquality({value: "chiranS"}, >m["annot"]); @@ -59,7 +72,10 @@ function testAnnotationOnLocalRecordWithMultipleFields() { string gVar = "foo"; function testAnnotationOnLocalRecordWithGlobalVariable() { - record {@annot {value: gVar} string x;} r = {x : ""}; + record { + @annot {value: gVar} + string x; + } r = {x: ""}; map m = getLocalRecordAnnotations(typeof r, "$field$.x"); assertEquality({value: "foo"}, >m["annot"]); @@ -67,96 +83,116 @@ function testAnnotationOnLocalRecordWithGlobalVariable() { function testAnnotationOnLocalRecordWithinLambdaFunction() { string k = "chiranS"; - function() func = function () { - record {@annot {value: k} string x;} r = {x : ""}; - map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({value: "chiranS"} , >m["annot"]); - }; - func(); + function () returns map func = function() returns map { + record { + @annot {value: k} + string x; + } r = {x: ""}; + return getLocalRecordAnnotations(typeof r, "$field$.x"); + }; + map x = func(); + assertEquality({value: "chiranS"}, >x["annot"]); } function testAnnotationOnLocalRecordWithinLambdaFunction1() { string k = "chiranS"; - function(string) func = function (string value) { - record {@annot {value: value} string x;} r = {x : ""}; - map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({value: "chiranS"}, >m["annot"]); - }; - func(k); + function (string) returns map func = function(string value) returns map { + record { + @annot {value: value} + string x; + } r = {x: ""}; + return getLocalRecordAnnotations(typeof r, "$field$.x"); + }; + map x = func(k); + assertEquality({value: "chiranS"}, >x["annot"]); } function testAnnotationOnLocalRecordWithinNestedLambdaFunctions() { string k = "chiranS"; - function () returns function() var1 = function () returns function() { - function() func = function () { - record {@annot {value: k} string x;} r = {x : ""}; - map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({value: "chiranS"}, >m["annot"]); - }; - return func; - }; - function() func = var1(); - func(); + function () returns function () returns map var1 = function() returns function () returns map { + function () returns map func = function() returns map { + record {@annot {value: k} + string x;} r = {x: ""}; + return getLocalRecordAnnotations(typeof r, "$field$.x"); + }; + return func; + }; + function () returns map func = var1(); + map x = func(); + assertEquality({value: "chiranS"}, >x["annot"]); } function testAnnotationOnLocalRecordWithinNestedLambdaFunctions1() { string k = "chiranS"; - function (string) returns function() var1 = function (string val) returns function() { - function() func = function () { - record {@annot {value: val} string x;} r = {x : ""}; - map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({value: "chiranS"}, >m["annot"]); - }; - return func; - }; - function() func = var1(k); - func(); -} - -function testAnnotationOnLocalRecordWithinNestedLambdaFunctions2() { - string k = "chiranS"; - function (string) returns function() var1 = function (string val) returns function() { - string name = "Name: "; - function() func = function () { - record {@annot {value: name + val} string x;} r = {x : ""}; - map m = getLocalRecordAnnotations(typeof r, "$field$.x"); - assertEquality({value: "Name: chiranS"}, >m["annot"]); - }; - return func; - }; - function() func = var1(k); - func(); + function (string) returns function () returns map var1 = function(string val) returns function () returns map { + function () returns map func = function() returns map { + record {@annot {value: val} string x;} r = {x: ""}; + return getLocalRecordAnnotations(typeof r, "$field$.x"); + }; + return func; + }; + function () returns map func = var1(k); + map m = func(); + assertEquality({value: "chiranS"}, >m["annot"]); } function testMultipleAnnotationsOnLocaRecord() { string k = "chiranS"; - record {@annot {value: k} @annot1 {value: k} string x;} r = {x : ""}; + record { + @annot {value: k} + @annot1 {value: k} + string x; + } r = {x: ""}; map m = getLocalRecordAnnotations(typeof r, "$field$.x"); assertEquality({value: "chiranS"}, >m["annot"]); assertEquality({value: "chiranS"}, >m["annot1"]); } -function testLocalRecordAnnotations() { - testMultipleAnnotationsOnLocaRecord(); - testAnnotationOnLocalRecord(); - testAnnotationOnLocalRecordWithGlobalVariable(); - testAnnotationOnLocalRecordWithinLambdaFunction(); - testAnnotationOnLocalRecordWithinLambdaFunction1(); - testAnnotationOnLocalRecordWithinNestedLambdaFunctions(); - testAnnotationOnLocalRecordWithinNestedLambdaFunctions1(); - testAnnotationOnLocalRecordWithinNestedLambdaFunctions2(); - testAnnotationWithMultipleFieldsOnLocalRecord(); - testAnnotationOnLocalRecordWithMultipleFields(); +string gVar1 = "bar"; + +function () returns record {string x;} x = function() returns record {@annot {value: "value"} + string x;} { + return {x: ""}; +}; +function () returns record {string x;} x2 = function() returns record { + @annot {value: gVar1} + @annot1 {value: gVar2} + string x; +} { + return {x: ""}; +}; +function () returns record {int x; int y;} x3 = function() returns record { + @annot {value: gVar1} + int x; + @details {name: "name", age: gVar3} + int y; +} { + return {x: 10, y: 10}; +}; + +function testGlobalAnnotationsOnFunctionPointerReturnType() { + map m1 = getLocalRecordAnnotations(typeof x(), "$field$.x"); + map m2 = getLocalRecordAnnotations(typeof x2(), "$field$.x"); + map m3 = getLocalRecordAnnotations(typeof x3(), "$field$.x"); + map m4 = getLocalRecordAnnotations(typeof x3(), "$field$.y"); + assertEquality({value: "value"}, >m1["annot"]); + assertEquality({value: "bar"}, >m2["annot"]); + assertEquality({value: "baz"}, >m2["annot1"]); + assertEquality({value: "bar"}, >m3["annot"]); + assertEquality({name: "name", age: 10}, >m4["details"]); } +string gVar2 = "baz"; +int gVar3 = 10; + function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = @java:Method { 'class: "org/ballerinalang/test/annotations/LocalRecordAnnotationTest", name: "getLocalRecordAnnotations" } external; -function assertEquality(anydata expected, anydata actual) { +function assertEquality(anydata expected, anydata actual) { if expected == actual { return; From b4798a68d2390b76d873ccb8b55ac5f893faba9b Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 21:43:29 +0530 Subject: [PATCH 37/43] Fix review suggestions --- .../runtime/internal/values/TypedescValue.java | 6 ------ .../internal/values/TypedescValueImpl.java | 2 -- .../compiler/BIRPackageSymbolEnter.java | 17 ----------------- .../ballerinalang/compiler/bir/BIRGen.java | 10 +++++++--- .../compiler/bir/codegen/JvmConstants.java | 2 +- .../compiler/bir/codegen/JvmValueGen.java | 1 - .../compiler/bir/writer/BIRTypeWriter.java | 18 ------------------ .../compiler/desugar/AnnotationDesugar.java | 1 - 8 files changed, 8 insertions(+), 49 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java index bc139e2ce38a..6cb915b3fa65 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValue.java @@ -26,10 +26,4 @@ * @since 1.3.0 */ public interface TypedescValue extends RefValue, BTypedesc { - /** - * Returns the annotations specified on this type descriptor. - * - * @return annotations - */ - MapValue getAnnotations(); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java index cc7f6ca98b00..3eab28f85ded 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TypedescValueImpl.java @@ -68,7 +68,6 @@ public TypedescValueImpl(Type describingType, MapValue[] closures) { this.closures = closures; } - @Deprecated public TypedescValueImpl(Type describingType, MapValue[] closures, MapValue annotations) { this(describingType, closures); this.annotations = annotations; @@ -92,7 +91,6 @@ public Object instantiate(Strand s) { return instantiate(s, new BInitialValueEntry[0]); } - @Override public MapValue getAnnotations() { return annotations; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java index f3d575238915..bea9862d5e66 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/BIRPackageSymbolEnter.java @@ -1316,9 +1316,6 @@ public BType readType(int cpI) throws IOException { } recordType.typeInclusions = readTypeInclusions(); - if (inputStream.readBoolean()) { - readFieldAnnotations(recordSymbol); - } // setDocumentation(varSymbol, attrData); // TODO fix @@ -1595,9 +1592,6 @@ public BType readType(int cpI) throws IOException { if (inputStream.readBoolean()) { bTupleType.restType = readTypeFromCp(); } - if (inputStream.readBoolean()) { - readFieldAnnotations(tupleTypeSymbol); - } return bTupleType; case TypeTags.FUTURE: @@ -1749,17 +1743,6 @@ public BType readType(int cpI) throws IOException { return null; } - private void readFieldAnnotations(BTypeSymbol typeSymbol) throws IOException { - String fieldName = getStringCPEntryValue(inputStream); - var fieldFlags = inputStream.readLong(); - byte[] docBytes = readDocBytes(inputStream); - BType fieldType = readTypeFromCp(); - BVarSymbol varSymbol = new BVarSymbol(fieldFlags, Names.fromString(fieldName), typeSymbol.pkgID, fieldType, - typeSymbol, symTable.builtinPos, COMPILED_SOURCE); - defineMarkDownDocAttachment(varSymbol, docBytes); - typeSymbol.annotations = varSymbol; - } - private BTypeIdSet readTypeIdSet(DataInputStream inputStream) throws IOException { Set primary = new HashSet<>(); int primaryTypeIdCount = inputStream.readInt(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index d0c8941d4fb4..464865cfcbbb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -1564,7 +1564,7 @@ public void visit(BLangLiteral astLiteralExpr) { @Override public void visit(BLangMapLiteral astMapLiteralExpr) { - visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList(), null); + visitTypedesc(astMapLiteralExpr.pos, astMapLiteralExpr.getBType(), Collections.emptyList()); BIRVariableDcl tempVarDcl = new BIRVariableDcl(astMapLiteralExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1980,7 +1980,7 @@ public void visit(BLangWaitExpr waitExpr) { @Override public void visit(BLangWaitForAllExpr.BLangWaitLiteral waitLiteral) { - visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList(), null); + visitTypedesc(waitLiteral.pos, waitLiteral.getBType(), Collections.emptyList()); BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId(names)); addToTrapStack(thenBB); BIRVariableDcl tempVarDcl = new BIRVariableDcl(waitLiteral.getBType(), @@ -2250,7 +2250,11 @@ public void visit(BLangTableConstructorExpr tableConstructorExpr) { public void visit(BLangSimpleVarRef.BLangTypeLoad typeLoad) { BType type = typeLoad.symbol.tag == SymTag.TYPE_DEF ? ((BTypeDefinitionSymbol) typeLoad.symbol).referenceType : typeLoad.symbol.type; - visitTypedesc(typeLoad.pos, type, Collections.emptyList(), null); + visitTypedesc(typeLoad.pos, type, Collections.emptyList()); + } + + private void visitTypedesc(Location pos, BType type, List varDcls) { + visitTypedesc(pos, type, varDcls, null); } private void visitTypedesc(Location pos, BType type, List varDcls, BIROperand annotations) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java index 0255d2fe2da4..d8f9b7685d4c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmConstants.java @@ -252,7 +252,7 @@ public class JvmConstants { // service objects, annotation processing related classes public static final String ANNOTATION_UTILS = "io/ballerina/runtime/internal/AnnotationUtils"; public static final String ANNOTATION_MAP_NAME = "$annotation_data"; - public static final String ANNOTATIONS_FIELD = "annotations"; + public static final String ANNOTATIONS_FIELD = "$annotations"; public static final String DEFAULTABLE_ARGS_ANOT_NAME = "DefaultableArgs"; public static final String DEFAULTABLE_ARGS_ANOT_FIELD = "args"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java index 48975e1fffe7..08078f247ac1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmValueGen.java @@ -445,7 +445,6 @@ private void createTypeDescConstructorWithAnnotations(ClassWriter cw, String nam mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 3); mv.visitFieldInsn(PUTFIELD, name, ANNOTATIONS_FIELD, GET_MAP_VALUE); - // load super mv.visitVarInsn(ALOAD, 0); // load type diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java index 2735acb13117..9d1ecec805ec 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRTypeWriter.java @@ -346,7 +346,6 @@ public void visit(BTupleType bTupleType) { } else { buff.writeBoolean(false); } - writeFieldAnnotations(bTupleType.tsymbol); } @Override @@ -436,23 +435,6 @@ public void visit(BRecordType bRecordType) { writeTypeCpIndex(initializerFunc.type); writeTypeInclusions(bRecordType.typeInclusions); - writeFieldAnnotations(tsymbol); - } - - private void writeFieldAnnotations(BTypeSymbol typeSymbol) { - if (typeSymbol == null) { - buff.writeBoolean(false); - return; - } - BVarSymbol annotations = typeSymbol.annotations; - boolean annotationsExist = annotations != null; - buff.writeBoolean(annotationsExist); - if (annotationsExist) { - buff.writeInt(addStringCPEntry(annotations.name.value)); - buff.writeLong(annotations.flags); - writeMarkdownDocAttachment(buff, annotations.markdownDocumentation); - writeTypeCpIndex(annotations.type); - } } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 13292a50f3da..54c589f218aa 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -802,7 +802,6 @@ private BLangFunction defineFunction(Location pos, PackageID pkgID, BSymbol owne String funcName = ANNOT_FUNC + UNDERSCORE + annotFuncCount++; BLangFunction function = ASTBuilderUtil.createFunction(pos, funcName); function.setBType(new BInvokableType(Collections.emptyList(), symTable.mapType, null)); - function.flagSet.add(Flag.PUBLIC); BLangBuiltInRefTypeNode anyMapType = (BLangBuiltInRefTypeNode) TreeBuilder.createBuiltInReferenceTypeNode(); anyMapType.typeKind = TypeKind.MAP; anyMapType.pos = pos; From 294bcc7c4c964db934e64abbf6921edc2349d0d4 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 22:17:21 +0530 Subject: [PATCH 38/43] Update ksy file --- docs/bir-spec/src/main/resources/kaitai/bir.ksy | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/docs/bir-spec/src/main/resources/kaitai/bir.ksy b/docs/bir-spec/src/main/resources/kaitai/bir.ksy index 1bf74759678b..f11fe9546f1a 100644 --- a/docs/bir-spec/src/main/resources/kaitai/bir.ksy +++ b/docs/bir-spec/src/main/resources/kaitai/bir.ksy @@ -409,11 +409,6 @@ types: - id: rest_type_cp_index type: s4 if: has_rest_type == 1 - - id: has_annotations - type: u1 - - id: annotations_cp_index - type: s4 - if: has_annotations != 0 tuple_member: seq: - id: name_cp_index @@ -487,11 +482,6 @@ types: type: s4 repeat: expr repeat-expr: type_inclusions_count - - id: has_annotations - type: u1 - - id: annotations_cp_index - type: s4 - if: has_annotations != 0 record_field: seq: - id: name_cp_index From bf4915bf6e775f66670afe01dbab656c5779c2f7 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 22:18:07 +0530 Subject: [PATCH 39/43] fix `getting unused variable warning` with tuple annotation --- .../compiler/semantics/analyzer/DataflowAnalyzer.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java index 3e8edc95e881..a120ce1332d4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/DataflowAnalyzer.java @@ -2038,7 +2038,12 @@ public void visit(BLangFiniteTypeNode finiteTypeNode) { @Override public void visit(BLangTupleTypeNode tupleTypeNode) { - tupleTypeNode.members.forEach(member -> analyzeNode(member, env)); + for (BLangSimpleVariable member : tupleTypeNode.members) { + analyzeNode(member, env); + for (BLangAnnotationAttachment annotationAttachment : member.annAttachments) { + analyzeNode(annotationAttachment.expr, env); + } + } } @Override From e14d9f156b5033fa13ed7c871fa4a3c1ec123221 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Mon, 23 Jan 2023 22:18:38 +0530 Subject: [PATCH 40/43] Add tests for unused variable warnings --- .../test/dataflow/analysis/UnusedVariableTest.java | 2 ++ .../analysis/unused_variable_analysis_test.bal | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/dataflow/analysis/UnusedVariableTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/dataflow/analysis/UnusedVariableTest.java index 43ec0a752903..266af25788f0 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/dataflow/analysis/UnusedVariableTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/dataflow/analysis/UnusedVariableTest.java @@ -108,6 +108,8 @@ public void testUnusedVariableAnalysis() { validateWarning(result, i++, getUnusedVariableWarning("i"), 388, 5); validateWarning(result, i++, getUnusedVariableWarning("j"), 397, 9); validateWarning(result, i++, getUnusedVariableWarning("k"), 405, 9); + validateWarning(result, i++, getUnusedVariableWarning("k1"), 418, 5); + validateWarning(result, i++, getUnusedVariableWarning("k2"), 421, 5); Assert.assertEquals(result.getWarnCount(), i); Assert.assertEquals(result.getErrorCount(), 0); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/dataflow/analysis/unused_variable_analysis_test.bal b/tests/jballerina-unit-test/src/test/resources/test-src/dataflow/analysis/unused_variable_analysis_test.bal index 2a49bf2136e4..6c554c8b0cf5 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/dataflow/analysis/unused_variable_analysis_test.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/dataflow/analysis/unused_variable_analysis_test.bal @@ -406,3 +406,17 @@ service / on new Listener(1234) { int _ = y[0]; } } + +type AnnotTupleOne record {| + string value; +|}; + +annotation AnnotTupleOne annotOne on type, field; + +function f19() { + string n3 = "n3"; // used `n3` + [@annotOne {value: n3} int] k1 = []; // unused `k1` + + string n4 = "n4"; // used `n4` + record {@annotOne {value: n4} string x;} k2 = {x: ""}; // unused `k2` +} From e1da96f4d0206e33b5f2606aaa007b5efadaea02 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 24 Jan 2023 09:48:19 +0530 Subject: [PATCH 41/43] Add bala test --- .../test/bala/annotation/AnnotationTests.java | 5 +++++ .../bala/test_bala/annotations/annotation.bal | 11 +++++++++++ .../bala/test_projects/test_project/annotations.bal | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java index 429103a5623f..801ba8f100f5 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/bala/annotation/AnnotationTests.java @@ -76,6 +76,11 @@ public void testAnnotationsOnRecordFields() { BRunUtil.invoke(result, "testAnnotOnRecordFields"); } + @Test + public void testAnnotationsOnTupleFields() { + BRunUtil.invoke(result, "testAnnotOnTupleFields"); + } + @Test(description = "Test the deprecated construct from external module") public void testDeprecation() { CompileResult result = BCompileUtil.compile("test-src/bala/test_bala/annotations/deprecation_annotation.bal"); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal index 858ccb32db82..b9fea04b2883 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal @@ -33,12 +33,23 @@ function testAnnotOnRecordFields() { assertEquality({value : "10"} , >m["testorg/foo:1:annotOne"]); } +function testAnnotOnTupleFields() { + map m = getLocalTupleAnnotations(typeof foo:testAnnotationsOnLocalTupleFields(), "$field$.0"); + assertEquality({value : "10"} , >m["testorg/foo:1:annotOne"]); +} + function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = @java:Method { 'class: "org/ballerinalang/test/annotations/LocalRecordAnnotationTest", name: "getLocalRecordAnnotations" } external; +function getLocalTupleAnnotations(typedesc obj, string annotName) returns map = +@java:Method { + 'class: "org/ballerinalang/test/annotations/LocalTupleAnnotationTest", + name: "getLocalTupleAnnotations" +} external; + function assertEquality(anydata expected, anydata actual) { if expected == actual { return; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal index 0d10ac16652c..e910ce28c228 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal @@ -32,3 +32,7 @@ public function testAnnotationsOnLocalRecordFields() returns record {string x; s record {@annotOne {value: "10"} string x; string y;} r = {x : "", y: ""}; return r; } + +public function testAnnotationsOnLocalTupleFields() returns [@annotOne {value: "10"} string] { + return [""]; +} From b9b862efcc715dfe31d145ffe02b0fc07646a0d4 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 24 Jan 2023 09:49:58 +0530 Subject: [PATCH 42/43] Add annotation for anonymous records to global map --- .../ballerinalang/compiler/desugar/AnnotationDesugar.java | 2 +- .../ballerinalang/compiler/desugar/ClosureGenerator.java | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 54c589f218aa..dcd4f491994a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -457,7 +457,7 @@ void defineStatementAnnotations(List attachments, private void defineTypeAnnotations(BLangPackage pkgNode, SymbolEnv env, BLangFunction initFunction) { for (BLangTypeDefinition typeDef : pkgNode.typeDefinitions) { - if (typeDef.isBuiltinTypeDef || typeDef.flagSet.contains(Flag.ANONYMOUS)) { + if (typeDef.isBuiltinTypeDef) { continue; } PackageID pkgID = typeDef.symbol.pkgID; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java index 38a5fa3fae9c..672038a1a7a9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java @@ -410,7 +410,7 @@ public void visit(BLangTupleTypeNode tupleTypeNode) { private void desugarFieldAnnotations(BSymbol owner, BTypeSymbol typeSymbol, List fields, Location pos) { - if (Symbols.isFlagOn(typeSymbol.flags, Flags.ANONYMOUS) || owner.getKind() != SymbolKind.PACKAGE) { + if (owner.getKind() != SymbolKind.PACKAGE) { owner = getOwner(env); BLangLambdaFunction lambdaFunction = annotationDesugar.defineFieldAnnotations(fields, pos, env.enclPkg, env, typeSymbol.pkgID, owner); @@ -907,9 +907,13 @@ public void visit(BLangRecordLiteral recordLiteral) { for (RecordLiteralNode.RecordField field : recordLiteral.fields) { if (field.isKeyValueField()) { BLangRecordLiteral.BLangRecordKeyValueField keyValueField = - (BLangRecordLiteral.BLangRecordKeyValueField) field; + (BLangRecordLiteral.BLangRecordKeyValueField) field; keyValueField.key.expr = rewriteExpr(keyValueField.key.expr); keyValueField.valueExpr = rewriteExpr(keyValueField.valueExpr); + } else if (field.getKind() != NodeKind.SIMPLE_VARIABLE_REF) { + BLangRecordLiteral.BLangRecordSpreadOperatorField spreadOpField = + (BLangRecordLiteral.BLangRecordSpreadOperatorField) field; + spreadOpField.expr = rewriteExpr(spreadOpField.expr); } } result = recordLiteral; From 01f2595b311c017d829f4bf223ef82b02c848bb6 Mon Sep 17 00:00:00 2001 From: chiranSachintha Date: Tue, 24 Jan 2023 11:42:15 +0530 Subject: [PATCH 43/43] Update bala tests --- .../bala/test_bala/annotations/annotation.bal | 5 +++++ .../bala/test_projects/test_project/annotations.bal | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal index b9fea04b2883..e2d2a0aa0e9c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_bala/annotations/annotation.bal @@ -31,11 +31,16 @@ function testAnnotOnBoundMethod() { function testAnnotOnRecordFields() { map m = getLocalRecordAnnotations(typeof foo:testAnnotationsOnLocalRecordFields(), "$field$.x"); assertEquality({value : "10"} , >m["testorg/foo:1:annotOne"]); + m = getLocalRecordAnnotations(typeof foo:testRecordFieldAnnotationsOnReturnType(), "$field$.x"); + assertEquality({value : "100"} , >m["testorg/foo:1:annotOne"]); + } function testAnnotOnTupleFields() { map m = getLocalTupleAnnotations(typeof foo:testAnnotationsOnLocalTupleFields(), "$field$.0"); assertEquality({value : "10"} , >m["testorg/foo:1:annotOne"]); + m = getLocalTupleAnnotations(typeof foo:testTupleFieldAnnotationsOnReturnType(), "$field$.0"); + assertEquality({value : "100"} , >m["testorg/foo:1:annotOne"]); } function getLocalRecordAnnotations(typedesc obj, string annotName) returns map = diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal index e910ce28c228..ad2b48f29501 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/bala/test_projects/test_project/annotations.bal @@ -33,6 +33,15 @@ public function testAnnotationsOnLocalRecordFields() returns record {string x; s return r; } -public function testAnnotationsOnLocalTupleFields() returns [@annotOne {value: "10"} string] { +public function testRecordFieldAnnotationsOnReturnType() returns record {@annotOne {value: "100"} string x; string y;} { + return {x : "", y: ""}; +} + +public function testTupleFieldAnnotationsOnReturnType() returns [@annotOne {value: "100"} string] { return [""]; } + +public function testAnnotationsOnLocalTupleFields() returns [@annotOne {value: "10"} string] { + [@annotOne {value: "10"} string] r = [""]; + return r; +}