From a3371aadfc8128b13f50a477117c34a77cd51c9e Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:01:55 +0530 Subject: [PATCH 01/97] Enable build for worker_change branch --- .github/workflows/publish_timestamped_release.yml | 1 + .github/workflows/pull_request_ubuntu_build.yml | 1 + .github/workflows/pull_request_windows_build.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/publish_timestamped_release.yml b/.github/workflows/publish_timestamped_release.yml index bd39a4f4add9..34276582b158 100644 --- a/.github/workflows/publish_timestamped_release.yml +++ b/.github/workflows/publish_timestamped_release.yml @@ -4,6 +4,7 @@ on: push: branches: - query-grouping-aggregation + - worker_change workflow_dispatch: jobs: diff --git a/.github/workflows/pull_request_ubuntu_build.yml b/.github/workflows/pull_request_ubuntu_build.yml index 5bdf8e1e7fee..214233f284bd 100644 --- a/.github/workflows/pull_request_ubuntu_build.yml +++ b/.github/workflows/pull_request_ubuntu_build.yml @@ -15,6 +15,7 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation + - worker_change jobs: ubuntu_build: diff --git a/.github/workflows/pull_request_windows_build.yml b/.github/workflows/pull_request_windows_build.yml index 4f42987df8a5..cadfb9ef3c42 100644 --- a/.github/workflows/pull_request_windows_build.yml +++ b/.github/workflows/pull_request_windows_build.yml @@ -15,6 +15,7 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation + - worker_change jobs: windows_build: name: Build with some tests on Windows From 752ac25f0e1f452411aed466c8ce5515a1ebb81d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:04:20 +0530 Subject: [PATCH 02/97] Add parsing support for on-fail-clause in worker-decl --- .../internal/parser/BallerinaParser.java | 7 +- .../parser/BallerinaParserErrorHandler.java | 4 +- .../tree/STNamedWorkerDeclarationNode.java | 18 +- .../internal/parser/tree/STNodeFactory.java | 6 +- .../internal/parser/tree/STTreeModifier.java | 4 +- .../tree/NamedWorkerDeclarationNode.java | 27 +- .../compiler/syntax/tree/NodeFactory.java | 26 +- .../compiler/syntax/tree/TreeModifier.java | 5 +- .../test/syntax/misc/WorkerDeclTest.java | 11 +- .../worker-decl/worker_decl_assert_06.json | 1312 +++++++++++++++++ .../worker-decl/worker_decl_assert_07.json | 1106 ++++++++++++++ .../worker-decl/worker_decl_source_06.bal | 30 + .../worker-decl/worker_decl_source_07.bal | 22 + .../resources/syntax_tree_descriptor.json | 5 + .../core/FormattingTreeModifier.java | 14 +- .../api_gen_syntax_tree_descriptor.json | 5 + 16 files changed, 2580 insertions(+), 22 deletions(-) create mode 100644 compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json create mode 100644 compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json create mode 100644 compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_06.bal create mode 100644 compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_07.bal diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index db5bc23b717a..1cf924bc3bfb 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -9978,9 +9978,9 @@ private STNode parseNamespacePrefix() { * Parse named worker declaration. *

* named-worker-decl := [annots] [transactional] worker worker-name return-type-descriptor { sequence-stmt } - * + * [on-fail-clause] * - * @param annots Annotations attached to the worker decl + * @param annots Annotations attached to the worker decl * @param qualifiers Preceding transactional keyword in a list * @return Parsed node */ @@ -9992,8 +9992,9 @@ private STNode parseNamedWorkerDeclaration(STNode annots, List qualifier STNode returnTypeDesc = parseReturnTypeDescriptor(); STNode workerBody = parseBlockNode(); endContext(); + STNode onFailClause = parseOptionalOnFailClause(); return STNodeFactory.createNamedWorkerDeclarationNode(annots, transactionalKeyword, workerKeyword, workerName, - returnTypeDesc, workerBody); + returnTypeDesc, workerBody, onFailClause); } private STNode getTransactionalKeyword(List qualifierList) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java index 3865df486aa7..b3b698f061b6 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java @@ -4824,10 +4824,10 @@ private ParserRuleContext getNextRuleForCloseBrace(int nextLookahead) { case CLOSE_BRACE_TOKEN: return ParserRuleContext.CLOSE_BRACE; default: - return ParserRuleContext.STATEMENT; + return ParserRuleContext.REGULAR_COMPOUND_STMT_RHS; } } else { - return ParserRuleContext.STATEMENT; + return ParserRuleContext.REGULAR_COMPOUND_STMT_RHS; } case MATCH_BODY: return ParserRuleContext.MATCH_PATTERN; diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNamedWorkerDeclarationNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNamedWorkerDeclarationNode.java index 4bbe811b30f5..396e6c690da5 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNamedWorkerDeclarationNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNamedWorkerDeclarationNode.java @@ -37,6 +37,7 @@ public class STNamedWorkerDeclarationNode extends STNode { public final STNode workerName; public final STNode returnTypeDesc; public final STNode workerBody; + public final STNode onFailClause; STNamedWorkerDeclarationNode( STNode annotations, @@ -44,7 +45,8 @@ public class STNamedWorkerDeclarationNode extends STNode { STNode workerKeyword, STNode workerName, STNode returnTypeDesc, - STNode workerBody) { + STNode workerBody, + STNode onFailClause) { this( annotations, transactionalKeyword, @@ -52,6 +54,7 @@ public class STNamedWorkerDeclarationNode extends STNode { workerName, returnTypeDesc, workerBody, + onFailClause, Collections.emptyList()); } @@ -62,6 +65,7 @@ public class STNamedWorkerDeclarationNode extends STNode { STNode workerName, STNode returnTypeDesc, STNode workerBody, + STNode onFailClause, Collection diagnostics) { super(SyntaxKind.NAMED_WORKER_DECLARATION, diagnostics); this.annotations = annotations; @@ -70,6 +74,7 @@ public class STNamedWorkerDeclarationNode extends STNode { this.workerName = workerName; this.returnTypeDesc = returnTypeDesc; this.workerBody = workerBody; + this.onFailClause = onFailClause; addChildren( annotations, @@ -77,7 +82,8 @@ public class STNamedWorkerDeclarationNode extends STNode { workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } public STNode modifyWith(Collection diagnostics) { @@ -88,6 +94,7 @@ public STNode modifyWith(Collection diagnostics) { this.workerName, this.returnTypeDesc, this.workerBody, + this.onFailClause, diagnostics); } @@ -97,14 +104,16 @@ public STNamedWorkerDeclarationNode modify( STNode workerKeyword, STNode workerName, STNode returnTypeDesc, - STNode workerBody) { + STNode workerBody, + STNode onFailClause) { if (checkForReferenceEquality( annotations, transactionalKeyword, workerKeyword, workerName, returnTypeDesc, - workerBody)) { + workerBody, + onFailClause)) { return this; } @@ -115,6 +124,7 @@ public STNamedWorkerDeclarationNode modify( workerName, returnTypeDesc, workerBody, + onFailClause, diagnostics); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index 9faa0246f642..3f8b593e0d4c 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -979,7 +979,8 @@ public static STNode createNamedWorkerDeclarationNode( STNode workerKeyword, STNode workerName, STNode returnTypeDesc, - STNode workerBody) { + STNode workerBody, + STNode onFailClause) { return new STNamedWorkerDeclarationNode( annotations, @@ -987,7 +988,8 @@ public static STNode createNamedWorkerDeclarationNode( workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } public static STNode createNamedWorkerDeclarator( diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index f7ad60532229..38c85e0e6f8a 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -1039,13 +1039,15 @@ public STNamedWorkerDeclarationNode transform( STNode workerName = modifyNode(namedWorkerDeclarationNode.workerName); STNode returnTypeDesc = modifyNode(namedWorkerDeclarationNode.returnTypeDesc); STNode workerBody = modifyNode(namedWorkerDeclarationNode.workerBody); + STNode onFailClause = modifyNode(namedWorkerDeclarationNode.onFailClause); return namedWorkerDeclarationNode.modify( annotations, transactionalKeyword, workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } @Override diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NamedWorkerDeclarationNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NamedWorkerDeclarationNode.java index ecf4af702eec..89e3dc9a03dc 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NamedWorkerDeclarationNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NamedWorkerDeclarationNode.java @@ -57,6 +57,10 @@ public BlockStatementNode workerBody() { return childInBucket(5); } + public Optional onFailClause() { + return optionalChildInBucket(6); + } + @Override public void accept(NodeVisitor visitor) { visitor.visit(this); @@ -75,7 +79,8 @@ protected String[] childNames() { "workerKeyword", "workerName", "returnTypeDesc", - "workerBody"}; + "workerBody", + "onFailClause"}; } public NamedWorkerDeclarationNode modify( @@ -84,14 +89,16 @@ public NamedWorkerDeclarationNode modify( Token workerKeyword, IdentifierToken workerName, Node returnTypeDesc, - BlockStatementNode workerBody) { + BlockStatementNode workerBody, + OnFailClauseNode onFailClause) { if (checkForReferenceEquality( annotations.underlyingListNode(), transactionalKeyword, workerKeyword, workerName, returnTypeDesc, - workerBody)) { + workerBody, + onFailClause)) { return this; } @@ -101,7 +108,8 @@ public NamedWorkerDeclarationNode modify( workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } public NamedWorkerDeclarationNodeModifier modify() { @@ -121,6 +129,7 @@ public static class NamedWorkerDeclarationNodeModifier { private IdentifierToken workerName; private Node returnTypeDesc; private BlockStatementNode workerBody; + private OnFailClauseNode onFailClause; public NamedWorkerDeclarationNodeModifier(NamedWorkerDeclarationNode oldNode) { this.oldNode = oldNode; @@ -130,6 +139,7 @@ public NamedWorkerDeclarationNodeModifier(NamedWorkerDeclarationNode oldNode) { this.workerName = oldNode.workerName(); this.returnTypeDesc = oldNode.returnTypeDesc().orElse(null); this.workerBody = oldNode.workerBody(); + this.onFailClause = oldNode.onFailClause().orElse(null); } public NamedWorkerDeclarationNodeModifier withAnnotations( @@ -172,6 +182,12 @@ public NamedWorkerDeclarationNodeModifier withWorkerBody( return this; } + public NamedWorkerDeclarationNodeModifier withOnFailClause( + OnFailClauseNode onFailClause) { + this.onFailClause = onFailClause; + return this; + } + public NamedWorkerDeclarationNode apply() { return oldNode.modify( annotations, @@ -179,7 +195,8 @@ public NamedWorkerDeclarationNode apply() { workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } } } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index 693914e36019..9c6c52be4114 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -1270,6 +1270,11 @@ public static FunctionBodyBlockNode createFunctionBodyBlockNode( return stFunctionBodyBlockNode.createUnlinkedFacade(); } + /** + * @deprecated Use {@link #createNamedWorkerDeclarationNode(NodeList, Token, Token, IdentifierToken, Node, + * BlockStatementNode, OnFailClauseNode)} instead. + */ + @Deprecated public static NamedWorkerDeclarationNode createNamedWorkerDeclarationNode( NodeList annotations, Token transactionalKeyword, @@ -1277,6 +1282,24 @@ public static NamedWorkerDeclarationNode createNamedWorkerDeclarationNode( IdentifierToken workerName, Node returnTypeDesc, BlockStatementNode workerBody) { + return createNamedWorkerDeclarationNode( + annotations, + transactionalKeyword, + workerKeyword, + workerName, + returnTypeDesc, + workerBody, + null); + } + + public static NamedWorkerDeclarationNode createNamedWorkerDeclarationNode( + NodeList annotations, + Token transactionalKeyword, + Token workerKeyword, + IdentifierToken workerName, + Node returnTypeDesc, + BlockStatementNode workerBody, + OnFailClauseNode onFailClause) { Objects.requireNonNull(annotations, "annotations must not be null"); Objects.requireNonNull(workerKeyword, "workerKeyword must not be null"); Objects.requireNonNull(workerName, "workerName must not be null"); @@ -1288,7 +1311,8 @@ public static NamedWorkerDeclarationNode createNamedWorkerDeclarationNode( workerKeyword.internalNode(), workerName.internalNode(), getOptionalSTNode(returnTypeDesc), - workerBody.internalNode()); + workerBody.internalNode(), + getOptionalSTNode(onFailClause)); return stNamedWorkerDeclarationNode.createUnlinkedFacade(); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index 4b4cf4872685..89648f55b9f7 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -1335,13 +1335,16 @@ public NamedWorkerDeclarationNode transform( modifyNode(namedWorkerDeclarationNode.returnTypeDesc().orElse(null)); BlockStatementNode workerBody = modifyNode(namedWorkerDeclarationNode.workerBody()); + OnFailClauseNode onFailClause = + modifyNode(namedWorkerDeclarationNode.onFailClause().orElse(null)); return namedWorkerDeclarationNode.modify( annotations, transactionalKeyword, workerKeyword, workerName, returnTypeDesc, - workerBody); + workerBody, + onFailClause); } @Override diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/misc/WorkerDeclTest.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/misc/WorkerDeclTest.java index 0be245411909..30f63c6b6db0 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/misc/WorkerDeclTest.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/misc/WorkerDeclTest.java @@ -31,6 +31,11 @@ public void testBasicWorkerDecl() { testFile("worker-decl/worker_decl_source_01.bal", "worker-decl/worker_decl_assert_01.json"); } + @Test + public void testWorkerDeclWithOnFailClause() { + testFile("worker-decl/worker_decl_source_06.bal", "worker-decl/worker_decl_assert_06.json"); + } + // Recovery tests @Test @@ -53,5 +58,9 @@ public void testMissingReturnTypeDesc() { public void testInvalidUsageOfNamedWorkers() { testFile("worker-decl/worker_decl_source_05.bal", "worker-decl/worker_decl_assert_05.json"); } - + + @Test + public void testWorkerWithOnFailClauseRecovery() { + testFile("worker-decl/worker_decl_source_07.bal", "worker-decl/worker_decl_assert_07.json"); + } } diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json new file mode 100644 index 000000000000..2dd9dec55296 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json @@ -0,0 +1,1312 @@ +{ + "kind": "MODULE_PART", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "FUNCTION_DEFINITION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "foo" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w1", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "2" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "children": [ + { + "kind": "ON_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "3" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w2", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w3", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "3" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "children": [ + { + "kind": "ON_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "VAR_TYPE_DESC", + "children": [ + { + "kind": "VAR_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "e", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w4", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "3" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "children": [ + { + "kind": "ON_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ERROR_TYPE_DESC", + "children": [ + { + "kind": "ERROR_KEYWORD" + }, + { + "kind": "TYPE_PARAMETER", + "children": [ + { + "kind": "LT_TOKEN" + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "E" + } + ] + }, + { + "kind": "GT_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "e", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "RETURN_STATEMENT", + "children": [ + { + "kind": "RETURN_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ERROR_CONSTRUCTOR", + "children": [ + { + "kind": "ERROR_KEYWORD" + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "POSITIONAL_ARG", + "children": [ + { + "kind": "STRING_LITERAL", + "children": [ + { + "kind": "STRING_LITERAL_TOKEN", + "value": "error!" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "ANNOTATION", + "children": [ + { + "kind": "AT_TOKEN", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "someAnnot", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "MAPPING_CONSTRUCTOR", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w5", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RETURN_TYPE_DESCRIPTOR", + "children": [ + { + "kind": "RETURNS_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "STRING_TYPE_DESC", + "children": [ + { + "kind": "STRING_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "3" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "4" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "EOF_TOKEN" + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json new file mode 100644 index 000000000000..44e295cf1bd3 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json @@ -0,0 +1,1106 @@ +{ + "kind": "MODULE_PART", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "FUNCTION_DEFINITION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "foo" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w1", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "2" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "hasDiagnostics": true, + "children": [ + { + "kind": "ON_KEYWORD", + "hasDiagnostics": true, + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "PERCENT_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "hasDiagnostics": true, + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "PERCENT_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "FUNCTION_DEFINITION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "bar" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w2", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "2" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "hasDiagnostics": true, + "children": [ + { + "kind": "ON_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_FAIL_KEYWORD" + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + }, + { + "kind": "BLOCK_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OPEN_BRACE_TOKEN" + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_CLOSE_BRACE_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "FUNCTION_DEFINITION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "baz" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "w3", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "2" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "ON_FAIL_CLAUSE", + "hasDiagnostics": true, + "children": [ + { + "kind": "ON_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "FAIL_KEYWORD", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_FAIL_KEYWORD" + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "value": "w4", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "WORKER_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "NUMERIC_LITERAL", + "children": [ + { + "kind": "DECIMAL_INTEGER_LITERAL_TOKEN", + "value": "2" + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "EOF_TOKEN" + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_06.bal b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_06.bal new file mode 100644 index 000000000000..0bea360ca99f --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_06.bal @@ -0,0 +1,30 @@ +function foo() { + worker w1 { + int b = 2; + } on fail { + int c = 3; + } + + worker w2 { + + } + + worker w3 { + int c = 3; + } on fail var e { + + } + + worker w4 { + int c = 3; + } on fail error e { + return error("error!"); + } + + @someAnnot {} + worker w5 returns string { + int c = 3; + } + + int d = 4; +} diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_07.bal b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_07.bal new file mode 100644 index 000000000000..6e4abdad6630 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_source_07.bal @@ -0,0 +1,22 @@ +function foo() { + worker w1 { + int b = 2; + } % on % fail { + } +} + +function bar() { + worker w2 { + int b = 2; + } on f +} + +function baz() { + worker w3 { + int b = 2; + } on f + + worker w4 { + int b = 2; + } +} diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 3f017e2ee548..56feb7921564 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -1808,6 +1808,11 @@ { "name": "workerBody", "type": "BlockStatementNode" + }, + { + "name": "onFailClause", + "type": "OnFailClauseNode", + "isOptional": true } ] }, diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 185d1094f875..6440048c8bfc 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -3501,8 +3501,17 @@ public NamedWorkerDeclarationNode transform(NamedWorkerDeclarationNode namedWork Token workerKeyword = formatToken(namedWorkerDeclarationNode.workerKeyword(), 1, 0); IdentifierToken workerName = formatToken(namedWorkerDeclarationNode.workerName(), 1, 0); Node returnTypeDesc = formatNode(namedWorkerDeclarationNode.returnTypeDesc().orElse(null), 1, 0); - BlockStatementNode workerBody = formatNode(namedWorkerDeclarationNode.workerBody(), env.trailingWS, - env.trailingNL); + + BlockStatementNode workerBody; + OnFailClauseNode onFailClause; + Optional onFailClauseNode = namedWorkerDeclarationNode.onFailClause(); + if (onFailClauseNode.isPresent()) { + workerBody = formatNode(namedWorkerDeclarationNode.workerBody(), 1, 0); + onFailClause = formatNode(onFailClauseNode.get(), env.trailingWS, env.trailingNL); + } else { + workerBody = formatNode(namedWorkerDeclarationNode.workerBody(), env.trailingWS, env.trailingNL); + onFailClause = null; + } return namedWorkerDeclarationNode.modify() .withAnnotations(annotations) @@ -3511,6 +3520,7 @@ public NamedWorkerDeclarationNode transform(NamedWorkerDeclarationNode namedWork .withWorkerName(workerName) .withReturnTypeDesc(returnTypeDesc) .withWorkerBody(workerBody) + .withOnFailClause(onFailClause) .apply(); } diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index 3016675785e2..19c5c6e99fe3 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -1808,6 +1808,11 @@ { "name": "workerBody", "type": "BlockStatementNode" + }, + { + "name": "onFailClause", + "type": "OnFailClauseNode", + "isOptional": true } ] }, From bd8cf2f6e286bfce48c5b4efceca15f91e6a8cae Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 14 Nov 2023 14:22:29 +0530 Subject: [PATCH 03/97] Add parsing support for alternate-receive-action --- .../internal/parser/BallerinaParser.java | 37 +- .../parser/BallerinaParserErrorHandler.java | 24 +- .../internal/parser/ParserRuleContext.java | 3 + .../tree/STAlternateReceiveWorkerNode.java | 84 ++ .../internal/parser/tree/STNodeFactory.java | 7 + .../parser/tree/STNodeTransformer.java | 4 + .../internal/parser/tree/STNodeVisitor.java | 4 + .../internal/parser/tree/STTreeModifier.java | 8 + .../tree/AlternateReceiveWorkerNode.java | 96 ++ .../compiler/syntax/tree/NodeFactory.java | 9 + .../compiler/syntax/tree/NodeTransformer.java | 4 + .../compiler/syntax/tree/NodeVisitor.java | 4 + .../compiler/syntax/tree/SyntaxKind.java | 2 +- .../compiler/syntax/tree/TreeModifier.java | 9 + .../compiler/parser/test/ParserTestUtils.java | 2 + .../syntax/actions/ReceiveActionTest.java | 10 + .../receive_action_assert_04.json | 992 ++++++++++++++++++ .../receive_action_assert_05.json | 508 +++++++++ .../receive_action_source_04.bal | 13 + .../receive_action_source_05.bal | 5 + .../main/resources/syntax_node_metadata.json | 4 + .../resources/syntax_tree_descriptor.json | 12 + .../core/FormattingTreeModifier.java | 10 + .../api_gen_syntax_tree_descriptor.json | 12 + 24 files changed, 1858 insertions(+), 5 deletions(-) create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_04.bal create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_05.bal diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 1cf924bc3bfb..c4a91b6ee211 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13069,7 +13069,14 @@ private STNode parseSyncSendToken() { /** * Parse receive action. *

- * receive-action := single-receive-action | multiple-receive-action + * receive-action := single-receive-action | multiple-receive-action | alternate-receive-action + *

+ * single-receive-action := <- peer-worker + *

+ * multiple-receive-action := <- { receive-field (, receive-field)* } + *

+ * alternate-receive-action := <- peer-worker (| peer-worker)* + *
* * @return Receive action */ @@ -13083,7 +13090,7 @@ private STNode parseReceiveWorkers() { switch (peek().kind) { case FUNCTION_KEYWORD: case IDENTIFIER_TOKEN: - return parsePeerWorkerName(); + return parseSingleOrAlternateReceiveWorkers(); case OPEN_BRACE_TOKEN: return parseMultipleReceiveWorkers(); default: @@ -13092,6 +13099,32 @@ private STNode parseReceiveWorkers() { } } + private STNode parseSingleOrAlternateReceiveWorkers() { + startContext(ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER); + List workers = new ArrayList<>(); + // Parse first peer worker name, that has no leading comma + STNode peerWorker = parsePeerWorkerName(); + workers.add(peerWorker); + + STToken nextToken = peek(); + if (nextToken.kind != SyntaxKind.PIPE_TOKEN) { + endContext(); + return peerWorker; + } + + // Parse the remaining peer worker names + while (nextToken.kind == SyntaxKind.PIPE_TOKEN) { + STNode pipeToken = consume(); + workers.add(pipeToken); + peerWorker = parsePeerWorkerName(); + workers.add(peerWorker); + nextToken = peek(); + } + + endContext(); + return STNodeFactory.createAlternateReceiveWorkerNode(STNodeFactory.createNodeList(workers)); + } + /** * Parse multiple worker receivers. *

diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java index b3b698f061b6..ae64f3c86902 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java @@ -522,7 +522,10 @@ public class BallerinaParserErrorHandler extends AbstractParserErrorHandler { { ParserRuleContext.ARG_LIST_OPEN_PAREN, ParserRuleContext.SEMICOLON }; private static final ParserRuleContext[] RECEIVE_WORKERS = - { ParserRuleContext.PEER_WORKER_NAME, ParserRuleContext.MULTI_RECEIVE_WORKERS }; + { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER, ParserRuleContext.MULTI_RECEIVE_WORKERS }; + + private static final ParserRuleContext[] SINGLE_OR_ALTERNATE_WORKER_SEPARATOR = + { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END, ParserRuleContext.PIPE }; private static final ParserRuleContext[] RECEIVE_FIELD = { ParserRuleContext.PEER_WORKER_NAME, ParserRuleContext.RECEIVE_FIELD_NAME }; @@ -1607,6 +1610,7 @@ protected boolean hasAlternativePaths(ParserRuleContext currentCtx) { case GROUPING_KEY_LIST_ELEMENT: case GROUPING_KEY_LIST_ELEMENT_END: case RESULT_CLAUSE: + case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: return true; default: return false; @@ -2075,6 +2079,8 @@ protected ParserRuleContext getShortestAlternative(ParserRuleContext currentCtx) return ParserRuleContext.TYPE_DESC_IN_TUPLE; case RESULT_CLAUSE: return ParserRuleContext.SELECT_CLAUSE; + case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: + return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END; default: throw new IllegalStateException("Alternative path entry not found"); } @@ -2845,6 +2851,9 @@ private Result seekMatchInExprRelatedAlternativePaths(ParserRuleContext currentC case ERROR_CONSTRUCTOR_RHS: alternativeRules = ERROR_CONSTRUCTOR_RHS; break; + case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: + alternativeRules = SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; + break; default: throw new IllegalStateException("seekMatchInExprRelatedAlternativePaths found: " + currentCtx); } @@ -3481,6 +3490,11 @@ protected ParserRuleContext getNextRule(ParserRuleContext currentCtx, int nextLo return getNextRuleForBindingPattern(); case TUPLE_MEMBERS: return ParserRuleContext.TUPLE_MEMBER; + case SINGLE_OR_ALTERNATE_WORKER: + return ParserRuleContext.PEER_WORKER_NAME; + case SINGLE_OR_ALTERNATE_WORKER_END: + endContext(); // end single-or-alternate-worker + return ParserRuleContext.EXPRESSION_RHS; default: return getNextRuleInternal(currentCtx, nextLookahead); } @@ -3504,6 +3518,8 @@ private ParserRuleContext getNextRuleInternal(ParserRuleContext currentCtx, int return ParserRuleContext.XML_ATOMIC_NAME_PATTERN; } else if (parentCtx == ParserRuleContext.MATCH_PATTERN) { return ParserRuleContext.MATCH_PATTERN_START; + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { + return ParserRuleContext.PEER_WORKER_NAME; } return ParserRuleContext.TYPE_DESCRIPTOR; case TABLE_CONSTRUCTOR: @@ -4091,8 +4107,11 @@ private ParserRuleContext getNextRuleForKeywords(ParserRuleContext currentCtx, i case FLUSH_KEYWORD: return ParserRuleContext.OPTIONAL_PEER_WORKER; case PEER_WORKER_NAME: - if (getParentContext() == ParserRuleContext.MULTI_RECEIVE_WORKERS) { + parentCtx = getParentContext(); + if (parentCtx == ParserRuleContext.MULTI_RECEIVE_WORKERS) { return ParserRuleContext.RECEIVE_FIELD_END; + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { + return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; } return ParserRuleContext.EXPRESSION_RHS; case WAIT_KEYWORD: @@ -4269,6 +4288,7 @@ private void startContextIfRequired(ParserRuleContext currentCtx) { case BRACED_EXPRESSION: case CLIENT_RESOURCE_ACCESS_ACTION: case TUPLE_MEMBERS: + case SINGLE_OR_ALTERNATE_WORKER: // Contexts that expect a type case TYPE_DESC_IN_ANNOTATION_DECL: diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java index b336e39c4454..7463f0a3281b 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java @@ -733,6 +733,9 @@ public enum ParserRuleContext { OPTIONAL_TOP_LEVEL_SEMICOLON("optional-top-level-semicolon"), TUPLE_MEMBERS("tuple-members"), TUPLE_MEMBER("tuple-member"), + SINGLE_OR_ALTERNATE_WORKER("single-or-alternate-worker"), + SINGLE_OR_ALTERNATE_WORKER_SEPARATOR("single-or-alternate-worker-separator"), + SINGLE_OR_ALTERNATE_WORKER_END("single-or-alternate-worker-end"), ; private String value; diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java new file mode 100644 index 000000000000..cdf5bbd00e4b --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.internal.parser.tree; + +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NonTerminalNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; + +import java.util.Collection; +import java.util.Collections; + +/** + * This is a generated internal syntax tree node. + * + * @since 2201.9.0 + */ +public class STAlternateReceiveWorkerNode extends STNode { + public final STNode workers; + + STAlternateReceiveWorkerNode( + STNode workers) { + this( + workers, + Collections.emptyList()); + } + + STAlternateReceiveWorkerNode( + STNode workers, + Collection diagnostics) { + super(SyntaxKind.ALTERNATE_RECEIVE_WORKER, diagnostics); + this.workers = workers; + + addChildren( + workers); + } + + public STNode modifyWith(Collection diagnostics) { + return new STAlternateReceiveWorkerNode( + this.workers, + diagnostics); + } + + public STAlternateReceiveWorkerNode modify( + STNode workers) { + if (checkForReferenceEquality( + workers)) { + return this; + } + + return new STAlternateReceiveWorkerNode( + workers, + diagnostics); + } + + public Node createFacade(int position, NonTerminalNode parent) { + return new AlternateReceiveWorkerNode(this, position, parent); + } + + @Override + public void accept(STNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(STNodeTransformer transformer) { + return transformer.transform(this); + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index 3f8b593e0d4c..3ab3c497ce65 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -1826,6 +1826,13 @@ public static STNode createReceiveFieldsNode( closeBrace); } + public static STNode createAlternateReceiveWorkerNode( + STNode workers) { + + return new STAlternateReceiveWorkerNode( + workers); + } + public static STNode createRestDescriptorNode( STNode typeDescriptor, STNode ellipsisToken) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java index 14b60714218b..8fffa392f44a 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java @@ -621,6 +621,10 @@ public T transform(STReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } + public T transform(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + return transformSyntaxNode(alternateReceiveWorkerNode); + } + public T transform(STRestDescriptorNode restDescriptorNode) { return transformSyntaxNode(restDescriptorNode); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java index e7b961a89e50..8e20dc2e4cec 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java @@ -621,6 +621,10 @@ public void visit(STReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } + public void visit(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + visitSyntaxNode(alternateReceiveWorkerNode); + } + public void visit(STRestDescriptorNode restDescriptorNode) { visitSyntaxNode(restDescriptorNode); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index 38c85e0e6f8a..4c4a0582efb8 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -1955,6 +1955,14 @@ public STReceiveFieldsNode transform( closeBrace); } + @Override + public STAlternateReceiveWorkerNode transform( + STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + STNode workers = modifyNode(alternateReceiveWorkerNode.workers); + return alternateReceiveWorkerNode.modify( + workers); + } + @Override public STRestDescriptorNode transform( STRestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java new file mode 100644 index 000000000000..9faf603d867d --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.syntax.tree; + +import io.ballerina.compiler.internal.parser.tree.STNode; + +import java.util.Objects; + +/** + * This is a generated syntax tree node. + * + * @since 2201.9.0 + */ +public class AlternateReceiveWorkerNode extends NonTerminalNode { + + public AlternateReceiveWorkerNode(STNode internalNode, int position, NonTerminalNode parent) { + super(internalNode, position, parent); + } + + public SeparatedNodeList workers() { + return new SeparatedNodeList<>(childInBucket(0)); + } + + @Override + public void accept(NodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(NodeTransformer visitor) { + return visitor.transform(this); + } + + @Override + protected String[] childNames() { + return new String[]{ + "workers"}; + } + + public AlternateReceiveWorkerNode modify( + SeparatedNodeList workers) { + if (checkForReferenceEquality( + workers.underlyingListNode())) { + return this; + } + + return NodeFactory.createAlternateReceiveWorkerNode( + workers); + } + + public AlternateReceiveWorkerNodeModifier modify() { + return new AlternateReceiveWorkerNodeModifier(this); + } + + /** + * This is a generated tree node modifier utility. + * + * @since 2201.9.0 + */ + public static class AlternateReceiveWorkerNodeModifier { + private final AlternateReceiveWorkerNode oldNode; + private SeparatedNodeList workers; + + public AlternateReceiveWorkerNodeModifier(AlternateReceiveWorkerNode oldNode) { + this.oldNode = oldNode; + this.workers = oldNode.workers(); + } + + public AlternateReceiveWorkerNodeModifier withWorkers( + SeparatedNodeList workers) { + Objects.requireNonNull(workers, "workers must not be null"); + this.workers = workers; + return this; + } + + public AlternateReceiveWorkerNode apply() { + return oldNode.modify( + workers); + } + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index 9c6c52be4114..41e78a9d7aa9 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -2430,6 +2430,15 @@ public static ReceiveFieldsNode createReceiveFieldsNode( return stReceiveFieldsNode.createUnlinkedFacade(); } + public static AlternateReceiveWorkerNode createAlternateReceiveWorkerNode( + SeparatedNodeList workers) { + Objects.requireNonNull(workers, "workers must not be null"); + + STNode stAlternateReceiveWorkerNode = STNodeFactory.createAlternateReceiveWorkerNode( + workers.underlyingListNode().internalNode()); + return stAlternateReceiveWorkerNode.createUnlinkedFacade(); + } + public static RestDescriptorNode createRestDescriptorNode( TypeDescriptorNode typeDescriptor, Token ellipsisToken) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java index ec21175b1833..856f0a16e8c3 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java @@ -632,6 +632,10 @@ public T transform(ReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } + public T transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + return transformSyntaxNode(alternateReceiveWorkerNode); + } + public T transform(RestDescriptorNode restDescriptorNode) { return transformSyntaxNode(restDescriptorNode); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java index 13544361784d..6ec321663c9b 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java @@ -631,6 +631,10 @@ public void visit(ReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } + public void visit(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + visitSyntaxNode(alternateReceiveWorkerNode); + } + public void visit(RestDescriptorNode restDescriptorNode) { visitSyntaxNode(restDescriptorNode); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java index a800be0930c3..7022853b81b2 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java @@ -484,7 +484,7 @@ public enum SyntaxKind { GROUPING_KEY_VAR_NAME(3092), GROUP_BY_CLAUSE(3093), COLLECT_CLAUSE(3094), - + ALTERNATE_RECEIVE_WORKER(3095), // XML XML_ELEMENT(4000), diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index 89648f55b9f7..3b588db29c0d 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -2474,6 +2474,15 @@ public ReceiveFieldsNode transform( closeBrace); } + @Override + public AlternateReceiveWorkerNode transform( + AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + SeparatedNodeList workers = + modifySeparatedNodeList(alternateReceiveWorkerNode.workers()); + return alternateReceiveWorkerNode.modify( + workers); + } + @Override public RestDescriptorNode transform( RestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java index 611a9b071e3c..7ced96123ba9 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java @@ -633,6 +633,8 @@ private static SyntaxKind getNodeKind(String kind) { return SyntaxKind.COMPUTED_RESOURCE_ACCESS_SEGMENT; case "RESOURCE_ACCESS_REST_SEGMENT": return SyntaxKind.RESOURCE_ACCESS_REST_SEGMENT; + case "ALTERNATE_RECEIVE_WORKER": + return SyntaxKind.ALTERNATE_RECEIVE_WORKER; // Trivia case "EOF_TOKEN": diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java index d13102ea25e2..446896beb7c9 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java @@ -33,6 +33,11 @@ public void testBasicReceiveAction() { testFile("receive-action/receive_action_source_01.bal", "receive-action/receive_action_assert_01.json"); } + @Test + public void testAlternateReceiveAction() { + testFile("receive-action/receive_action_source_04.bal", "receive-action/receive_action_assert_04.json"); + } + // Recover tests @Test @@ -44,4 +49,9 @@ public void testRecoveryInReceiveAction() { public void testInvalidNodeInReceiveAction() { testFile("receive-action/receive_action_source_03.bal", "receive-action/receive_action_assert_03.json"); } + + @Test + public void testAlternateReceiveActionRecovery() { + testFile("receive-action/receive_action_source_05.bal", "receive-action/receive_action_assert_05.json"); + } } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json new file mode 100644 index 000000000000..19961f156696 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -0,0 +1,992 @@ +{ + "kind": "FUNCTION_DEFINITION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "foo" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "E", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "FOREACH_STATEMENT", + "children": [ + { + "kind": "FOREACH_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "VAR_TYPE_DESC", + "children": [ + { + "kind": "VAR_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "err", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "IN_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json new file mode 100644 index 000000000000..4ae969c3f442 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json @@ -0,0 +1,508 @@ +{ + "kind": "FUNCTION_DEFINITION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "foo" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "ACTION_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ], + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IMPORT_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ], + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IMPORT_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "ALTERNATE_RECEIVE_WORKER", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_04.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_04.bal new file mode 100644 index 000000000000..88bd3fd56d20 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_04.bal @@ -0,0 +1,13 @@ +function foo() { + worker E { + foreach var err in <- A | B { + } + } + + <- function | function; + <- A | B | C | D; + <- A | function | function | D; + a = <- function | A; + a = <- A | B | C; + int b = <- B | C; +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_05.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_05.bal new file mode 100644 index 000000000000..c4aa9317c6d0 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_05.bal @@ -0,0 +1,5 @@ +function foo() { + <- A | import| C | D + a = <- A | B | import| D; + a = <- A | +} diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index f62a209a1bcb..d4d9de78f262 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -1,4 +1,8 @@ { + "AlternateReceiveWorkerNode": { + "createdYear": "2023", + "since": "2201.9.0" + }, "ClientResourceActionNode": { "createdYear": "2022", "since": "2201.2.0" diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 56feb7921564..910133a78585 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -3341,6 +3341,18 @@ } ] }, + { + "name": "AlternateReceiveWorkerNode", + "base": "Node", + "kind": "ALTERNATE_RECEIVE_WORKER", + "attributes": [ + { + "name": "workers", + "type": "SimpleNameReferenceNode", + "occurrences": "MULTIPLE_SEPARATED" + } + ] + }, { "name": "RestDescriptorNode", "base": "Node", diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 6440048c8bfc..a43a6ebc44e0 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -17,6 +17,7 @@ */ package org.ballerinalang.formatter.core; +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -3020,6 +3021,15 @@ public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { .apply(); } + @Override + public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + SeparatedNodeList workers = + formatSeparatedNodeList(alternateReceiveWorkerNode.workers(), 1, 0, env.trailingWS, env.trailingNL); + return alternateReceiveWorkerNode.modify() + .withWorkers(workers) + .apply(); + } + @Override public RestDescriptorNode transform(RestDescriptorNode restDescriptorNode) { TypeDescriptorNode typeDescriptor = formatNode(restDescriptorNode.typeDescriptor(), 0, 0); diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index 19c5c6e99fe3..b6d44b817afb 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -3341,6 +3341,18 @@ } ] }, + { + "name": "AlternateReceiveWorkerNode", + "base": "Node", + "kind": "ALTERNATE_RECEIVE_WORKER", + "attributes": [ + { + "name": "workers", + "type": "SimpleNameReferenceNode", + "occurrences": "MULTIPLE_SEPARATED" + } + ] + }, { "name": "RestDescriptorNode", "base": "Node", From a5d501caa6d58ef75b931de6ccde60ed72b53c03 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 15 Nov 2023 09:54:46 +0530 Subject: [PATCH 04/97] Skip worker-decl_source_07.bal from formatting due to #41698 --- .../org/ballerinalang/formatter/core/ParserTestFormatter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java index 21ab99112917..d5db5b4992a3 100644 --- a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java +++ b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java @@ -96,6 +96,9 @@ public List skipList() { "separated_node_list_import_decl.bal", "node_location_test_03.bal", + // formatter keeps adding whitespaces #41698 + "worker_decl_source_07.bal", + // parser tests with syntax errors that cannot be handled by the formatter "worker_decl_source_03.bal", "worker_decl_source_05.bal", "invalid_identifier_source_01.bal", "ambiguity_source_23.bal", "ambiguity_source_09.bal", "ambiguity_source_18.bal", From a215eb81308a78539c49d4737f843b990921e37e Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 22 Nov 2023 10:12:51 +0530 Subject: [PATCH 05/97] Create channel per each worker message send-receive Each pair of send-receive is associated with an index called eventIndex --- .../ballerinalang/compiler/bir/BIRGen.java | 8 ++- .../semantics/analyzer/CodeAnalyzer.java | 43 ++++++++----- .../compiler/tree/BLangFunction.java | 3 +- .../expressions/BLangWorkerAsyncSendExpr.java | 2 +- .../BLangWorkerSendReceiveExpr.java | 60 +++++++++++++++++++ .../expressions/BLangWorkerSyncSendExpr.java | 2 +- 6 files changed, 97 insertions(+), 21 deletions(-) create mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java 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 da3c31f9d93b..2ea82421ae1f 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 @@ -163,6 +163,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerAsyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendReceiveExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLCommentLiteral; @@ -598,9 +599,10 @@ public void visit(BLangFunction astFunc) { //create channelDetails array int i = 0; - for (String channelName : astFunc.sendsToThis) { - birFunc.workerChannels[i] = new BIRNode.ChannelDetails(channelName, astFunc.defaultWorkerName.value - .equals(DEFAULT_WORKER_NAME), isWorkerSend(channelName, astFunc.defaultWorkerName.value)); + for (BLangWorkerSendReceiveExpr.Channel channel : astFunc.sendsToThis) { + String channelId = channel.channelId(); + birFunc.workerChannels[i] = new BIRNode.ChannelDetails(channelId, astFunc.defaultWorkerName.value + .equals(DEFAULT_WORKER_NAME), isWorkerSend(channelId, astFunc.defaultWorkerName.value)); i++; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 889e815a1e11..9ebd74ebd386 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -169,6 +169,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerAsyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendReceiveExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLCommentLiteral; @@ -3659,22 +3660,21 @@ private void validateWorkerInteractions(WorkerActionSystem workerActionSystem, A continue; } BLangWorkerReceive receive = (BLangWorkerReceive) otherSM.currentAction(); - if (isWorkerSyncSend(currentAction)) { - this.validateWorkerActionParameters((BLangWorkerSyncSendExpr) currentAction, receive); - } else { - this.validateWorkerActionParameters((BLangWorkerAsyncSendExpr) currentAction, receive); - } + BLangWorkerSendReceiveExpr send = (BLangWorkerSendReceiveExpr) currentAction; + validateWorkerActionParameters(send, receive); + + BLangWorkerSendReceiveExpr.Channel channel = createChannel(workerActionSystem, worker, otherSM); + receive.setChannel(channel); + send.setChannel(channel); + otherSM.next(); data.workerSystemMovementSequence++; worker.next(); data.workerSystemMovementSequence++; - systemRunning = true; - String channelName = generateChannelName(worker.workerId, otherSM.workerId); - otherSM.node.sendsToThis.add(channelName); - - worker.node.sendsToThis.add(channelName); + otherSM.node.sendsToThis.add(channel); + worker.node.sendsToThis.add(channel); } // If we iterated move than the number of workers in the system and did not progress, @@ -3693,6 +3693,15 @@ private void validateWorkerInteractions(WorkerActionSystem workerActionSystem, A } } + private static BLangWorkerSendReceiveExpr.Channel createChannel(WorkerActionSystem workerActionSystem, + WorkerActionStateMachine worker, + WorkerActionStateMachine otherSM) { + String workerPairId = BLangWorkerSendReceiveExpr.Channel.workerPairId(worker.workerId, otherSM.workerId); + Integer eventIndex = workerActionSystem.workerEventIndexMap.getOrDefault(workerPairId, 0); + workerActionSystem.workerEventIndexMap.put(workerPairId, ++eventIndex); + return new BLangWorkerSendReceiveExpr.Channel(worker.workerId, otherSM.workerId, eventIndex); + } + private boolean validateWorkerInteractionsAfterWaitAction(WorkerActionSystem workerActionSystem) { boolean isValid = true; for (WorkerActionStateMachine worker : workerActionSystem.finshedWorkers) { @@ -3834,6 +3843,14 @@ private void reportInvalidWorkerInteractionDiagnostics(WorkerActionSystem worker workerActionSystem.toString()); } + private void validateWorkerActionParameters(BLangWorkerSendReceiveExpr send, BLangWorkerReceive receive) { + if (isWorkerSyncSend(send)) { + validateWorkerActionParameters((BLangWorkerSyncSendExpr) send, receive); + } else if (isWorkerSend(send)) { + validateWorkerActionParameters((BLangWorkerAsyncSendExpr) send, receive); + } + } + private void validateWorkerActionParameters(BLangWorkerAsyncSendExpr send, BLangWorkerReceive receive) { send.receive = receive; types.checkType(send.pos, symTable.nilType, send.expectedType, @@ -4043,6 +4060,7 @@ private static class WorkerActionSystem { public List finshedWorkers = new ArrayList<>(); private Stack workerActionStateMachines = new Stack<>(); private Map workerInteractionEnvironments = new IdentityHashMap<>(); + private Map workerEventIndexMap = new HashMap<>(); private boolean hasErrors = false; @@ -4156,11 +4174,6 @@ public String toString() { } } - public static String generateChannelName(String source, String target) { - - return source + "->" + target; - } - private BLangNode getEnclosingClass(SymbolEnv env) { BLangNode node = env.node; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangFunction.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangFunction.java index cc8ccfdd28a4..8cb9ce6d101a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangFunction.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangFunction.java @@ -23,6 +23,7 @@ import org.wso2.ballerinalang.compiler.semantics.model.symbols.BInvokableSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendReceiveExpr; import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; import org.wso2.ballerinalang.compiler.util.ClosureVarSymbol; @@ -57,7 +58,7 @@ public class BLangFunction extends BLangInvokableNode implements FunctionNode { public BInvokableSymbol originalFuncSymbol; - public LinkedHashSet sendsToThis = new LinkedHashSet<>(); + public LinkedHashSet sendsToThis = new LinkedHashSet<>(); // This only set when we encounter worker inside a fork statement. public String anonForkName; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java index e7d886d854bd..da4dc4fda60c 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java @@ -33,7 +33,7 @@ * * @since 0.94 */ -public class BLangWorkerAsyncSendExpr extends BLangExpression implements WorkerSendExpressionNode { +public class BLangWorkerAsyncSendExpr extends BLangWorkerSendReceiveExpr implements WorkerSendExpressionNode { // BLangNodes public BLangExpression expr; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java new file mode 100644 index 000000000000..43e450d003f6 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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.wso2.ballerinalang.compiler.tree.expressions; + +/** + * Represents commons in worker async-send, sync-send and receive. + * + * @since 2201.9.0 + */ +public abstract class BLangWorkerSendReceiveExpr extends BLangExpression { + + private Channel channel; + + public Channel getChannel() { + return channel; + } + + public void setChannel(Channel channel) { + this.channel = channel; + } + + public static final class Channel { + public final String sender; + public final String receiver; + public final int eventIndex; + + public Channel(String sender, String receiver, int eventIndex) { + this.sender = sender; + this.receiver = receiver; + this.eventIndex = eventIndex; + } + + public String workerPairId() { + return workerPairId(sender, receiver); + } + + public static String workerPairId(String sender, String receiver) { + return sender + "->" + receiver; + } + + public String channelId() { + return sender + "->" + receiver + ":" + eventIndex; + } + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java index 4b7f67adbd56..4362be409b54 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java @@ -34,7 +34,7 @@ * * @since 0.985 */ -public class BLangWorkerSyncSendExpr extends BLangExpression implements WorkerSendExpressionNode { +public class BLangWorkerSyncSendExpr extends BLangWorkerSendReceiveExpr implements WorkerSendExpressionNode { // BLangNodes public BLangIdentifier workerIdentifier; From 36b41e7453cd433b4cc670906305cb64af849d98 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:57:21 +0530 Subject: [PATCH 06/97] Implement alternate-receive support up to desugar --- .../org/ballerinalang/model/TreeBuilder.java | 9 +++ .../ballerinalang/model/tree/NodeKind.java | 2 + .../ballerinalang/compiler/bir/BIRGen.java | 7 ++ .../compiler/desugar/ClosureDesugar.java | 6 ++ .../compiler/desugar/ClosureGenerator.java | 6 ++ .../compiler/desugar/ConstantPropagation.java | 6 ++ .../compiler/desugar/Desugar.java | 6 ++ .../compiler/desugar/QueryDesugar.java | 9 +++ .../compiler/parser/BLangNodeBuilder.java | 48 +++++++++--- .../compiler/parser/NodeCloner.java | 14 ++++ .../semantics/analyzer/CodeAnalyzer.java | 8 ++ .../semantics/analyzer/DataflowAnalyzer.java | 8 ++ .../semantics/analyzer/IsolationAnalyzer.java | 8 ++ .../semantics/analyzer/TypeChecker.java | 8 ++ .../compiler/tree/BLangNodeAnalyzer.java | 3 + .../compiler/tree/BLangNodeTransformer.java | 5 ++ .../compiler/tree/BLangNodeVisitor.java | 5 ++ .../tree/SimpleBLangNodeAnalyzer.java | 6 ++ .../BLangCombinedWorkerReceive.java | 75 +++++++++++++++++++ .../tree/expressions/BLangWorkerReceive.java | 4 +- .../BLangWorkerSendReceiveExpr.java | 2 +- 21 files changed, 231 insertions(+), 14 deletions(-) create mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java index f625ab191cbe..8ac7bd4a6d27 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java @@ -248,6 +248,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -914,6 +915,14 @@ public static WorkerReceiveNode createWorkerReceiveNode() { return new BLangWorkerReceive(); } + public static BLangCombinedWorkerReceive createAlternateWorkerReceiveNode() { + return new BLangCombinedWorkerReceive(NodeKind.ALTERNATE_WORKER_RECEIVE); + } + + public static BLangCombinedWorkerReceive createMultipleWorkerReceiveNode() { + return new BLangCombinedWorkerReceive(NodeKind.MULTIPLE_WORKER_RECEIVE); + } + public static WorkerSendExpressionNode createWorkerSendNode() { return new BLangWorkerAsyncSendExpr(); } diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/NodeKind.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/NodeKind.java index cf16f169ebf2..989e0d1edc7c 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/NodeKind.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/tree/NodeKind.java @@ -181,6 +181,8 @@ public enum NodeKind { WHILE, LOCK, WORKER_RECEIVE, + ALTERNATE_WORKER_RECEIVE, + MULTIPLE_WORKER_RECEIVE, WORKER_ASYNC_SEND, WORKER_SYNC_SEND, WORKER_FLUSH, 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 2ea82421ae1f..742f157079f0 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 @@ -104,6 +104,7 @@ import org.wso2.ballerinalang.compiler.tree.BLangXMLNS.BLangLocalXMLNS; import org.wso2.ballerinalang.compiler.tree.BLangXMLNS.BLangPackageXMLNS; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; import org.wso2.ballerinalang.compiler.tree.expressions.BLangDynamicArgExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorConstructorExpr; @@ -1143,6 +1144,12 @@ public void visit(BLangForkJoin forkJoin) { forkJoin.workers.forEach(worker -> worker.accept(this)); } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + // TODO: 22/11/23 implement + throw new AssertionError("alternate/multiple receive not yet implemented"); + } + @Override public void visit(BLangWorkerReceive workerReceive) { BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java index edf0e7add015..4b81184583d4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java @@ -69,6 +69,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1515,6 +1516,11 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { result = syncSendExpr; } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + result = combinedWorkerReceive; + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { result = workerReceiveNode; 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 cb167d786dd7..bf4f3d19e84e 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 @@ -65,6 +65,7 @@ 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1189,6 +1190,11 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { result = syncSendExpr; } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + result = combinedWorkerReceive; + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { result = workerReceiveNode; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java index 5f3c66d95b1f..6a87e522e257 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java @@ -68,6 +68,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -615,6 +616,11 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { result = asyncSendExpr; } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + result = combinedWorkerReceive; + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { result = workerReceiveNode; 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 20deedc98a6f..6bb03cce41ac 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 @@ -134,6 +134,7 @@ 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -8142,6 +8143,11 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { result = syncSendExpr; } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + result = combinedWorkerReceive; + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { result = workerReceiveNode; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java index f898371b3cb3..17a692f255f5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java @@ -86,6 +86,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -2715,6 +2716,14 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { this.acceptNode(asyncSendExpr.expr); } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + acceptNode(bLangWorkerReceive); + } + result = combinedWorkerReceive; + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { workerReceiveNode.sendExpression = rewrite(workerReceiveNode.sendExpression); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index d5925bfaeeaf..8e348c303ad1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -17,6 +17,7 @@ */ package org.wso2.ballerinalang.compiler.parser; +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -347,6 +348,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -2508,20 +2510,44 @@ public BLangNode transform(TrapExpressionNode trapExpressionNode) { @Override public BLangNode transform(ReceiveActionNode receiveActionNode) { - BLangWorkerReceive workerReceiveExpr = (BLangWorkerReceive) TreeBuilder.createWorkerReceiveNode(); + Location receiveActionPos = getPosition(receiveActionNode); Node receiveWorkers = receiveActionNode.receiveWorkers(); - Token workerName; + if (receiveWorkers.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { - workerName = ((SimpleNameReferenceNode) receiveWorkers).name(); - } else { - // TODO: implement multiple-receive-action support - Location receiveFieldsPos = getPosition(receiveWorkers); - dlog.error(receiveFieldsPos, DiagnosticErrorCode.MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED); - workerName = NodeFactory.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN, - NodeFactory.createEmptyMinutiaeList(), NodeFactory.createEmptyMinutiaeList()); + BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive((SimpleNameReferenceNode) receiveWorkers); + singleWorkerRecv.pos = receiveActionPos; + return singleWorkerRecv; } - workerReceiveExpr.setWorkerName(createIdentifier(workerName)); - workerReceiveExpr.pos = getPosition(receiveActionNode); + + if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE_WORKER) { + SeparatedNodeList alternateWorkers = + ((AlternateReceiveWorkerNode) receiveWorkers).workers(); + List workerReceives = new ArrayList<>(alternateWorkers.size()); + for (SimpleNameReferenceNode w : alternateWorkers) { + workerReceives.add(createSimpleWorkerReceive(w)); + } + + BLangCombinedWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); + alternateWorkerRecv.setWorkerReceives(workerReceives); + alternateWorkerRecv.pos = receiveActionPos; + return alternateWorkerRecv; + } + + + // TODO: implement multiple-receive-action support + dlog.error(getPosition(receiveWorkers), DiagnosticErrorCode.MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED); + Token missingIdentifier = NodeFactory.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN, + NodeFactory.createEmptyMinutiaeList(), NodeFactory.createEmptyMinutiaeList()); + SimpleNameReferenceNode simpleNameRef = NodeFactory.createSimpleNameReferenceNode(missingIdentifier); + BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive(simpleNameRef); + singleWorkerRecv.pos = receiveActionPos; + return singleWorkerRecv; + } + + private BLangWorkerReceive createSimpleWorkerReceive(SimpleNameReferenceNode simpleNameRef) { + BLangWorkerReceive workerReceiveExpr = (BLangWorkerReceive) TreeBuilder.createWorkerReceiveNode(); + workerReceiveExpr.setWorkerName(createIdentifier(simpleNameRef.name())); + workerReceiveExpr.pos = getPosition(simpleNameRef); return workerReceiveExpr; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index b1c4f0fd72cb..756147925137 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -91,6 +91,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1028,6 +1029,19 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { clone.workerIdentifier = asyncSendExpr.workerIdentifier; } + @Override + public void visit(BLangCombinedWorkerReceive source) { + BLangCombinedWorkerReceive clone = new BLangCombinedWorkerReceive(source.getKind()); + source.cloneRef = clone; + + List workerReceives = new ArrayList<>(source.getWorkerReceives().size()); + for (BLangWorkerReceive workerReceive : source.getWorkerReceives()) { + workerReceives.add(clone(workerReceive)); + } + + clone.setWorkerReceives(workerReceives); + } + @Override public void visit(BLangWorkerReceive source) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 9ebd74ebd386..a608ee6a8537 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -121,6 +121,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -2093,6 +2094,13 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { analyzeExpr(syncSendExpr.expr, data); } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive, AnalyzerData data) { + for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + analyzeExpr(bLangWorkerReceive, data); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { // Validate worker receive 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 d20fdefbfe2e..f1ce1529053a 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 @@ -100,6 +100,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1082,6 +1083,13 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { analyzeNode(syncSendExpr.expr, env); } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + for (BLangWorkerReceive workerReceive : combinedWorkerReceive.getWorkerReceives()) { + analyzeNode(workerReceive, env); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { // todo diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java index fc6532be9c26..98f339a94d9b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java @@ -138,6 +138,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1103,6 +1104,13 @@ public void visit(BLangForkJoin forkJoin) { public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + for (BLangWorkerReceive workerReceive : combinedWorkerReceive.getWorkerReceives()) { + analyzeNode(workerReceive, env); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 862182a3ff13..bc238985af0f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -103,6 +103,7 @@ 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -2850,6 +2851,13 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { data.resultType = symTable.nilType; } + @Override + public void visit(BLangCombinedWorkerReceive combinedWorkerReceive, AnalyzerData data) { + for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + bLangWorkerReceive.accept(this, data); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveExpr, AnalyzerData data) { BSymbol symbol = diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java index 12bfd933e341..bcddad04a3b6 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java @@ -51,6 +51,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -517,6 +518,8 @@ public abstract class BLangNodeAnalyzer { public abstract void visit(BLangWorkerReceive node, T data); + public abstract void visit(BLangCombinedWorkerReceive node, T data); + public abstract void visit(BLangWorkerSyncSendExpr node, T data); public abstract void visit(BLangXMLAttribute node, T data); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java index 43c21c27b8fb..d06308c8e8d2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java @@ -50,6 +50,7 @@ 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -822,6 +823,10 @@ public R transform(BLangWorkerReceive node, T data) { return transformNode(node, data); } + public R transform(BLangCombinedWorkerReceive node, T data) { + return transformNode(node, data); + } + public R transform(BLangWorkerSyncSendExpr node, T data) { return transformNode(node, data); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java index 2ed8668730b1..6322639a4218 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java @@ -53,6 +53,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -578,6 +579,10 @@ public void visit(BLangWorkerReceive workerReceiveNode) { throw new AssertionError(); } + public void visit(BLangCombinedWorkerReceive combinedWorkerReceiveNode) { + throw new AssertionError(); + } + public void visit(BLangRollback rollbackNode) { throw new AssertionError(); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java index f386a100f8be..8dd6e5733f19 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java @@ -54,6 +54,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckPanickedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCheckedExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCollectContextInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -1044,6 +1045,11 @@ public void visit(BLangWorkerFlushExpr node, T data) { visitNode(node.workerIdentifier, data); } + public void visit(BLangCombinedWorkerReceive node, T data) { + analyzeNode(node, data); + visitNode(node.getWorkerReceives(), data); + } + public void visit(BLangWorkerReceive node, T data) { analyzeNode(node, data); visitNode(node.workerIdentifier, data); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java new file mode 100644 index 000000000000..1c5b49acb11f --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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.wso2.ballerinalang.compiler.tree.expressions; + +import org.ballerinalang.model.tree.ActionNode; +import org.ballerinalang.model.tree.NodeKind; +import org.wso2.ballerinalang.compiler.tree.BLangNodeAnalyzer; +import org.wso2.ballerinalang.compiler.tree.BLangNodeTransformer; +import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; + +import java.util.List; + +/** + * Represents both alternate-receive and multiple-receive in worker communication. + * + * @since 2201.9.0 + */ +public class BLangCombinedWorkerReceive extends BLangExpression implements ActionNode { + + private final NodeKind nodeKind; + private List workerReceives; + + /** + * Constructs a BLangCombinedWorkerReceive with NodeKind. + * + * @param nodeKind Combined worker kind. Either {@link NodeKind#ALTERNATE_WORKER_RECEIVE} or + * {@link NodeKind#MULTIPLE_WORKER_RECEIVE} + */ + public BLangCombinedWorkerReceive(NodeKind nodeKind) { + this.nodeKind = nodeKind; + } + + @Override + public NodeKind getKind() { + return nodeKind; + } + + @Override + public void accept(BLangNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public void accept(BLangNodeAnalyzer analyzer, T props) { + analyzer.visit(this, props); + } + + @Override + public R apply(BLangNodeTransformer modifier, T props) { + return modifier.transform(this, props); + } + + public List getWorkerReceives() { + return workerReceives; + } + + public void setWorkerReceives(List workerReceives) { + this.workerReceives = workerReceives; + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java index c84aa6bf239a..d62e6a23e530 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java @@ -33,14 +33,14 @@ * * @since 0.94 */ -public class BLangWorkerReceive extends BLangExpression implements WorkerReceiveNode { +public class BLangWorkerReceive extends BLangWorkerSendReceiveExpr implements WorkerReceiveNode { // BLangNodes public BLangIdentifier workerIdentifier; // Semantic Data public BLangExpression sendExpression; // TODO: #AST_CLEAN - No Transformer ? - public BSymbol workerSymbol; + public BSymbol workerSymbol; // TODO: 22/11/23 Seems no usage. Clean. public SymbolEnv env; public BType workerType; public BType matchingSendsError; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java index 43e450d003f6..81d80d5590e8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java @@ -18,7 +18,7 @@ package org.wso2.ballerinalang.compiler.tree.expressions; /** - * Represents commons in worker async-send, sync-send and receive. + * Represents commons in worker async-send, sync-send and single-receive. * * @since 2201.9.0 */ From e015ca1c35eced573d9f7a325d49772b1bb5b8dc Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 23 Nov 2023 11:12:09 +0530 Subject: [PATCH 07/97] Fix channel name for single message passing --- .../ballerinalang/compiler/bir/BIRGen.java | 24 +++++++------------ 1 file changed, 9 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 742f157079f0..7395d3e8cf1b 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 @@ -91,7 +91,6 @@ import org.wso2.ballerinalang.compiler.tree.BLangClassDefinition; 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.BLangImportPackage; import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; import org.wso2.ballerinalang.compiler.tree.BLangPackage; @@ -1154,7 +1153,6 @@ public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { public void visit(BLangWorkerReceive workerReceive) { BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); addToTrapStack(thenBB); - String channel = workerReceive.workerIdentifier.value + "->" + env.enclFunc.workerName.value; BIRVariableDcl tempVarDcl = new BIRVariableDcl(workerReceive.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); @@ -1164,8 +1162,9 @@ public void visit(BLangWorkerReceive workerReceive) { boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); - this.env.enclBB.terminator = new BIRTerminator.WorkerReceive(workerReceive.pos, names.fromString(channel), - lhsOp, isOnSameStrand, thenBB, this.currentScope); + this.env.enclBB.terminator = new BIRTerminator.WorkerReceive(workerReceive.pos, + names.fromString(workerReceive.getChannel().channelId()), lhsOp, isOnSameStrand, thenBB, + this.currentScope); this.env.enclBasicBlocks.add(thenBB); this.env.enclBB = thenBB; @@ -1183,12 +1182,10 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { this.env.enclFunc.localVars.add(tempVarDcl); BIROperand lhsOp = new BIROperand(tempVarDcl); this.env.targetOperand = lhsOp; - - String channelName = this.env.enclFunc.workerName.value + "->" + asyncSendExpr.workerIdentifier.value; boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); this.env.enclBB.terminator = new BIRTerminator.WorkerSend( - asyncSendExpr.pos, names.fromString(channelName), dataOp, isOnSameStrand, false, lhsOp, + asyncSendExpr.pos, names.fromString(asyncSendExpr.getChannel().channelId()), dataOp, isOnSameStrand, false, lhsOp, thenBB, this.currentScope); this.env.enclBasicBlocks.add(thenBB); @@ -1208,11 +1205,10 @@ public void visit(BLangWorkerSyncSendExpr syncSend) { BIROperand lhsOp = new BIROperand(tempVarDcl); this.env.targetOperand = lhsOp; - String channelName = this.env.enclFunc.workerName.value + "->" + syncSend.workerIdentifier.value; boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); this.env.enclBB.terminator = new BIRTerminator.WorkerSend( - syncSend.pos, names.fromString(channelName), dataOp, isOnSameStrand, true, lhsOp, + syncSend.pos, names.fromString(syncSend.getChannel().channelId()), dataOp, isOnSameStrand, true, lhsOp, thenBB, this.currentScope); this.env.enclBasicBlocks.add(thenBB); @@ -1225,15 +1221,13 @@ public void visit(BLangWorkerFlushExpr flushExpr) { addToTrapStack(thenBB); //create channelDetails array - BIRNode.ChannelDetails[] channels = new BIRNode.ChannelDetails[flushExpr.workerIdentifierList.size()]; + BIRNode.ChannelDetails[] channels = new BIRNode.ChannelDetails[flushExpr.cachedWorkerSendStmts.size()]; int i = 0; - for (BLangIdentifier workerIdentifier : flushExpr.workerIdentifierList) { - String channelName = this.env.enclFunc.workerName.value + "->" + workerIdentifier.value; - boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); - channels[i] = new BIRNode.ChannelDetails(channelName, isOnSameStrand, true); + boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); + for (BLangWorkerAsyncSendExpr sendStmt : flushExpr.cachedWorkerSendStmts) { + channels[i] = new BIRNode.ChannelDetails(sendStmt.getChannel().channelId(), isOnSameStrand, true); i++; } - BIRVariableDcl tempVarDcl = new BIRVariableDcl(flushExpr.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); From b9cf39a36bbb4835cea6d8b7577670d591bdb46d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 23 Nov 2023 11:50:00 +0530 Subject: [PATCH 08/97] Fix check styles --- .../main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 7395d3e8cf1b..206967f53e83 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 @@ -1185,8 +1185,8 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); this.env.enclBB.terminator = new BIRTerminator.WorkerSend( - asyncSendExpr.pos, names.fromString(asyncSendExpr.getChannel().channelId()), dataOp, isOnSameStrand, false, lhsOp, - thenBB, this.currentScope); + asyncSendExpr.pos, names.fromString(asyncSendExpr.getChannel().channelId()), dataOp, isOnSameStrand, + false, lhsOp, thenBB, this.currentScope); this.env.enclBasicBlocks.add(thenBB); this.env.enclBB = thenBB; From bae6ffeb853959231919fac576e2cbd8d635ac24 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:21:33 +0530 Subject: [PATCH 09/97] Implement multiple worker support up to desugar --- .../org/ballerinalang/model/TreeBuilder.java | 11 ++- .../util/diagnostic/DiagnosticErrorCode.java | 3 +- .../ballerinalang/compiler/bir/BIRGen.java | 13 ++- .../compiler/desugar/ClosureDesugar.java | 12 ++- .../compiler/desugar/ClosureGenerator.java | 12 ++- .../compiler/desugar/ConstantPropagation.java | 12 ++- .../compiler/desugar/Desugar.java | 12 ++- .../compiler/desugar/QueryDesugar.java | 18 +++- .../compiler/parser/BLangNodeBuilder.java | 45 ++++++--- .../compiler/parser/NodeCloner.java | 25 ++++- .../semantics/analyzer/CodeAnalyzer.java | 14 ++- .../semantics/analyzer/DataflowAnalyzer.java | 15 ++- .../semantics/analyzer/IsolationAnalyzer.java | 15 ++- .../semantics/analyzer/TypeChecker.java | 14 ++- .../compiler/tree/BLangNodeAnalyzer.java | 7 +- .../compiler/tree/BLangNodeTransformer.java | 9 +- .../compiler/tree/BLangNodeVisitor.java | 9 +- .../tree/SimpleBLangNodeAnalyzer.java | 13 ++- ....java => BLangAlternateWorkerReceive.java} | 17 +--- .../BLangMultipleWorkerReceive.java | 91 +++++++++++++++++++ 20 files changed, 289 insertions(+), 78 deletions(-) rename compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/{BLangCombinedWorkerReceive.java => BLangAlternateWorkerReceive.java} (75%) create mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java index 8ac7bd4a6d27..68b530b7b2ac 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/model/TreeBuilder.java @@ -242,13 +242,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -272,6 +272,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -915,12 +916,12 @@ public static WorkerReceiveNode createWorkerReceiveNode() { return new BLangWorkerReceive(); } - public static BLangCombinedWorkerReceive createAlternateWorkerReceiveNode() { - return new BLangCombinedWorkerReceive(NodeKind.ALTERNATE_WORKER_RECEIVE); + public static BLangAlternateWorkerReceive createAlternateWorkerReceiveNode() { + return new BLangAlternateWorkerReceive(); } - public static BLangCombinedWorkerReceive createMultipleWorkerReceiveNode() { - return new BLangCombinedWorkerReceive(NodeKind.MULTIPLE_WORKER_RECEIVE); + public static BLangMultipleWorkerReceive createMultipleWorkerReceiveNode() { + return new BLangMultipleWorkerReceive(); } public static WorkerSendExpressionNode createWorkerSendNode() { diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index ea970ed5c62f..803c86eb1310 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -722,8 +722,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { MISMATCHED_VISIBILITY_QUALIFIERS_IN_OBJECT_FIELD( "BCE3988", "mismatched.visibility.qualifiers.in.object.field"), INVALID_INCLUSION_OF_OBJECT_WITH_PRIVATE_MEMBERS("BCE3989", "invalid.inclusion.of.object.with.private.members"), - - MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE3990", "multiple.receive.action.not.yet.supported"), + // Vacant error code: BCE3990 INVALID_READONLY_FIELD_TYPE("BCE3991", "invalid.readonly.field.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 ba521d830d0c..ffc03e3fd48e 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 @@ -103,8 +103,8 @@ import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; import org.wso2.ballerinalang.compiler.tree.BLangXMLNS.BLangLocalXMLNS; import org.wso2.ballerinalang.compiler.tree.BLangXMLNS.BLangPackageXMLNS; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; import org.wso2.ballerinalang.compiler.tree.expressions.BLangDynamicArgExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangErrorConstructorExpr; @@ -130,6 +130,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangTupleLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangReAssertion; import org.wso2.ballerinalang.compiler.tree.expressions.BLangReAtomCharOrEscape; import org.wso2.ballerinalang.compiler.tree.expressions.BLangReAtomQuantifier; @@ -1145,9 +1146,15 @@ public void visit(BLangForkJoin forkJoin) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { // TODO: 22/11/23 implement - throw new AssertionError("alternate/multiple receive not yet implemented"); + throw new AssertionError("alternate receive not yet implemented"); + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + // TODO: 24/11/23 implement + throw new AssertionError("multiple receive not yet implemented"); } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java index 4b81184583d4..c4bb2a8620be 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureDesugar.java @@ -65,11 +65,11 @@ import org.wso2.ballerinalang.compiler.tree.BLangVariable; import org.wso2.ballerinalang.compiler.tree.BLangXMLNS; import org.wso2.ballerinalang.compiler.tree.OCEDynamicEnvironmentData; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCheckedExpr; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -92,6 +92,7 @@ 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.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangRecordLiteral; @@ -1517,8 +1518,13 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - result = combinedWorkerReceive; + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { + result = altWorkerReceive; + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + result = multipleWorkerReceive; } @Override 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 bf4f3d19e84e..512ce4af1eaf 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 @@ -60,12 +60,12 @@ 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.BLangAlternateWorkerReceive; 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -89,6 +89,7 @@ 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.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -1191,8 +1192,13 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - result = combinedWorkerReceive; + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + result = alternateWorkerReceive; + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + result = multipleWorkerReceive; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java index 6a87e522e257..496d85290cdb 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java @@ -62,13 +62,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -86,6 +86,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -617,8 +618,13 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - result = combinedWorkerReceive; + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + result = alternateWorkerReceive; + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + result = multipleWorkerReceive; } @Override 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 44a32253bf1f..0c562728fe39 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 @@ -129,12 +129,12 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangMatchClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangOnFailClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -170,6 +170,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangTupleLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -8155,8 +8156,13 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - result = combinedWorkerReceive; + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { + result = altWorkerReceive; + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + result = multipleWorkerReceive; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java index 17a692f255f5..90bc4b0202b1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java @@ -80,13 +80,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -107,6 +107,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -2717,11 +2718,20 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { + for (BLangWorkerReceive bLangWorkerReceive : altWorkerReceive.getWorkerReceives()) { acceptNode(bLangWorkerReceive); } - result = combinedWorkerReceive; + result = altWorkerReceive; + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : multipleWorkerReceive.getReceiveFields()) { + acceptNode(rvField.getKey()); + acceptNode(rvField.getWorkerReceive()); + } + result = multipleWorkerReceive; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 36d2041bbb0b..57087bc1175b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -180,6 +180,7 @@ import io.ballerina.compiler.syntax.tree.ReUnicodePropertyEscapeNode; import io.ballerina.compiler.syntax.tree.ReUnicodeScriptNode; import io.ballerina.compiler.syntax.tree.ReceiveActionNode; +import io.ballerina.compiler.syntax.tree.ReceiveFieldsNode; import io.ballerina.compiler.syntax.tree.RecordFieldNode; import io.ballerina.compiler.syntax.tree.RecordFieldWithDefaultValueNode; import io.ballerina.compiler.syntax.tree.RecordRestDescriptorNode; @@ -342,13 +343,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -372,6 +373,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -2514,7 +2516,8 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { Node receiveWorkers = receiveActionNode.receiveWorkers(); if (receiveWorkers.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { - BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive((SimpleNameReferenceNode) receiveWorkers); + BLangWorkerReceive singleWorkerRecv = + createSimpleWorkerReceive(((SimpleNameReferenceNode) receiveWorkers).name()); singleWorkerRecv.pos = receiveActionPos; return singleWorkerRecv; } @@ -2524,30 +2527,42 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { ((AlternateReceiveWorkerNode) receiveWorkers).workers(); List workerReceives = new ArrayList<>(alternateWorkers.size()); for (SimpleNameReferenceNode w : alternateWorkers) { - workerReceives.add(createSimpleWorkerReceive(w)); + workerReceives.add(createSimpleWorkerReceive(w.name())); } - BLangCombinedWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); + BLangAlternateWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); alternateWorkerRecv.setWorkerReceives(workerReceives); alternateWorkerRecv.pos = receiveActionPos; return alternateWorkerRecv; } + ReceiveFieldsNode receiveFieldsNode = (ReceiveFieldsNode) receiveWorkers; + SeparatedNodeList receiveFields = receiveFieldsNode.receiveFields(); + List fields = new ArrayList<>(receiveFields.size()); + for (NameReferenceNode nameRef : receiveFields) { + BLangMultipleWorkerReceive.BLangReceiveField rvField = new BLangMultipleWorkerReceive.BLangReceiveField(); + if (nameRef.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { + Token name = ((SimpleNameReferenceNode) nameRef).name(); + rvField.setKey(createIdentifier(name)); + rvField.setWorkerReceive(createSimpleWorkerReceive(name)); + } else { + QualifiedNameReferenceNode qualifiedNameRef = (QualifiedNameReferenceNode) nameRef; + rvField.setKey(createIdentifier(qualifiedNameRef.modulePrefix())); + rvField.setWorkerReceive(createSimpleWorkerReceive(qualifiedNameRef.identifier())); + } + fields.add(rvField); + } - // TODO: implement multiple-receive-action support - dlog.error(getPosition(receiveWorkers), DiagnosticErrorCode.MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED); - Token missingIdentifier = NodeFactory.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN, - NodeFactory.createEmptyMinutiaeList(), NodeFactory.createEmptyMinutiaeList()); - SimpleNameReferenceNode simpleNameRef = NodeFactory.createSimpleNameReferenceNode(missingIdentifier); - BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive(simpleNameRef); - singleWorkerRecv.pos = receiveActionPos; - return singleWorkerRecv; + BLangMultipleWorkerReceive multipleWorkerRv = TreeBuilder.createMultipleWorkerReceiveNode(); + multipleWorkerRv.setReceiveFields(fields); + multipleWorkerRv.pos = receiveActionPos; + return multipleWorkerRv; } - private BLangWorkerReceive createSimpleWorkerReceive(SimpleNameReferenceNode simpleNameRef) { + private BLangWorkerReceive createSimpleWorkerReceive(Token workerRef) { BLangWorkerReceive workerReceiveExpr = (BLangWorkerReceive) TreeBuilder.createWorkerReceiveNode(); - workerReceiveExpr.setWorkerName(createIdentifier(simpleNameRef.name())); - workerReceiveExpr.pos = getPosition(simpleNameRef); + workerReceiveExpr.setWorkerName(createIdentifier(workerRef)); + workerReceiveExpr.pos = getPosition(workerRef); return workerReceiveExpr; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index 756147925137..2d33341820d2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -85,13 +85,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -117,6 +117,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -1030,8 +1031,8 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive source) { - BLangCombinedWorkerReceive clone = new BLangCombinedWorkerReceive(source.getKind()); + public void visit(BLangAlternateWorkerReceive source) { + BLangAlternateWorkerReceive clone = new BLangAlternateWorkerReceive(); source.cloneRef = clone; List workerReceives = new ArrayList<>(source.getWorkerReceives().size()); @@ -1042,6 +1043,24 @@ public void visit(BLangCombinedWorkerReceive source) { clone.setWorkerReceives(workerReceives); } + @Override + public void visit(BLangMultipleWorkerReceive source) { + BLangMultipleWorkerReceive clone = new BLangMultipleWorkerReceive(); + source.cloneRef = clone; + + List cloneFields = + new ArrayList<>(source.getReceiveFields().size()); + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : source.getReceiveFields()) { + BLangMultipleWorkerReceive.BLangReceiveField clonedRvField = + new BLangMultipleWorkerReceive.BLangReceiveField(); + clonedRvField.setKey(clone(rvField.getKey())); + clonedRvField.setWorkerReceive(clone(rvField.getWorkerReceive())); + cloneFields.add(clonedRvField); + } + + clone.setReceiveFields(cloneFields); + } + @Override public void visit(BLangWorkerReceive source) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index fe7daa9c6550..dd4d45ee0d41 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -115,13 +115,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderByClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -140,6 +140,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -2079,12 +2080,19 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive, AnalyzerData data) { - for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive, AnalyzerData data) { + for (BLangWorkerReceive bLangWorkerReceive : altWorkerReceive.getWorkerReceives()) { analyzeExpr(bLangWorkerReceive, data); } } + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData data) { + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : multipleWorkerReceive.getReceiveFields()) { + analyzeExpr(rvField.getWorkerReceive(), data); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { // Validate worker receive 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 f1ce1529053a..c9455cadd312 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 @@ -94,13 +94,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -124,6 +124,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -1084,12 +1085,20 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - for (BLangWorkerReceive workerReceive : combinedWorkerReceive.getWorkerReceives()) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { + for (BLangWorkerReceive workerReceive : altWorkerReceive.getWorkerReceives()) { analyzeNode(workerReceive, env); } } + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : multipleWorkerReceive.getReceiveFields()) { + analyzeNode(rvField.getKey(), env); + analyzeNode(rvField.getWorkerReceive(), env); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { // todo diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java index 98f339a94d9b..921febf5d8b7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java @@ -132,13 +132,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -157,6 +157,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -1105,12 +1106,20 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - for (BLangWorkerReceive workerReceive : combinedWorkerReceive.getWorkerReceives()) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive) { + for (BLangWorkerReceive workerReceive : altWorkerReceive.getWorkerReceives()) { analyzeNode(workerReceive, env); } } + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : multipleWorkerReceive.getReceiveFields()) { + analyzeNode(rvField.getKey(), env); + analyzeNode(rvField.getWorkerReceive(), env); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index e2c282f6824e..e0ef8e985e40 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -98,12 +98,12 @@ import org.wso2.ballerinalang.compiler.tree.SimpleBLangNodeAnalyzer; import org.wso2.ballerinalang.compiler.tree.clauses.BLangOnFailClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangElvisExpr; @@ -120,6 +120,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr.BLangListConstructorSpreadOpExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -2852,12 +2853,19 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } @Override - public void visit(BLangCombinedWorkerReceive combinedWorkerReceive, AnalyzerData data) { - for (BLangWorkerReceive bLangWorkerReceive : combinedWorkerReceive.getWorkerReceives()) { + public void visit(BLangAlternateWorkerReceive altWorkerReceive, AnalyzerData data) { + for (BLangWorkerReceive bLangWorkerReceive : altWorkerReceive.getWorkerReceives()) { bLangWorkerReceive.accept(this, data); } } + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData data) { + for (BLangMultipleWorkerReceive.BLangReceiveField receiveFiled : multipleWorkerReceive.getReceiveFields()) { + receiveFiled.getWorkerReceive().accept(this, data); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveExpr, AnalyzerData data) { BSymbol symbol = diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java index bcddad04a3b6..fd383d9bdffa 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeAnalyzer.java @@ -45,13 +45,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -77,6 +77,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -518,7 +519,9 @@ public abstract class BLangNodeAnalyzer { public abstract void visit(BLangWorkerReceive node, T data); - public abstract void visit(BLangCombinedWorkerReceive node, T data); + public abstract void visit(BLangAlternateWorkerReceive node, T data); + + public abstract void visit(BLangMultipleWorkerReceive node, T data); public abstract void visit(BLangWorkerSyncSendExpr node, T data); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java index d06308c8e8d2..8a4386fc84a5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeTransformer.java @@ -45,12 +45,12 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -76,6 +76,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -823,7 +824,11 @@ public R transform(BLangWorkerReceive node, T data) { return transformNode(node, data); } - public R transform(BLangCombinedWorkerReceive node, T data) { + public R transform(BLangAlternateWorkerReceive node, T data) { + return transformNode(node, data); + } + + public R transform(BLangMultipleWorkerReceive node, T data) { return transformNode(node, data); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java index 6322639a4218..be815733febf 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/BLangNodeVisitor.java @@ -47,13 +47,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -92,6 +92,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; @@ -579,7 +580,11 @@ public void visit(BLangWorkerReceive workerReceiveNode) { throw new AssertionError(); } - public void visit(BLangCombinedWorkerReceive combinedWorkerReceiveNode) { + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + throw new AssertionError(); + } + + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { throw new AssertionError(); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java index 8dd6e5733f19..a5939f8232cc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/SimpleBLangNodeAnalyzer.java @@ -48,13 +48,13 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAccessExpression; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; 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.BLangCollectContextInvocation; -import org.wso2.ballerinalang.compiler.tree.expressions.BLangCombinedWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangCommitExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstRef; import org.wso2.ballerinalang.compiler.tree.expressions.BLangConstant; @@ -80,6 +80,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -1045,11 +1046,19 @@ public void visit(BLangWorkerFlushExpr node, T data) { visitNode(node.workerIdentifier, data); } - public void visit(BLangCombinedWorkerReceive node, T data) { + public void visit(BLangAlternateWorkerReceive node, T data) { analyzeNode(node, data); visitNode(node.getWorkerReceives(), data); } + public void visit(BLangMultipleWorkerReceive node, T data) { + analyzeNode(node, data); + for (BLangMultipleWorkerReceive.BLangReceiveField rvField : node.getReceiveFields()) { + visitNode(rvField.getKey(), data); + visitNode(rvField.getWorkerReceive(), data); + } + } + public void visit(BLangWorkerReceive node, T data) { analyzeNode(node, data); visitNode(node.workerIdentifier, data); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java similarity index 75% rename from compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java rename to compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java index 1c5b49acb11f..18253ff4e1aa 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java @@ -26,28 +26,17 @@ import java.util.List; /** - * Represents both alternate-receive and multiple-receive in worker communication. + * Represents alternate-receive in worker communication. * * @since 2201.9.0 */ -public class BLangCombinedWorkerReceive extends BLangExpression implements ActionNode { +public class BLangAlternateWorkerReceive extends BLangExpression implements ActionNode { - private final NodeKind nodeKind; private List workerReceives; - /** - * Constructs a BLangCombinedWorkerReceive with NodeKind. - * - * @param nodeKind Combined worker kind. Either {@link NodeKind#ALTERNATE_WORKER_RECEIVE} or - * {@link NodeKind#MULTIPLE_WORKER_RECEIVE} - */ - public BLangCombinedWorkerReceive(NodeKind nodeKind) { - this.nodeKind = nodeKind; - } - @Override public NodeKind getKind() { - return nodeKind; + return NodeKind.ALTERNATE_WORKER_RECEIVE; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java new file mode 100644 index 000000000000..49c40b37d777 --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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.wso2.ballerinalang.compiler.tree.expressions; + +import org.ballerinalang.model.tree.ActionNode; +import org.ballerinalang.model.tree.NodeKind; +import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; +import org.wso2.ballerinalang.compiler.tree.BLangNodeAnalyzer; +import org.wso2.ballerinalang.compiler.tree.BLangNodeTransformer; +import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; + +import java.util.List; + +/** + * Represents multiple-receive in worker communication. + * + * @since 2201.9.0 + */ +public class BLangMultipleWorkerReceive extends BLangExpression implements ActionNode { + + private List receiveFields; + + @Override + public NodeKind getKind() { + return NodeKind.MULTIPLE_WORKER_RECEIVE; + } + + @Override + public void accept(BLangNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public void accept(BLangNodeAnalyzer analyzer, T props) { + analyzer.visit(this, props); + } + + @Override + public R apply(BLangNodeTransformer modifier, T props) { + return modifier.transform(this, props); + } + + public List getReceiveFields() { + return receiveFields; + } + + public void setReceiveFields(List receiveFields) { + this.receiveFields = receiveFields; + } + + /** + * This static inner class represents key-value pair in a multiple worker. + * + * @since 2201.9.0 + */ + public static class BLangReceiveField { + private BLangIdentifier key; + private BLangWorkerReceive workerReceive; + + public BLangIdentifier getKey() { + return key; + } + + public void setKey(BLangIdentifier key) { + this.key = key; + } + + public BLangWorkerReceive getWorkerReceive() { + return workerReceive; + } + + public void setWorkerReceive(BLangWorkerReceive workerReceive) { + this.workerReceive = workerReceive; + } + } +} From d4eba649df0e0c6275f3d98bda2dda15f2773910 Mon Sep 17 00:00:00 2001 From: poorna2152 Date: Mon, 27 Nov 2023 11:11:56 +0530 Subject: [PATCH 10/97] Fix failing worker change parser tests --- .../worker-decl/worker_decl_assert_06.json | 90 ++++++----- .../worker-decl/worker_decl_assert_07.json | 142 ++++++++++-------- 2 files changed, 138 insertions(+), 94 deletions(-) diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json index 2dd9dec55296..a489150893d5 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json @@ -595,26 +595,36 @@ ] }, { - "kind": "VAR_TYPE_DESC", + "kind": "TYPED_BINDING_PATTERN", "children": [ { - "kind": "VAR_KEYWORD", - "trailingMinutiae": [ + "kind": "VAR_TYPE_DESC", + "children": [ { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "VAR_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "e", - "trailingMinutiae": [ + }, { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "e", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] } ] }, @@ -827,28 +837,48 @@ ] }, { - "kind": "ERROR_TYPE_DESC", + "kind": "TYPED_BINDING_PATTERN", "children": [ { - "kind": "ERROR_KEYWORD" - }, - { - "kind": "TYPE_PARAMETER", + "kind": "ERROR_TYPE_DESC", "children": [ { - "kind": "LT_TOKEN" + "kind": "ERROR_KEYWORD" }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPE_PARAMETER", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "E" + "kind": "LT_TOKEN" + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "E" + } + ] + }, + { + "kind": "GT_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] - }, + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ { - "kind": "GT_TOKEN", + "kind": "IDENTIFIER_TOKEN", + "value": "e", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -860,16 +890,6 @@ } ] }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "e", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, { "kind": "BLOCK_STATEMENT", "children": [ diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json index 44e295cf1bd3..8f6984a58f42 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json @@ -592,28 +592,40 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPED_BINDING_PATTERN", + "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "f", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] } ] } ] }, - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - }, { "kind": "BLOCK_STATEMENT", "hasDiagnostics": true, @@ -907,58 +919,70 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPED_BINDING_PATTERN", + "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "f", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] } ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "hasDiagnostics": true, - "value": "w4", - "leadingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - }, - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - }, - { - "kind": "INVALID_NODE_MINUTIAE", - "invalidNode": { - "kind": "INVALID_TOKEN_MINUTIAE_NODE", - "hasDiagnostics": true, - "children": [ - { - "kind": "WORKER_KEYWORD", - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_INVALID_TOKEN" - ] - } - ] - } }, { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "CAPTURE_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "value": "w4", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "WORKER_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] } ] }, From 87e9ce58bb9b487dbb5badd122687d593a8cd234 Mon Sep 17 00:00:00 2001 From: poorna2152 Date: Tue, 21 Nov 2023 16:12:55 +0530 Subject: [PATCH 11/97] Add semantic for worker on fail --- .../compiler/parser/BLangNodeBuilder.java | 13 ++- .../semantics/analyzer/CodeAnalyzer.java | 10 ++- .../test/worker/WorkerOnFailTest.java | 78 ++++++++++++++++ .../test-src/workers/worker-on-fail.bal | 89 +++++++++++++++++++ 4 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 36d2041bbb0b..bc66a64213e5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -1743,7 +1743,18 @@ public BLangNode transform(NamedWorkerDeclarationNode namedWorkerDeclNode) { // Set the function body BLangBlockStmt blockStmt = (BLangBlockStmt) namedWorkerDeclNode.workerBody().apply(this); BLangBlockFunctionBody bodyNode = (BLangBlockFunctionBody) TreeBuilder.createBlockFunctionBodyNode(); - bodyNode.stmts = blockStmt.stmts; + if (namedWorkerDeclNode.onFailClause().isPresent()) { + BLangDo bLDo = (BLangDo) TreeBuilder.createDoNode(); + bLDo.pos = workerBodyPos; + bLDo.setBody(blockStmt); + OnFailClauseNode onFailClauseNode = namedWorkerDeclNode.onFailClause().get(); + bLDo.setOnFailClause( + (org.ballerinalang.model.clauses.OnFailClauseNode) (onFailClauseNode.apply(this))); + bodyNode.addStatement(bLDo); + } else { + bodyNode.stmts = blockStmt.stmts; + } + bodyNode.pos = workerBodyPos; bLFunction.body = bodyNode; bLFunction.internal = true; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index fe7daa9c6550..42f1e46b58e0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1510,12 +1510,15 @@ public void visit(BLangWhile whileNode, AnalyzerData data) { public void visit(BLangDo doNode, AnalyzerData data) { boolean onFailExists = doNode.onFailClause != null; boolean failureHandled = data.failureHandled; + boolean previousWithinDoBlock = data.withinDoBlock; + data.withinDoBlock = true; if (onFailExists) { data.failureHandled = true; } analyzeNode(doNode.body, data); data.failureHandled = failureHandled; analyseOnFailClause(onFailExists, doNode.onFailClause, data); + data.withinDoBlock = previousWithinDoBlock; } @@ -2002,7 +2005,8 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } String workerName = asyncSendExpr.workerIdentifier.getValue(); - if (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (!data.withinDoBlock && (data.withinQuery || + (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2061,7 +2065,8 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - if (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (!data.withinDoBlock && (data.withinQuery || + (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { this.dlog.error(syncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -4256,6 +4261,7 @@ public static class AnalyzerData { boolean loopAlterNotAllowed; // Fields related to worker system boolean inInternallyDefinedBlockStmt; + boolean withinDoBlock; int workerSystemMovementSequence; Stack workerActionSystemStack = new Stack<>(); Map> workerReferences = new HashMap<>(); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java new file mode 100644 index 000000000000..883be193b203 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * + * 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 + * + * 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.worker; + +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; + +import java.util.Arrays; + +/** + * Tests the worker on fail clause. + */ +public class WorkerOnFailTest { + + private CompileResult result; + + @BeforeClass + public void setup() { + this.result = BCompileUtil.compile("test-src/workers/worker-on-fail.bal"); + Assert.assertEquals(result.getErrorCount(), 0, Arrays.asList(result.getDiagnostics()).toString()); + } + + @Test + public void simpleOnFailTest() { + Object returns = BRunUtil.invoke(result, "testOnFailInWorker"); + long ret = (long) returns; + Assert.assertEquals(ret, -1); + } + + @Test + public void doOnFailInsideWorker() { + Object returns = BRunUtil.invoke(result, "testDoOnFailInsideWorker"); + long ret = (long) returns; + Assert.assertEquals(ret, 3); + } + + @Test + public void returnWithinOnFail() { + Object returns = BRunUtil.invoke(result, "testReturnWithinOnFail"); + long ret = (long) returns; + Assert.assertEquals(ret, -1); + } + + @Test + public void onFailWorkerWithVariable() { + Object returns = BRunUtil.invoke(result, "testOnFailWorkerWithVariable"); + long ret = (long) returns; + Assert.assertEquals(ret, 0); + } + + @Test + public void workerOnFailWithSend() { + Object returns = BRunUtil.invoke(result, "testWorkerOnFailWithSend"); + long ret = (long) returns; + Assert.assertEquals(ret, 1); + } + +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal new file mode 100644 index 000000000000..4fbf781f33fa --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal @@ -0,0 +1,89 @@ +function testOnFailInWorker() returns int { + int[] vals = returnIntArr(); + int key = returnOne(); + int val = 0; + + worker A { + int? index = vals.indexOf(key); + if index != () { + val = vals[index]; + } else { + check error("value not found"); + } + } on fail { + val = -1; + } + wait A; + return val; +} + +function testDoOnFailInsideWorker() returns int { + int val = 0; + worker A { + do { + val += 1; + fail error("error in do"); + } on fail { + val += 1; + } + fail error("error for worker"); + } on fail { + val += 1; + } + wait A; + return val; +} + +function testReturnWithinOnFail() returns int { + int x = returnOne(); + worker A returns string { + if (x == 1) { + check error("one"); + } + return "not one"; + } on fail error e { + return e.message(); + } + string str = wait A; + return str == "one" ? -1 : 0; +} + +function testOnFailWorkerWithVariable() returns int { + int x = 0; + worker A { + do { + x += 1; + fail error("error in do"); + } on fail { + x += 1; + } + fail error("error in worker"); + } on fail error e { + if e.message() == "error in worker" { + x -= 2; + } else { + x -= -1; + } + } + wait A; + return x; +} + +function testWorkerOnFailWithSend() returns int { + worker A { + int x = 1; + x -> B; + check error("testWorkerOnFailWithSend"); + } on fail var err { + _ = err.message(); + } + + worker B returns int { + return <- A; + } + return wait B; +} + +function returnOne() returns int => 1; + +function returnIntArr() returns int[] => [2, 3, 4, 5]; From f2bfbf4ddc728f1266fce8fc93062bb543e05eb6 Mon Sep 17 00:00:00 2001 From: poorna2152 Date: Wed, 22 Nov 2023 11:04:53 +0530 Subject: [PATCH 12/97] Update the top level check --- .../compiler/semantics/analyzer/CodeAnalyzer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 42f1e46b58e0..d3237f101ad7 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1510,15 +1510,15 @@ public void visit(BLangWhile whileNode, AnalyzerData data) { public void visit(BLangDo doNode, AnalyzerData data) { boolean onFailExists = doNode.onFailClause != null; boolean failureHandled = data.failureHandled; - boolean previousWithinDoBlock = data.withinDoBlock; - data.withinDoBlock = true; + boolean previousWithinDoBlock = data.withinWorkerTopLevelDo; + data.withinWorkerTopLevelDo = isCommunicationAllowedLocation(data.env) && isInWorker(data.env); if (onFailExists) { data.failureHandled = true; } analyzeNode(doNode.body, data); data.failureHandled = failureHandled; analyseOnFailClause(onFailExists, doNode.onFailClause, data); - data.withinDoBlock = previousWithinDoBlock; + data.withinWorkerTopLevelDo = previousWithinDoBlock; } @@ -2005,7 +2005,7 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } String workerName = asyncSendExpr.workerIdentifier.getValue(); - if (!data.withinDoBlock && (data.withinQuery || + if (!data.withinWorkerTopLevelDo && (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; @@ -2065,7 +2065,7 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - if (!data.withinDoBlock && (data.withinQuery || + if (!data.withinWorkerTopLevelDo && (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { this.dlog.error(syncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; @@ -4261,7 +4261,7 @@ public static class AnalyzerData { boolean loopAlterNotAllowed; // Fields related to worker system boolean inInternallyDefinedBlockStmt; - boolean withinDoBlock; + boolean withinWorkerTopLevelDo; int workerSystemMovementSequence; Stack workerActionSystemStack = new Stack<>(); Map> workerReferences = new HashMap<>(); From 71b5e28bc77e97cdbab3a8192a09d3cd0b4beb3b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 29 Nov 2023 13:01:57 +0530 Subject: [PATCH 13/97] Allow send-action inside if-else --- .../compiler/desugar/Desugar.java | 115 +++++++++++++++++- .../semantics/analyzer/CodeAnalyzer.java | 12 +- .../main/ballerina/auto-close-channels.bal | 25 ++++ .../langlib/internal/AutoCloseChannels.java | 43 +++++++ 4 files changed, 187 insertions(+), 8 deletions(-) create mode 100644 langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal create mode 100644 langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java 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 0c562728fe39..69f93ac5ef8f 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 @@ -221,6 +221,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerAsyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendReceiveExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLCommentLiteral; @@ -363,6 +364,7 @@ public class Desugar extends BLangNodeVisitor { private static final String GENERATED_ERROR_VAR = "$error$"; private static final String HAS_KEY = "hasKey"; private static final String CREATE_RECORD_VALUE = "createRecordFromMap"; + private static final String CHANNEL_AUTO_CLOSE_FUNC_NAME = "autoClose"; public static final String XML_INTERNAL_SELECT_DESCENDANTS = "selectDescendants"; public static final String XML_INTERNAL_CHILDREN = "children"; @@ -416,6 +418,10 @@ public class Desugar extends BLangNodeVisitor { private boolean isVisitingQuery; private boolean desugarToReturn; + // Worker related variables + private boolean withinIfStmt; + private Set channelsWithinIfStmt = new LinkedHashSet<>(); + // Safe navigation related variables private Stack matchStmtStack = new Stack<>(); Stack accessExprStack = new Stack<>(); @@ -3544,13 +3550,105 @@ public void visit(BLangExpressionStmt exprStmtNode) { @Override public void visit(BLangIf ifNode) { + boolean prevWithinIfStmt = this.withinIfStmt; + Set prevChannels = new LinkedHashSet<>(this.channelsWithinIfStmt); + this.withinIfStmt = true; + ifNode.expr = rewriteExpr(ifNode.expr); + + Set ifBlockChannels = new LinkedHashSet<>(); + this.channelsWithinIfStmt = ifBlockChannels; ifNode.body = rewrite(ifNode.body, env); + + Set elseBlockChannels = new LinkedHashSet<>(); + this.channelsWithinIfStmt = elseBlockChannels; ifNode.elseStmt = rewrite(ifNode.elseStmt, env); + addWorkerChannelAutoCloseStmts(ifNode, ifBlockChannels, elseBlockChannels); + + prevChannels.addAll(ifBlockChannels); + prevChannels.addAll(elseBlockChannels); + this.withinIfStmt = prevWithinIfStmt; + this.channelsWithinIfStmt = prevChannels; result = ifNode; } + /** + * We need to close the channels that the send actions are not going to execute in the if-else block. + * This method will add channel auto close function calls at the beginning of if and/or else blocks. + *

+ * If else will be generated as follows: + *

+ * + * if expr { + * autoClose(string ... channelIds); + * stmti1; + * stmti2; + * ... + * } else { + * autoClose(string ... channelIds); + * stmtj1; + * stmtj2; + * ... + * } + * + * + * @param ifNode if-else node + * @param ifBlockChannels channels used in if block + * @param elseBlockChannels channels used in else block + */ + private void addWorkerChannelAutoCloseStmts(BLangIf ifNode, + Set ifBlockChannels, + Set elseBlockChannels) { + if (!elseBlockChannels.isEmpty()) { + ifNode.body.stmts.add(0, generateChannelAutoCloseStmt(elseBlockChannels)); + } + if (!ifBlockChannels.isEmpty()) { + // Three cases to handle: + // 1) No else block + // 2) There is an else block + // 3) Else block itself is an if-else node + + BLangStatement elseStmt = ifNode.elseStmt; + + if (elseStmt == null) { + List stmts = + new ArrayList<>(Collections.singletonList(generateChannelAutoCloseStmt(ifBlockChannels))); + ifNode.elseStmt = rewrite(ASTBuilderUtil.createBlockStmt(symTable.builtinPos, stmts), env); + } else if (elseStmt.getKind() == NodeKind.BLOCK) { + ((BLangBlockStmt) elseStmt).stmts.add(0, generateChannelAutoCloseStmt(ifBlockChannels)); + } else { + assert elseStmt.getKind() == NodeKind.IF; + List stmts = new ArrayList<>(2); + stmts.add(generateChannelAutoCloseStmt(ifBlockChannels)); + stmts.add(elseStmt); + ifNode.elseStmt = rewrite(ASTBuilderUtil.createBlockStmt(elseStmt.pos, stmts), env); + } + } + } + + private BLangExpressionStmt generateChannelAutoCloseStmt(Set channels) { + List restArgs = generateChannelIdLiteralList(channels); + BLangInvocation funcInvocation = createLangLibInvocationNode(CHANNEL_AUTO_CLOSE_FUNC_NAME, new ArrayList<>(), + restArgs, symTable.nilType, symTable.builtinPos); + funcInvocation.internal = true; + + BLangExpressionStmt exprStmt = (BLangExpressionStmt) TreeBuilder.createExpressionStatementNode(); + exprStmt.internal = true; + exprStmt.expr = funcInvocation; + exprStmt.pos = symTable.builtinPos; + return rewrite(exprStmt, env); + } + + private List generateChannelIdLiteralList(Set channels) { + List exprs = new ArrayList<>(); + for (BLangWorkerSendReceiveExpr.Channel channel : channels) { + BLangLiteral channelIdLiteral = createStringLiteral(symTable.builtinPos, channel.channelId()); + exprs.add(channelIdLiteral); + } + return exprs; + } + @Override public void visit(BLangMatchStatement matchStatement) { BLangOnFailClause currentOnFailClause = this.onFailClause; @@ -8146,12 +8244,14 @@ private BLangFunction createUserDefinedObjectInitFn(BLangClassDefinition classDe @Override public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { asyncSendExpr.expr = visitCloneInvocation(rewriteExpr(asyncSendExpr.expr), asyncSendExpr.expr.getBType()); + this.channelsWithinIfStmt.add(asyncSendExpr.getChannel()); result = asyncSendExpr; } @Override public void visit(BLangWorkerSyncSendExpr syncSendExpr) { syncSendExpr.expr = visitCloneInvocation(rewriteExpr(syncSendExpr.expr), syncSendExpr.expr.getBType()); + this.channelsWithinIfStmt.add(syncSendExpr.getChannel()); result = syncSendExpr; } @@ -8881,7 +8981,15 @@ protected BLangInvocation createLangLibInvocationNode(String functionName, } private BLangInvocation createLangLibInvocationNode(String functionName, - List args, + List requiredArgs, + BType retType, + Location pos) { + return createLangLibInvocationNode(functionName, requiredArgs, new ArrayList<>(), retType, pos); + } + + private BLangInvocation createLangLibInvocationNode(String functionName, + List requiredArgs, + List restArgs, BType retType, Location pos) { BLangInvocation invocationNode = (BLangInvocation) TreeBuilder.createInvocationNode(); @@ -8896,9 +9004,8 @@ private BLangInvocation createLangLibInvocationNode(String functionName, invocationNode.symbol = symResolver.lookupMethodInModule(symTable.langInternalModuleSymbol, names.fromString(functionName), env); - ArrayList requiredArgs = new ArrayList<>(); - requiredArgs.addAll(args); - invocationNode.requiredArgs = requiredArgs; + invocationNode.requiredArgs = new ArrayList<>(requiredArgs); + invocationNode.restArgs = new ArrayList<>(restArgs); invocationNode.setBType(retType != null ? retType : ((BInvokableSymbol) invocationNode.symbol).retType); invocationNode.langLibInvocation = true; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index dd4d45ee0d41..a7cb012b0d5a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1958,10 +1958,14 @@ private boolean isInWorker(SymbolEnv env) { return env.enclInvokable.flagSet.contains(Flag.WORKER); } - private boolean isCommunicationAllowedLocation(SymbolEnv env) { + private boolean isReceiveAllowedLocation(SymbolEnv env) { return isTopLevel(env); } + private boolean isSendAllowedLocation(SymbolEnv env) { + return isTopLevel(env) || env.node.parent.getKind() == NodeKind.IF; // TODO: fix properly + } + private boolean isDefaultWorkerCommunication(String workerIdentifier) { return workerIdentifier.equals(DEFAULT_WORKER_NAME); } @@ -2003,7 +2007,7 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } String workerName = asyncSendExpr.workerIdentifier.getValue(); - if (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (data.withinQuery || (!isSendAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2062,7 +2066,7 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - if (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (data.withinQuery || (!isSendAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { this.dlog.error(syncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2113,7 +2117,7 @@ public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { } String workerName = workerReceiveNode.workerIdentifier.getValue(); - if (data.withinQuery || (!isCommunicationAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (data.withinQuery || (!isReceiveAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.INVALID_WORKER_RECEIVE_POSITION); was.hasErrors = true; } diff --git a/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal new file mode 100644 index 000000000000..0ffcebca7db8 --- /dev/null +++ b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal @@ -0,0 +1,25 @@ +// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). +// +// 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 +// +// 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; + +# Auto-closes the specified worker channels if they exist; otherwise, closes them upon creation. +# +# + channelIds - channel IDs of the channels to be closed +public function autoClose(string ... channelIds) = @java:Method { + 'class: "org.ballerinalang.langlib.internal.AutoCloseChannels", + name: "autoClose" +} external; diff --git a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java new file mode 100644 index 000000000000..fc485e9948f1 --- /dev/null +++ b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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.langlib.internal; + +import io.ballerina.runtime.api.values.BString; + +/** + * Native implementation of lang.internal:AutoCloseChannels. + * + * @since 2201.9.0 + */ +public class AutoCloseChannels { + + /** + * Auto-closes the specified worker channels if they exist; otherwise, closes them upon creation. + * + * @param channelIds channel IDs of the channels to be closed + */ + public static void autoClose(BString[] channelIds) { + for (BString channelId : channelIds) { + autoCloseChannel(channelId); + } + } + + private static void autoCloseChannel(BString channelId) { + // TODO: Close channel if exists. Else close it at the creation in future. + } +} From d1eb0146b7aa351a1d47ea7539969e4eb3ec8da3 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Wed, 29 Nov 2023 16:14:40 +0530 Subject: [PATCH 14/97] Add runtime support for alternate receive --- .../internal/scheduling/WDChannels.java | 49 ++++++- .../scheduling/WorkerDataChannel.java | 125 ++++++++++++++---- .../ballerinalang/compiler/bir/BIRGen.java | 31 ++++- .../compiler/bir/codegen/JvmSignatures.java | 1 + .../bir/codegen/JvmTerminatorGen.java | 50 ++++++- .../compiler/bir/model/BIRTerminator.java | 48 +++++++ .../compiler/bir/model/BIRVisitor.java | 4 + .../compiler/bir/model/InstructionKind.java | 1 + .../bir/optimizer/BIRBasicBlockOptimizer.java | 7 + .../bir/optimizer/BIRLockOptimizer.java | 5 + .../compiler/bir/optimizer/BIROptimizer.java | 5 + .../bir/writer/BIRInstructionWriter.java | 8 ++ .../compiler/parser/NodeCloner.java | 3 + .../BLangCombinedWorkerReceive.java | 15 +++ 14 files changed, 316 insertions(+), 36 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index d0e7dca48de1..d84bb778d07d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -17,9 +17,15 @@ */ package io.ballerina.runtime.internal.scheduling; +import io.ballerina.runtime.internal.values.ErrorValue; + +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import static io.ballerina.runtime.internal.scheduling.State.BLOCK_AND_YIELD; + /** * This represents a worker data channel holder that is created for each strand to hold channels required. * @@ -28,10 +34,9 @@ public class WDChannels { private Map wDChannels; + private final List errors = new ArrayList<>(); //TODO try to generalize this to a normal data channel, in that case we won't need these classes. - public WDChannels() { - } public synchronized WorkerDataChannel getWorkerDataChannel(String name) { if (this.wDChannels == null) { @@ -44,4 +49,44 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { } return channel; } + + public Object tryTakeData(Strand strand, List channels) throws Throwable { + Object result = null; + for (String channelName : channels) { + WorkerDataChannel channel = getWorkerDataChannel(channelName); + if (channel.isClosed()) { + continue; + } + + result = channel.tryTakeDataRecursively(strand); + if (result != null) { + if (result instanceof ErrorValue) { + errors.add((ErrorValue) result); + channel.close(); + result = null; + continue; + } else { + closeChannels(channels); + } + break; + } + + } + if (result == null) { + if (errors.size() != channels.size()) { + strand.setState(BLOCK_AND_YIELD); + } else { + result = errors.get(errors.size() -1); + } + } + return result; + } + + private void closeChannels(List channels) { + for (String channelName : channels) { + WorkerDataChannel channel = getWorkerDataChannel(channelName); + channel.close(); + } + } + } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 8b68a02d8801..091ce75ce34e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -1,20 +1,20 @@ /* -* Copyright (c) 2019, 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. -*/ + * Copyright (c) 2019, 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 io.ballerina.runtime.internal.scheduling; import io.ballerina.runtime.internal.values.ErrorValue; @@ -49,17 +49,21 @@ public class WorkerDataChannel { @SuppressWarnings("rawtypes") private Queue channel = new LinkedList<>(); + private State state; public WorkerDataChannel() { this.channelLock = new ReentrantLock(); this.senderCounter = 0; this.receiverCounter = 0; + this.state = State.OPEN; } + public WorkerDataChannel(String channelName) { this.channelLock = new ReentrantLock(); this.senderCounter = 0; this.receiverCounter = 0; this.chnlName = channelName; + this.state = State.OPEN; } public void acquireChannelLock() { @@ -70,13 +74,25 @@ public void releaseChannelLock() { this.channelLock.unlock(); } + public boolean isClosed() { + return this.state == State.CLOSED; + } + + public enum State { + OPEN, CLOSED, FAILED + } + @SuppressWarnings("rawtypes") public void sendData(Object data, Strand sender) { + if (isClosed()) { + return; + } + try { acquireChannelLock(); this.channel.add(new WorkerResult(data)); this.senderCounter++; - if (this.receiver != null) { + if (this.receiver != null && receiver.scheduler != null) { this.receiver.scheduler.unblockStrand(this.receiver); this.receiver = null; } @@ -85,9 +101,18 @@ public void sendData(Object data, Strand sender) { } } + public void close() { + this.state = State.CLOSED; + if (this.receiver != null && this.receiver.isBlocked()) { + this.receiver.scheduler.unblockStrand(this.receiver); + this.receiver = null; + } + } + /** * Put data for sync send. - * @param data - data to be sent over the channel + * + * @param data - data to be sent over the channel * @param strand - sending strand, that will be paused * @return error if receiver already in error state, else null * @throws Throwable panic @@ -149,18 +174,16 @@ public Object tryTakeData(Strand strand) throws Throwable { if (result.isSync) { // sync sender will pick the this.error as result, which is null if (this.waitingSender != null) { - Strand waiting = this.waitingSender.waitingStrand; + Strand waiting = this.waitingSender.waitingStrand; waiting.scheduler.unblockStrand(waiting); this.waitingSender = null; } } else if (this.flushSender != null && this.flushSender.flushCount == this.receiverCounter) { this.flushSender.waitingStrand.flushDetail.flushLock.lock(); this.flushSender.waitingStrand.flushDetail.flushedCount++; - if (this.flushSender.waitingStrand.flushDetail.flushedCount - == this.flushSender.waitingStrand.flushDetail.flushChannels.length && - this.flushSender.waitingStrand.isBlocked()) { - //will continue if this is a sync wait, will try to flush again if blocked on flush - this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); + if (this.flushSender.waitingStrand.flushDetail.flushedCount == this.flushSender.waitingStrand.flushDetail.flushChannels.length && this.flushSender.waitingStrand.isBlocked()) { + //will continue if this is a sync wait, will try to flush again if blocked on flush + this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); } this.flushSender.waitingStrand.flushDetail.flushLock.unlock(); @@ -183,8 +206,51 @@ public Object tryTakeData(Strand strand) throws Throwable { } } + public Object tryTakeDataRecursively(Strand strand) throws Throwable { + try { + acquireChannelLock(); + WorkerResult result = this.channel.peek(); + if (result != null) { + this.receiverCounter++; + this.channel.remove(); + + if (result.isSync) { + // sync sender will pick the this.error as result, which is null + if (this.waitingSender != null) { + Strand waiting = this.waitingSender.waitingStrand; + waiting.scheduler.unblockStrand(waiting); + this.waitingSender = null; + } + } else if (this.flushSender != null && this.flushSender.flushCount == this.receiverCounter) { + this.flushSender.waitingStrand.flushDetail.flushLock.lock(); + this.flushSender.waitingStrand.flushDetail.flushedCount++; + if (this.flushSender.waitingStrand.flushDetail.flushedCount == this.flushSender.waitingStrand.flushDetail.flushChannels.length && this.flushSender.waitingStrand.isBlocked()) { + //will continue if this is a sync wait, will try to flush again if blocked on flush + this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); + + } + this.flushSender.waitingStrand.flushDetail.flushLock.unlock(); + this.flushSender = null; + } + return result.value; + } else if (this.panic != null && this.senderCounter == this.receiverCounter + 1) { + this.receiverCounter++; + throw this.panic; + } else if (this.error != null && this.senderCounter == this.receiverCounter + 1) { + this.receiverCounter++; + return error; + } else { + this.receiver = strand; + return null; + } + } finally { + releaseChannelLock(); + } + } + /** * Set the state as error if the receiving worker is in error state. + * * @param error the BError of the receiving worker */ public void setSendError(ErrorValue error) { @@ -263,9 +329,12 @@ public void removeFlushWait() { * @param panic to be set */ public void setSendPanic(Throwable panic) { + if (isClosed()) { + return; + } try { acquireChannelLock(); - this.panic = panic; + this.panic = panic; this.senderCounter++; if (this.receiver != null) { this.receiver.scheduler.unblockStrand(this.receiver); @@ -282,8 +351,11 @@ public void setSendPanic(Throwable panic) { * @param panic to be set */ public void setReceiverPanic(Throwable panic) { + if (isClosed()) { + return; + } acquireChannelLock(); - this.panic = panic; + this.panic = panic; this.receiverCounter++; if (this.flushSender != null) { this.flushSender.waitingStrand.flushDetail.flushLock.lock(); @@ -314,7 +386,6 @@ public static class WorkerResult { public Object value; public boolean isSync; - public WorkerResult(Object value) { this.value = value; } 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 206967f53e83..8a17f1c1f5dc 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 @@ -1145,8 +1145,35 @@ public void visit(BLangForkJoin forkJoin) { @Override public void visit(BLangCombinedWorkerReceive combinedWorkerReceive) { - // TODO: 22/11/23 implement - throw new AssertionError("alternate/multiple receive not yet implemented"); + if (combinedWorkerReceive.getKind() == NodeKind.ALTERNATE_WORKER_RECEIVE) { + BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); + addToTrapStack(thenBB); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(combinedWorkerReceive.getBType(), + this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(tempVarDcl); + BIROperand lhsOp = new BIROperand(tempVarDcl); + this.env.targetOperand = lhsOp; + + boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); + + this.env.enclBB.terminator = new BIRTerminator.WorkerAlternateReceive(combinedWorkerReceive.pos, + getChannelList(combinedWorkerReceive), lhsOp, isOnSameStrand, thenBB, this.currentScope); + + this.env.enclBasicBlocks.add(thenBB); + this.env.enclBB = thenBB; + + } else { + // TODO: 22/11/23 implement + throw new AssertionError("multiple receive not yet implemented"); + } + } + + private List getChannelList(BLangCombinedWorkerReceive combinedWorkerReceive) { + List channels = new ArrayList<>(); + for (BLangWorkerReceive workerReceive : combinedWorkerReceive.getWorkerReceives()) { + channels.add(workerReceive.getChannel().channelId()); + } + return channels; } @Override 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 bd5051f6b0ee..a36f35124bf6 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 @@ -499,6 +499,7 @@ public class JvmSignatures { public static final String GET_TOML_DETAILS = "()L" + TOML_DETAILS + ";"; public static final String GET_TEST_CONFIG_PATH = "(L" + MODULE + ";L" + STRING_VALUE + ";L" + STRING_VALUE + ";)L" + TOML_DETAILS + ";"; + public static final String ALT_RECEIVE_CALL = "(L" + STRAND_CLASS + ";L" + LIST + ";)L" + OBJECT + ";"; private JvmSignatures() { } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index d8cb660f1c77..3738d2b5b877 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -150,6 +150,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.WORKER_DATA_CHANNEL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.WORKER_UTILS; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmInstructionGen.addJUnboxInsn; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.ALT_RECEIVE_CALL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.ANNOTATION_GET_STRAND; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.ANY_TO_JBOOLEAN; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.BAL_ENV_PARAM; @@ -385,6 +386,10 @@ public void genTerminator(BIRTerminator terminator, String moduleClassName, BIRN case WK_RECEIVE: this.genWorkerReceiveIns((BIRTerminator.WorkerReceive) terminator, localVarOffset, invocationVarIndex); return; + case WK_ALT_RECEIVE: + this.genWorkerAlternateReceiveIns((BIRTerminator.WorkerAlternateReceive) terminator, localVarOffset, + invocationVarIndex); + return; case FLUSH: this.genFlushIns((BIRTerminator.Flush) terminator, localVarOffset, invocationVarIndex); return; @@ -1193,6 +1198,40 @@ private void genWorkerSendIns(BIRTerminator.WorkerSend ins, int localVarOffset, } } + private void genWorkerAlternateReceiveIns(BIRTerminator.WorkerAlternateReceive ins, int localVarOffset, + int invocationVarIndex) { + BIRNode.BIRVariableDcl listVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("channels"), + VarScope.FUNCTION, VarKind.LOCAL); + int channelIndex = this.getJVMIndexOfVarRef(listVar); + this.mv.visitTypeInsn(NEW, ARRAY_LIST); + this.mv.visitInsn(DUP); + this.mv.visitMethodInsn(INVOKESPECIAL, ARRAY_LIST, JVM_INIT_METHOD, VOID_METHOD_DESC, false); + + int i = 0; + while (i < ins.channels.size()) { + this.mv.visitInsn(DUP); + this.mv.visitVarInsn(ILOAD, invocationVarIndex); + this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, + new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, + HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), + ins.channels.get(i) + START_OF_HEADING_WITH_SEMICOLON); + this.mv.visitMethodInsn(INVOKEINTERFACE, LIST, ADD_METHOD, ANY_TO_JBOOLEAN, true); + this.mv.visitInsn(POP); + i += 1; + } + this.mv.visitVarInsn(ASTORE, channelIndex); + this.mv.visitVarInsn(ALOAD, localVarOffset); + if (!ins.isSameStrand) { + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); + } + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); + this.mv.visitVarInsn(ALOAD, localVarOffset); + this.mv.visitVarInsn(ALOAD, channelIndex); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "tryTakeData", ALT_RECEIVE_CALL, false); + + generateReceiveResultStore(ins.lhsOp); + } + private void genWorkerReceiveIns(BIRTerminator.WorkerReceive ins, int localVarOffset, int invocationVarIndex) { this.mv.visitVarInsn(ALOAD, localVarOffset); @@ -1209,9 +1248,11 @@ private void genWorkerReceiveIns(BIRTerminator.WorkerReceive ins, int localVarOf this.mv.visitVarInsn(ALOAD, localVarOffset); this.mv.visitMethodInsn(INVOKEVIRTUAL, WORKER_DATA_CHANNEL, "tryTakeData", TRY_TAKE_DATA, false); + generateReceiveResultStore(ins.lhsOp); + } - BIRNode.BIRVariableDcl tempVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("wrkMsg"), - VarScope.FUNCTION, VarKind.ARG); + private void generateReceiveResultStore(BIROperand ins) { + BIRNode.BIRVariableDcl tempVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("wrkMsg"), VarScope.FUNCTION, VarKind.ARG); int wrkResultIndex = this.getJVMIndexOfVarRef(tempVar); this.mv.visitVarInsn(ASTORE, wrkResultIndex); @@ -1222,9 +1263,8 @@ private void genWorkerReceiveIns(BIRTerminator.WorkerReceive ins, int localVarOf Label withinReceiveSuccess = new Label(); this.mv.visitLabel(withinReceiveSuccess); this.mv.visitVarInsn(ALOAD, wrkResultIndex); - jvmCastGen.addUnboxInsn(this.mv, ins.lhsOp.variableDcl.type); - this.storeToVar(ins.lhsOp.variableDcl); - + jvmCastGen.addUnboxInsn(this.mv, ins.variableDcl.type); + this.storeToVar(ins.variableDcl); this.mv.visitLabel(jumpAfterReceive); } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java index 4dd37845dfee..d85d2c2b39f3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java @@ -679,6 +679,54 @@ public BIRBasicBlock[] getNextBasicBlocks() { } } + + /** + * A worker receive instruction for alternate receive. + *

+ * e.g., WRK_RECEIVE w1 | w2; + * + * @since 2201.9.0 + */ + public static class WorkerAlternateReceive extends BIRTerminator { + public List channels; + public boolean isSameStrand; + + public WorkerAlternateReceive(Location pos, List channels, BIROperand lhsOp, + boolean isSameStrand, BIRBasicBlock thenBB) { + super(pos, InstructionKind.WK_ALT_RECEIVE); + this.channels = channels; + this.thenBB = thenBB; + this.isSameStrand = isSameStrand; + this.lhsOp = lhsOp; + } + + public WorkerAlternateReceive(Location pos, List channels, BIROperand lhsOp, boolean isSameStrand, + BIRBasicBlock thenBB, BirScope scope) { + this(pos, channels, lhsOp, isSameStrand, thenBB); + this.scope = scope; + } + + @Override + public void accept(BIRVisitor visitor) { + visitor.visit(this); + } + + @Override + public BIROperand[] getRhsOperands() { + return new BIROperand[0]; + } + + @Override + public void setRhsOperands(BIROperand[] operands) { + // do nothing + } + + @Override + public BIRBasicBlock[] getNextBasicBlocks() { + return new BIRBasicBlock[]{thenBB}; + } + } + /** * A worker send instruction. *

diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java index ec35bfbefc2e..a2c0630ea0f2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java @@ -142,6 +142,10 @@ public void visit(BIRTerminator.WorkerSend workerSend) { throw new AssertionError(); } + public void visit(BIRTerminator.WorkerAlternateReceive altReceive) { + throw new AssertionError(); + } + // Non-terminating instructions diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java index 2f17d01ffe2b..e7fec1928f30 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java @@ -38,6 +38,7 @@ public enum InstructionKind { FIELD_LOCK((byte) 12), UNLOCK((byte) 13), WAIT_ALL((byte) 14), + WK_ALT_RECEIVE((byte) 15), // Non-terminating instructions MOVE((byte) 20), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRBasicBlockOptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRBasicBlockOptimizer.java index 20e740584fdf..a53698cbc86a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRBasicBlockOptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRBasicBlockOptimizer.java @@ -281,4 +281,11 @@ public void visit(BIRTerminator.WorkerSend workerSend) { workerSend.thenBB = this.env.nextBB; } } + + @Override + public void visit(BIRTerminator.WorkerAlternateReceive workerAlternateReceive) { + if (workerAlternateReceive.thenBB == this.env.currentBB) { + workerAlternateReceive.thenBB = this.env.nextBB; + } + } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java index 045caf512a88..f8e3ea7d4781 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java @@ -248,6 +248,11 @@ public void visit(BIRTerminator.WorkerSend workerSend) { // Do nothing } + @Override + public void visit(BIRTerminator.WorkerAlternateReceive workerAlternateReceive) { + // Do nothing + } + @Override public void visit(BIRNode.BIRBasicBlock birBasicBlock) { BIRTerminator terminator = birBasicBlock.terminator; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java index d06c0300edf1..9123ec8d82de 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java @@ -468,6 +468,11 @@ public void visit(BIRTerminator.WorkerSend workerSend) { this.optimizeNode(workerSend.data, this.env); } + @Override + public void visit(BIRTerminator.WorkerAlternateReceive workerReceive) { + this.optimizeNode(workerReceive.lhsOp, this.env); + } + // Non-terminating instructions @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java index c0957fc1d929..1d56eef465df 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java @@ -233,6 +233,14 @@ public void visit(BIRTerminator.WorkerSend entry) { addCpAndWriteString(entry.thenBB.id.value); } + @Override + public void visit(BIRTerminator.WorkerAlternateReceive entry) { + entry.channels.forEach(key -> buf.writeInt(addStringCPEntry(key))); + entry.lhsOp.accept(this); + buf.writeBoolean(entry.isSameStrand); + addCpAndWriteString(entry.thenBB.id.value); + } + public void visit(BIRTerminator.WaitAll waitAll) { waitAll.lhsOp.accept(this); buf.writeInt(waitAll.keys.size()); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index 756147925137..d26f307be13a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -1027,6 +1027,7 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { asyncSendExpr.cloneRef = clone; clone.expr = clone(asyncSendExpr.expr); clone.workerIdentifier = asyncSendExpr.workerIdentifier; + clone.setChannel(asyncSendExpr.getChannel()); } @Override @@ -1049,6 +1050,7 @@ public void visit(BLangWorkerReceive source) { source.cloneRef = clone; clone.workerIdentifier = source.workerIdentifier; + clone.setChannel(source.getChannel()); } @Override @@ -2206,6 +2208,7 @@ public void visit(BLangWorkerSyncSendExpr source) { source.cloneRef = clone; clone.workerIdentifier = source.workerIdentifier; clone.expr = clone(source.expr); + clone.setChannel(source.getChannel()); } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java index 1c5b49acb11f..72153f8d2e2a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangCombinedWorkerReceive.java @@ -72,4 +72,19 @@ public List getWorkerReceives() { public void setWorkerReceives(List workerReceives) { this.workerReceives = workerReceives; } + + @Override + public String toString() { + return "CombinedWorkerReceive: " + this.toActionString(); + } + + public String toActionString() { + StringBuilder sb = new StringBuilder(" <- "); + int size = workerReceives.size(); + for (int i = 0; i < size - 1; i++) { + sb.append(workerReceives.get(i)).append(" | "); + } + sb.append(workerReceives.get(size - 1)); + return sb.toString(); + } } From a2324abfff776cb1caaaf831591a14b48024ef01 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 29 Nov 2023 20:15:24 +0530 Subject: [PATCH 15/97] Fix syntax tree for receive-field parsing --- .../internal/parser/BallerinaParser.java | 2 +- .../receive_action_assert_01.json | 36 ++++- .../receive_action_assert_02.json | 42 ++++-- .../receive_action_assert_03.json | 24 ++- .../worker-decl/worker_decl_assert_06.json | 90 ++++++----- .../worker-decl/worker_decl_assert_07.json | 142 ++++++++++-------- 6 files changed, 215 insertions(+), 121 deletions(-) diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 3848831490bc..b61086dcc011 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13220,7 +13220,7 @@ private STNode parseReceiveField() { private STNode createQualifiedReceiveField(STNode identifier) { if (peek().kind != SyntaxKind.COLON_TOKEN) { - return identifier; + return STNodeFactory.createSimpleNameReferenceNode(identifier); } STNode colon = parseColon(); diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index e3df09a6bc30..3c10de8636e7 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -265,8 +265,13 @@ "kind": "LIST", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a" + } + ] } ] }, @@ -343,8 +348,13 @@ "kind": "LIST", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a" + } + ] }, { "kind": "COMMA_TOKEN", @@ -386,8 +396,13 @@ ] }, { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] } ] }, @@ -486,8 +501,13 @@ ] }, { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index e5e65cac1548..69578d6cb6f2 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -312,12 +312,17 @@ "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] }, @@ -360,8 +365,13 @@ ] }, { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] } ] }, @@ -442,8 +452,13 @@ "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a" + } + ] }, { "kind": "COMMA_TOKEN", @@ -616,8 +631,13 @@ ] }, { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json index 730063a807c6..22dce87315d4 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json @@ -120,12 +120,17 @@ "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] }, @@ -188,8 +193,13 @@ ] }, { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json index 2dd9dec55296..a489150893d5 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_06.json @@ -595,26 +595,36 @@ ] }, { - "kind": "VAR_TYPE_DESC", + "kind": "TYPED_BINDING_PATTERN", "children": [ { - "kind": "VAR_KEYWORD", - "trailingMinutiae": [ + "kind": "VAR_TYPE_DESC", + "children": [ { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "VAR_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "e", - "trailingMinutiae": [ + }, { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "e", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] } ] }, @@ -827,28 +837,48 @@ ] }, { - "kind": "ERROR_TYPE_DESC", + "kind": "TYPED_BINDING_PATTERN", "children": [ { - "kind": "ERROR_KEYWORD" - }, - { - "kind": "TYPE_PARAMETER", + "kind": "ERROR_TYPE_DESC", "children": [ { - "kind": "LT_TOKEN" + "kind": "ERROR_KEYWORD" }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPE_PARAMETER", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "E" + "kind": "LT_TOKEN" + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "E" + } + ] + }, + { + "kind": "GT_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] } ] - }, + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ { - "kind": "GT_TOKEN", + "kind": "IDENTIFIER_TOKEN", + "value": "e", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -860,16 +890,6 @@ } ] }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "e", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, { "kind": "BLOCK_STATEMENT", "children": [ diff --git a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json index 44e295cf1bd3..8f6984a58f42 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json +++ b/compiler/ballerina-parser/src/test/resources/misc/worker-decl/worker_decl_assert_07.json @@ -592,28 +592,40 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPED_BINDING_PATTERN", + "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "f", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] } ] } ] }, - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - }, { "kind": "BLOCK_STATEMENT", "hasDiagnostics": true, @@ -907,58 +919,70 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "TYPED_BINDING_PATTERN", + "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "f", - "trailingMinutiae": [ + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" + "kind": "IDENTIFIER_TOKEN", + "value": "f", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] } ] - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "hasDiagnostics": true, - "value": "w4", - "leadingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - }, - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - }, - { - "kind": "INVALID_NODE_MINUTIAE", - "invalidNode": { - "kind": "INVALID_TOKEN_MINUTIAE_NODE", - "hasDiagnostics": true, - "children": [ - { - "kind": "WORKER_KEYWORD", - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_INVALID_TOKEN" - ] - } - ] - } }, { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " + "kind": "CAPTURE_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "value": "w4", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "WORKER_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] } ] }, From 8ca659cd2983f2e2886a0203e1db878397f2a755 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 30 Nov 2023 05:05:20 +0530 Subject: [PATCH 16/97] Fix checkstyle error --- .../ballerina/runtime/internal/scheduling/WDChannels.java | 8 ++++---- .../runtime/internal/scheduling/WorkerDataChannel.java | 8 ++++++-- .../compiler/bir/codegen/JvmTerminatorGen.java | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index d84bb778d07d..329b8e410abd 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -74,11 +74,11 @@ public Object tryTakeData(Strand strand, List channels) throws Throwable } if (result == null) { if (errors.size() != channels.size()) { - strand.setState(BLOCK_AND_YIELD); - } else { - result = errors.get(errors.size() -1); - } + strand.setState(BLOCK_AND_YIELD); + } else { + result = errors.get(errors.size() - 1); } + } return result; } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 091ce75ce34e..8a3e9f67174b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -181,7 +181,9 @@ public Object tryTakeData(Strand strand) throws Throwable { } else if (this.flushSender != null && this.flushSender.flushCount == this.receiverCounter) { this.flushSender.waitingStrand.flushDetail.flushLock.lock(); this.flushSender.waitingStrand.flushDetail.flushedCount++; - if (this.flushSender.waitingStrand.flushDetail.flushedCount == this.flushSender.waitingStrand.flushDetail.flushChannels.length && this.flushSender.waitingStrand.isBlocked()) { + if (this.flushSender.waitingStrand.flushDetail.flushedCount == + this.flushSender.waitingStrand.flushDetail.flushChannels.length && + this.flushSender.waitingStrand.isBlocked()) { //will continue if this is a sync wait, will try to flush again if blocked on flush this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); @@ -224,7 +226,9 @@ public Object tryTakeDataRecursively(Strand strand) throws Throwable { } else if (this.flushSender != null && this.flushSender.flushCount == this.receiverCounter) { this.flushSender.waitingStrand.flushDetail.flushLock.lock(); this.flushSender.waitingStrand.flushDetail.flushedCount++; - if (this.flushSender.waitingStrand.flushDetail.flushedCount == this.flushSender.waitingStrand.flushDetail.flushChannels.length && this.flushSender.waitingStrand.isBlocked()) { + if (this.flushSender.waitingStrand.flushDetail.flushedCount == + this.flushSender.waitingStrand.flushDetail.flushChannels.length && + this.flushSender.waitingStrand.isBlocked()) { //will continue if this is a sync wait, will try to flush again if blocked on flush this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 3738d2b5b877..79b92d62f7a9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -1252,7 +1252,8 @@ private void genWorkerReceiveIns(BIRTerminator.WorkerReceive ins, int localVarOf } private void generateReceiveResultStore(BIROperand ins) { - BIRNode.BIRVariableDcl tempVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("wrkMsg"), VarScope.FUNCTION, VarKind.ARG); + BIRNode.BIRVariableDcl tempVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("wrkMsg"), + VarScope.FUNCTION, VarKind.ARG); int wrkResultIndex = this.getJVMIndexOfVarRef(tempVar); this.mv.visitVarInsn(ASTORE, wrkResultIndex); From b56670da75036b1c9e771b5c91508624babf4b34 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 30 Nov 2023 10:27:19 +0530 Subject: [PATCH 17/97] Add alternate receive tests --- .../worker/WorkerAlternateReceiveTest.java | 65 ++++++ .../test-src/workers/workers_alt_receive.bal | 218 ++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java new file mode 100644 index 000000000000..53435337ebe8 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * + * 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 + * + * 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.worker; + +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * worker alternative receive related tests. + */ +public class WorkerAlternateReceiveTest { + + private CompileResult result; + + @BeforeClass + public void setup() { + this.result = BCompileUtil.compile("test-src/workers/workers_alt_receive.bal"); + Assert.assertEquals(result.getErrorCount(), 0); + } + + @Test(dataProvider = "FunctionProvider") + public void workerAlternateReceiveTest(String funcName) { + BRunUtil.invoke(result, funcName, new Object[0]); + } + + @DataProvider + public static String[] FunctionProvider() { + return new String[] { + "workerAlternateReceiveTest", + "workerAlternateReceiveTest2", + "alternateReceiveWithPanic", + "alternateReceiveWithMultiplePanic", + "alternateReceiveWithError", + "alternateReceiveWithMultipleError", + "alternateReceiveWithPanicAndError" + }; + } + + @AfterClass + public void tearDown() { + result = null; + } +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal new file mode 100644 index 000000000000..4a81aea1a627 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal @@ -0,0 +1,218 @@ +// Copyright (c) 2023 WSO2 LLC. +// +// 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 +// +// 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/test; +import ballerina/lang.runtime; + +function workerAlternateReceiveTest() { + worker w1 { + 2 -> w2; + } + + worker w2 returns int { + int result = <- w1 | w3; + return result; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + worker w4 { + runtime:sleep(2); + 2 -> w5; + } + + worker w5 returns int { + int result = <- w4 | w6; + return result; + } + + worker w6 { + 3 -> w5; + } + + map results = wait {a: w2, b: w5}; + test:assertEquals(results["a"], 2, "Invalid int result"); + test:assertEquals(results["b"], 3, "Invalid int result"); +} + +function workerAlternateReceiveTest2() { + worker w1 { + runtime:sleep(2); + 1 -> w5; + } + + worker w2 { + runtime:sleep(3); + 2 -> w5; + } + + worker w3 { + 3 -> w5; + } + + worker w4 { + runtime:sleep(4); + 4 -> w5; + } + + worker w5 returns int { + int result = <- w1 | w2 | w3 | w4; + return result; + } + + int result = wait w5; + test:assertEquals(result, 3, "Invalid int result"); +} + +function alternateReceiveWithPanic() { + worker w1 { + int value = 10; + if value == 10 { + panic error("Error in worker 1"); + } + value -> w2; + } + + worker w2 returns int { + int a = <- w1 | w3; + return a; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + int|error unionResult = trap wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} + +function alternateReceiveWithMultiplePanic() { + worker w1 { + int value = 10; + if value == 10 { + panic error("Error in worker 1"); + } + value -> w2; + } + + worker w2 returns int { + int a = <- w1 | w3; + return a; + } + + worker w3 { + int value = 10; + if value == 10 { + panic error("Error in worker 3"); + } + 3 -> w2; + } + + int|error unionResult = trap wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + boolean validError = e.message() == "Error in worker 1" || e.message() == "Error in worker 3"; + test:assertTrue(validError, "Invalid error message"); +} + +function alternateReceiveWithError() { + worker w1 returns error? { + int value = 10; + if value == 10 { + return error("Error in worker 1"); + } + value -> w2; + } + + worker w2 returns int|error { + int|error a = <- w1 | w3; + return a; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + int|error unionResult = wait w2; + test:assertTrue(unionResult is int, "Expected int result"); + test:assertEquals(unionResult, 3, "Invalid int result"); +} + +function alternateReceiveWithMultipleError() { + worker w1 returns error? { + int value = 10; + if value == 10 { + return error("Error in worker 1"); + } + value -> w2; + } + + worker w2 returns int|error { + int|error a = <- w1 | w3; + return a; + } + + worker w3 returns error? { + int value = 10; + runtime:sleep(2); + if value == 10 { + return error("Error in worker 3"); + } + value -> w2; + } + + int|error unionResult = wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 3", "Invalid error message"); +} + + + +function alternateReceiveWithPanicAndError() { + worker w1 { + int value = 10; + if value == 10 { + panic error("Error in worker 1"); + } + value -> w2; + } + + worker w2 returns int|error { + int|error a = <- w1 | w3; + return a; + } + + worker w3 returns error? { + int value = 10; + if value == 10 { + return error("Error in worker 3"); + } + value -> w2; + } + + int|error unionResult = trap wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} From d3e765c78a9efaab06e555fe5b5ca368b60dda9a Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 30 Nov 2023 10:52:43 +0530 Subject: [PATCH 18/97] Refactor receive logic --- .../internal/scheduling/WDChannels.java | 2 +- .../scheduling/WorkerDataChannel.java | 48 ++----------------- .../worker/WorkerAlternateReceiveTest.java | 4 +- 3 files changed, 8 insertions(+), 46 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 329b8e410abd..da179c0260a0 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -58,7 +58,7 @@ public Object tryTakeData(Strand strand, List channels) throws Throwable continue; } - result = channel.tryTakeDataRecursively(strand); + result = channel.tryTakeData(strand, true); if (result != null) { if (result instanceof ErrorValue) { errors.add((ErrorValue) result); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 8a3e9f67174b..1371b187b7f0 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -164,51 +164,10 @@ public Object syncSendData(Object data, Strand strand) throws Throwable { @SuppressWarnings("rawtypes") public Object tryTakeData(Strand strand) throws Throwable { - try { - acquireChannelLock(); - WorkerResult result = this.channel.peek(); - if (result != null) { - this.receiverCounter++; - this.channel.remove(); - - if (result.isSync) { - // sync sender will pick the this.error as result, which is null - if (this.waitingSender != null) { - Strand waiting = this.waitingSender.waitingStrand; - waiting.scheduler.unblockStrand(waiting); - this.waitingSender = null; - } - } else if (this.flushSender != null && this.flushSender.flushCount == this.receiverCounter) { - this.flushSender.waitingStrand.flushDetail.flushLock.lock(); - this.flushSender.waitingStrand.flushDetail.flushedCount++; - if (this.flushSender.waitingStrand.flushDetail.flushedCount == - this.flushSender.waitingStrand.flushDetail.flushChannels.length && - this.flushSender.waitingStrand.isBlocked()) { - //will continue if this is a sync wait, will try to flush again if blocked on flush - this.flushSender.waitingStrand.scheduler.unblockStrand(this.flushSender.waitingStrand); - - } - this.flushSender.waitingStrand.flushDetail.flushLock.unlock(); - this.flushSender = null; - } - return result.value; - } else if (this.panic != null && this.senderCounter == this.receiverCounter + 1) { - this.receiverCounter++; - throw this.panic; - } else if (this.error != null && this.senderCounter == this.receiverCounter + 1) { - this.receiverCounter++; - return error; - } else { - this.receiver = strand; - strand.setState(BLOCK_AND_YIELD); - return null; - } - } finally { - releaseChannelLock(); - } + return tryTakeData(strand, false); } - public Object tryTakeDataRecursively(Strand strand) throws Throwable { + public Object tryTakeData(Strand strand, boolean isMultiple) throws Throwable { try { acquireChannelLock(); WorkerResult result = this.channel.peek(); @@ -245,6 +204,9 @@ public Object tryTakeDataRecursively(Strand strand) throws Throwable { return error; } else { this.receiver = strand; + if (!isMultiple) { + strand.setState(BLOCK_AND_YIELD); + } return null; } } finally { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index 53435337ebe8..df93407491f5 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -40,13 +40,13 @@ public void setup() { Assert.assertEquals(result.getErrorCount(), 0); } - @Test(dataProvider = "FunctionProvider") + @Test(dataProvider = "functionProvider") public void workerAlternateReceiveTest(String funcName) { BRunUtil.invoke(result, funcName, new Object[0]); } @DataProvider - public static String[] FunctionProvider() { + public static String[] functionProvider() { return new String[] { "workerAlternateReceiveTest", "workerAlternateReceiveTest2", From 6b2bff4fdd3f266b203feeff83e6620a37462da3 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 1 Dec 2023 10:07:24 +0530 Subject: [PATCH 19/97] Remove unnecessary lines --- .../internal/scheduling/WorkerDataChannel.java | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 1371b187b7f0..b2042908fb4a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -59,11 +59,8 @@ public WorkerDataChannel() { } public WorkerDataChannel(String channelName) { - this.channelLock = new ReentrantLock(); - this.senderCounter = 0; - this.receiverCounter = 0; + this(); this.chnlName = channelName; - this.state = State.OPEN; } public void acquireChannelLock() { @@ -79,7 +76,7 @@ public boolean isClosed() { } public enum State { - OPEN, CLOSED, FAILED + OPEN, CLOSED } @SuppressWarnings("rawtypes") @@ -103,10 +100,6 @@ public void sendData(Object data, Strand sender) { public void close() { this.state = State.CLOSED; - if (this.receiver != null && this.receiver.isBlocked()) { - this.receiver.scheduler.unblockStrand(this.receiver); - this.receiver = null; - } } /** @@ -295,9 +288,6 @@ public void removeFlushWait() { * @param panic to be set */ public void setSendPanic(Throwable panic) { - if (isClosed()) { - return; - } try { acquireChannelLock(); this.panic = panic; @@ -317,9 +307,6 @@ public void setSendPanic(Throwable panic) { * @param panic to be set */ public void setReceiverPanic(Throwable panic) { - if (isClosed()) { - return; - } acquireChannelLock(); this.panic = panic; this.receiverCounter++; From f4e8e53ef7902fd1b815b57b814ff0b383269920 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 1 Dec 2023 10:09:57 +0530 Subject: [PATCH 20/97] Remove unnecessary lines --- .../ballerina/runtime/internal/scheduling/WorkerDataChannel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index b2042908fb4a..1c9258257a77 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -84,7 +84,6 @@ public void sendData(Object data, Strand sender) { if (isClosed()) { return; } - try { acquireChannelLock(); this.channel.add(new WorkerResult(data)); From 3d38a9d0597d8a95718fcc9dfca6e247bc9a4b71 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 1 Dec 2023 10:24:56 +0530 Subject: [PATCH 21/97] Add more tests --- .../worker/WorkerAlternateReceiveTest.java | 6 ++- .../test-src/workers/workers_alt_receive.bal | 52 +++++++++++++++++-- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index df93407491f5..097855829fcb 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -50,11 +50,13 @@ public static String[] functionProvider() { return new String[] { "workerAlternateReceiveTest", "workerAlternateReceiveTest2", - "alternateReceiveWithPanic", + "alternateReceiveWithSenderPanic", "alternateReceiveWithMultiplePanic", "alternateReceiveWithError", "alternateReceiveWithMultipleError", - "alternateReceiveWithPanicAndError" + "alternateReceiveWithPanicAndError", + "alternateReceiveWithReceiverPanic", + "alternateReceiveWithReceiverError" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal index 4a81aea1a627..fddc2f8bec08 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal @@ -80,7 +80,7 @@ function workerAlternateReceiveTest2() { test:assertEquals(result, 3, "Invalid int result"); } -function alternateReceiveWithPanic() { +function alternateReceiveWithSenderPanic() { worker w1 { int value = 10; if value == 10 { @@ -187,8 +187,6 @@ function alternateReceiveWithMultipleError() { test:assertEquals(e.message(), "Error in worker 3", "Invalid error message"); } - - function alternateReceiveWithPanicAndError() { worker w1 { int value = 10; @@ -216,3 +214,51 @@ function alternateReceiveWithPanicAndError() { error e = unionResult; test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); } + +function alternateReceiveWithReceiverPanic() { + worker w1 { + 10 -> w2; + } + + worker w2 returns int { + int value = 10; + if value == 10 { + panic error("Error in worker 2"); + } + int a = <- w1 | w3; + return a; + } + + worker w3 { + 3 -> w2; + } + + int|error unionResult = trap wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 2", "Invalid error message"); +} + +function alternateReceiveWithReceiverError() { + worker w1 { + 10 -> w2; + } + + worker w2 returns int|error { + int value = 10; + if value == 10 { + return error("Error in worker 2"); + } + int a = <- w1 | w3; + return a; + } + + worker w3 { + 3 -> w2; + } + + int|error unionResult = wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 2", "Invalid error message"); +} From 08089a0a7204cc72c8969752117fa52844e4ba72 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 1 Dec 2023 10:26:52 +0530 Subject: [PATCH 22/97] Rename error test --- .../ballerinalang/test/worker/WorkerAlternateReceiveTest.java | 2 +- .../src/test/resources/test-src/workers/workers_alt_receive.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index 097855829fcb..b42a0dce754a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -52,7 +52,7 @@ public static String[] functionProvider() { "workerAlternateReceiveTest2", "alternateReceiveWithSenderPanic", "alternateReceiveWithMultiplePanic", - "alternateReceiveWithError", + "alternateReceiveWithSenderError", "alternateReceiveWithMultipleError", "alternateReceiveWithPanicAndError", "alternateReceiveWithReceiverPanic", diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal index fddc2f8bec08..cdf2bae3a95c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal @@ -134,7 +134,7 @@ function alternateReceiveWithMultiplePanic() { test:assertTrue(validError, "Invalid error message"); } -function alternateReceiveWithError() { +function alternateReceiveWithSenderError() { worker w1 returns error? { int value = 10; if value == 10 { From 65dc784bb0bc6d6c5ccb68fc6f7aa019db4a3c53 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 4 Dec 2023 13:26:51 +0530 Subject: [PATCH 23/97] Fix compiler tests --- .../util/diagnostic/DiagnosticErrorCode.java | 2 +- .../ballerinalang/compiler/bir/BIRGen.java | 3 +- .../BasicWorkerActionsNegativeTest.java | 92 +++++++++---------- .../test/worker/WorkerFailTest.java | 27 ------ .../ballerinalang/test/worker/WorkerTest.java | 2 +- .../test-src/workers/actions-negative.bal | 5 +- .../test-src/workers/invalid-send-in-if.bal | 16 ---- .../workers/invalid-sync-send-in-fork.bal | 25 ----- .../workers/invalid-sync-send-in-if.bal | 16 ---- 9 files changed, 48 insertions(+), 140 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-in-if.bal delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-fork.bal delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-if.bal diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 803c86eb1310..9f79e4e65244 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -722,7 +722,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { MISMATCHED_VISIBILITY_QUALIFIERS_IN_OBJECT_FIELD( "BCE3988", "mismatched.visibility.qualifiers.in.object.field"), INVALID_INCLUSION_OF_OBJECT_WITH_PRIVATE_MEMBERS("BCE3989", "invalid.inclusion.of.object.with.private.members"), - // Vacant error code: BCE3990 + MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE3990", "multiple.receive.action.not.yet.supported"), INVALID_READONLY_FIELD_TYPE("BCE3991", "invalid.readonly.field.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 9926d2f95270..a6e1fb6de618 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 @@ -33,6 +33,7 @@ import org.ballerinalang.model.tree.OperatorKind; import org.ballerinalang.model.tree.TopLevelNode; import org.ballerinalang.model.tree.expressions.RecordLiteralNode; +import org.ballerinalang.util.diagnostic.DiagnosticErrorCode; 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; @@ -1173,7 +1174,7 @@ private List getChannelList(BLangAlternateWorkerReceive alternateWorkerR @Override public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { // TODO: 24/11/23 implement - throw new AssertionError("multiple receive not yet implemented"); + throw new AssertionError(DiagnosticErrorCode.MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED); } @Override diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java index 6eaf9b90c43a..70023f72aebf 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java @@ -63,67 +63,61 @@ public void testNegativeWorkerActions() { BAssertUtil.validateError(resultNegative, index++, "invalid worker flush expression for 'w1', there are no " + "worker send statements to 'w1' from 'w3'", 62, 17); BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'val'", 63, 9); - BAssertUtil.validateError(resultNegative, index++, "worker send statement position not supported yet, " + - "must be a top level statement in a worker", 76, 13); - BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'msg'", 81, 9); + BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'msg'", 78, 9); BAssertUtil.validateError(resultNegative, index++, "invalid worker receive statement position, must be a " + - "top level statement in a worker", 83, 19); - BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'x1'", 91, 9); - BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'x2'", 92, 9); - BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'result'", 93, 9); + "top level statement in a worker", 80, 19); + BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'x1'", 88, 9); + BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'x2'", 89, 9); + BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'result'", 90, 9); BAssertUtil.validateError(resultNegative, index++, "invalid worker flush expression for 'w2', there are no " + - "worker send statements to 'w2' from 'w1'", 93, 25); - BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'j'", 100, 9); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 144, 26); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 161, 26); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 162, 26); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 166, 25); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 167, 22); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 168, 25); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 169, 21); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 190, 17); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 198, 30); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 200, 26); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 218, 30); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 219, 30); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 220, 75); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 226, 29); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 227, 26); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 228, 29); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 229, 25); - BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 231, 21); + "worker send statements to 'w2' from 'w1'", 90, 25); + BAssertUtil.validateWarning(resultNegative, index++, "unused variable 'j'", 97, 9); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 141, 26); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 158, 26); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 159, 26); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 163, 25); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 164, 22); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 165, 25); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 166, 21); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 187, 17); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 195, 30); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 197, 26); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 215, 30); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 216, 30); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 217, 75); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 223, 29); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wix"), 224, 26); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 225, 29); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wx"), 226, 25); + BAssertUtil.validateError(resultNegative, index++, formatMessage("wy"), 228, 21); String notSupportedMsg = "worker send statement position not supported yet, " + "must be a top level statement in a worker"; - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 244, 13); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 246, 17); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 252, 13); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 253, 13); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 257, 13); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 258, 13); - BAssertUtil.validateError(resultNegative, index++, "unreachable code", 261, 9); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 249, 13); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 250, 13); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 254, 13); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 255, 13); + BAssertUtil.validateError(resultNegative, index++, "unreachable code", 258, 9); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 260, 17); BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 263, 17); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 266, 17); - BAssertUtil.validateError(resultNegative, index++, "undefined worker 'w1'", 271, 26); + BAssertUtil.validateError(resultNegative, index++, "undefined worker 'w1'", 268, 26); BAssertUtil.validateError(resultNegative, index++, - "invalid worker receive statement position, must be a top level statement in a worker", 278, 21); + "invalid worker receive statement position, must be a top level statement in a worker", 275, 21); BAssertUtil.validateError(resultNegative, index++, - "invalid worker receive statement position, must be a top level statement in a worker", 283, 17); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 290, 26); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 292, 30); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 298, 26); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 299, 26); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 303, 26); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 304, 26); - BAssertUtil.validateError(resultNegative, index++, "unreachable code", 307, 22); + "invalid worker receive statement position, must be a top level statement in a worker", 280, 17); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 295, 26); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 296, 26); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 300, 26); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 301, 26); + BAssertUtil.validateError(resultNegative, index++, "unreachable code", 304, 22); + BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 306, 30); BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 309, 30); - BAssertUtil.validateError(resultNegative, index++, notSupportedMsg, 312, 30); - BAssertUtil.validateError(resultNegative, index++, "undefined worker 'w1'", 317, 39); + BAssertUtil.validateError(resultNegative, index++, "undefined worker 'w1'", 314, 39); BAssertUtil.validateError(resultNegative, index++, - "invalid worker receive statement position, must be a top level statement in a worker", 324, 34); + "invalid worker receive statement position, must be a top level statement in a worker", 321, 34); BAssertUtil.validateError(resultNegative, index++, - "invalid worker receive statement position, must be a top level statement in a worker", 329, 30); + "invalid worker receive statement position, must be a top level statement in a worker", 326, 30); Assert.assertEquals(resultNegative.getDiagnostics().length, index, "Worker actions negative test diagnostic count"); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 7c9d4c241d00..23a029fc03e4 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -139,24 +139,6 @@ public void testSyncSendReceiveMismatch() { validateWarning(result, 3, "unused variable 'err'", 47, 5); } - @Test - public void invalidSendInIf() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-send-in-if.bal"); - String message = Arrays.toString(result.getDiagnostics()); - Assert.assertEquals(result.getErrorCount(), 1, message); - Assert.assertTrue(message.contains("worker send statement position not supported yet, " + - "must be a top level statement in a worker"), message); - } - - @Test - public void invalidSyncSendInIf() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-sync-send-in-if.bal"); - String message = Arrays.toString(result.getDiagnostics()); - Assert.assertEquals(result.getErrorCount(), 1, message); - Assert.assertTrue(message.contains("worker send statement position not supported yet, " + - "must be a top level statement in a worker"), message); - } - @Test public void invalidReceiveInIf() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-receive-in-if.bal"); @@ -238,15 +220,6 @@ public void invalidAsyncSendInFork() { "must be a top level statement in a worker"), message); } - @Test - public void invalidSyncSendInFork() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-sync-send-in-fork.bal"); - String message = Arrays.toString(result.getDiagnostics()); - Assert.assertEquals(result.getErrorCount(), 1, message); - Assert.assertTrue(message.contains("worker send statement position not supported yet, " + - "must be a top level statement in a worker"), message); - } - @Test public void invalidReceiveInFork() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-receive-in-fork.bal"); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java index fd68cb46d6f6..0699890879ab 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java @@ -342,7 +342,7 @@ public void testWorkerInsideLock() { BAssertUtil.validateError(result, index++, "cannot use a named worker inside a lock statement", 42, 20); } - @Test + @Test (enabled = false) public void testMultipleReceiveAction() { // Multiple receive action is not yet supported. This is to test the error message. CompileResult result = BCompileUtil.compile("test-src/workers/multiple-receive-action.bal"); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/actions-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/actions-negative.bal index 5641b8b7e4b1..145c6a733eb6 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/actions-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/actions-negative.bal @@ -71,11 +71,8 @@ function workerActionSecTest() { string msg = "hello"; msg -> w2; - - if (true) { - i -> w2; - } } + worker w2 { print("w1"); string msg = "default"; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-in-if.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-in-if.bal deleted file mode 100644 index e281c959d004..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-in-if.bal +++ /dev/null @@ -1,16 +0,0 @@ - - -public function main() { - worker w1{ - int i = 20; - if (0 > 1) { - i -> w2; - } - } - - worker w2 { - int j = 25; - j = <- w1; - } -} - diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-fork.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-fork.bal deleted file mode 100644 index 672a1e065efa..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-fork.bal +++ /dev/null @@ -1,25 +0,0 @@ -public function main() { - fork { - worker w1{ - int i = 20; - } - - worker w2 { - int j = 25; - int sum = 0; - fork { - worker w3 { - foreach var i in 1... 10 { - sum = sum + i; - if (true) { - var xx = i ->> w4; - } - } - } - worker w4 { - int k = <- w3; - } - } - } - } -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-if.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-if.bal deleted file mode 100644 index 194ae6479259..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-sync-send-in-if.bal +++ /dev/null @@ -1,16 +0,0 @@ - - -public function main() { - worker w1{ - int i = 20; - if(true){ - var ans = i ->> w2; - } - } - - worker w2 { - int j = 25; - j = <- w1; - } -} - From 2aca5dea5c90633c295ea424c97a39c946b60d2a Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Fri, 8 Dec 2023 11:53:53 +0530 Subject: [PATCH 24/97] Fix issue with autoClose() stmts --- .../org/wso2/ballerinalang/compiler/desugar/Desugar.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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 69f93ac5ef8f..bcd6239d72f4 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 @@ -419,7 +419,6 @@ public class Desugar extends BLangNodeVisitor { private boolean desugarToReturn; // Worker related variables - private boolean withinIfStmt; private Set channelsWithinIfStmt = new LinkedHashSet<>(); // Safe navigation related variables @@ -3550,10 +3549,7 @@ public void visit(BLangExpressionStmt exprStmtNode) { @Override public void visit(BLangIf ifNode) { - boolean prevWithinIfStmt = this.withinIfStmt; - Set prevChannels = new LinkedHashSet<>(this.channelsWithinIfStmt); - this.withinIfStmt = true; - + Set prevChannels = this.channelsWithinIfStmt; ifNode.expr = rewriteExpr(ifNode.expr); Set ifBlockChannels = new LinkedHashSet<>(); @@ -3568,7 +3564,6 @@ public void visit(BLangIf ifNode) { prevChannels.addAll(ifBlockChannels); prevChannels.addAll(elseBlockChannels); - this.withinIfStmt = prevWithinIfStmt; this.channelsWithinIfStmt = prevChannels; result = ifNode; } From 2da36e894ec09949fca64646c085a10a38f54d5f Mon Sep 17 00:00:00 2001 From: Nipuna Fernando Date: Fri, 8 Dec 2023 15:06:32 +0530 Subject: [PATCH 25/97] Add display annotation support for worker --- .../src/main/ballerina/annotations.bal | 2 +- .../annotations/DisplayAnnotationTest.java | 21 ++++++++++++++++++- .../test-src/annotations/display_annot.bal | 11 ++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/langlib/lang.annotations/src/main/ballerina/annotations.bal b/langlib/lang.annotations/src/main/ballerina/annotations.bal index d697461e45e3..9575dcd4f092 100644 --- a/langlib/lang.annotations/src/main/ballerina/annotations.bal +++ b/langlib/lang.annotations/src/main/ballerina/annotations.bal @@ -103,4 +103,4 @@ public const annotation record { "text"|"password"|"file" kind?; } display on source type, source class, source function, source return, source parameter, source field, source listener, - source var, source const, source annotation, source service; + source var, source const, source annotation, source service, source worker; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/DisplayAnnotationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/DisplayAnnotationTest.java index 3b6c09cba9a3..09533f15043d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/DisplayAnnotationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/annotations/DisplayAnnotationTest.java @@ -18,6 +18,7 @@ import org.ballerinalang.model.tree.AnnotationAttachmentNode; import org.ballerinalang.model.tree.ClassDefinition; +import org.ballerinalang.model.tree.FunctionNode; import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.tree.SimpleVariableNode; import org.ballerinalang.model.tree.TypeDefinition; @@ -30,13 +31,17 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; 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.BLangFunction; import org.wso2.ballerinalang.compiler.tree.BLangPackage; import org.wso2.ballerinalang.compiler.tree.BLangService; import org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangInvocation; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangLambdaFunction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangTypeConversionExpr; +import org.wso2.ballerinalang.compiler.tree.statements.BLangSimpleVariableDef; +import org.wso2.ballerinalang.compiler.tree.statements.BLangStatement; import java.util.List; @@ -91,7 +96,7 @@ public void testDisplayAnnotOnObjectAndMemberFunction() { @Test public void testDisplayAnnotOnRecord() { - TypeDefinition typeDefinition = result.getAST().getTypeDefinitions().get(13); + TypeDefinition typeDefinition = result.getAST().getTypeDefinitions().get(14); List annot = typeDefinition.getAnnotationAttachments(); Assert.assertEquals(annot.size(), 1); Assert.assertEquals(annot.get(0).getExpression().toString(), @@ -104,6 +109,20 @@ public void testDisplayAnnotOnRecord() { "clientSecret field,kind: <\"text\"|\"password\"|\"file\"?> password}"); } + @Test + public void testDisplayAnnotOnWorker() { + BLangBlockFunctionBody bLangBlockFunctionBody = + ((BLangBlockFunctionBody) result.getAST().getFunctions().get(2).getBody()); + BLangStatement bLangStatement = bLangBlockFunctionBody.getStatements().get(1); + FunctionNode workerExpression = + ((BLangLambdaFunction) ((BLangSimpleVariableDef) bLangStatement).getVariable() + .getInitialExpression()).getFunctionNode(); + BLangAnnotationAttachment annot = + (BLangAnnotationAttachment) workerExpression.getAnnotationAttachments().get(0); + Assert.assertEquals(getActualExpressionFromAnnotationAttachmentExpr(annot.expr).toString(), + " {label: worker annotation,type: named,id: hash}"); + } + @Test void testDisplayAnnotationNegative() { BAssertUtil.validateError(negative, 0, "cannot specify more than one annotation value " + "for annotation 'ballerina/lang.annotations:0.0.0:display'", 17, 1); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/display_annot.bal b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/display_annot.bal index e7cff1656913..8d5a12eda12f 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/annotations/display_annot.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/annotations/display_annot.bal @@ -74,3 +74,14 @@ public type RefreshTokenGrantConfig record {| @display {iconPath: "Field.icon", label: "clientSecret field", kind: "password"} string clientSecret; |}; + +function annotationOnWorker() { + @display { + label: "worker annotation", + 'type: "named", + id: "hash" + } + worker testWorker { + + } +} From 99b64956073915f44ffbd4de53c8f7c390d1bebe Mon Sep 17 00:00:00 2001 From: hindujaB Date: Sat, 9 Dec 2023 17:11:40 +0530 Subject: [PATCH 26/97] Add conditional send runtime support --- .../runtime/internal/ErrorUtils.java | 5 +++ .../runtime/internal/errors/ErrorCodes.java | 3 +- .../runtime/internal/errors/ErrorReasons.java | 2 ++ .../internal/scheduling/WDChannels.java | 13 +++++--- .../scheduling/WorkerDataChannel.java | 31 +++++++++++++++++-- .../main/resources/MessagesBundle.properties | 1 + .../ballerinalang/compiler/bir/BIRGen.java | 3 +- .../langlib/internal/AutoCloseChannels.java | 12 +++++-- 8 files changed, 58 insertions(+), 12 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java index 0d3a563afb5d..19b12306d8d7 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java @@ -187,4 +187,9 @@ public static BError createInvalidFractionDigitsError() { ErrorReasons.INVALID_FRACTION_DIGITS_ERROR), ErrorHelper.getErrorDetails(ErrorCodes.INVALID_FRACTION_DIGITS)); } + + public static BError createNoMessageError(String chnlName) { + return createError(ErrorReasons.NO_MESSAGE_ERROR, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, + StringUtils.fromString(chnlName.split(":")[0]))); + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java index a969630c6a83..f5e14c224077 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java @@ -149,7 +149,8 @@ public enum ErrorCodes implements DiagnosticCode { REGEXP_INVALID_HEX_DIGIT("regexp.invalid.hex.digit", "RUNTIME_0120"), CONFIG_TOML_INVALID_MODULE_STRUCTURE_WITH_VARIABLE("config.toml.invalid.module.structure.with.variable", "RUNTIME_0121"), - EMPTY_XML_SEQUENCE_HAS_NO_ATTRIBUTES("empty.xml.sequence.no.attributes", "RUNTIME_0122"); + EMPTY_XML_SEQUENCE_HAS_NO_ATTRIBUTES("empty.xml.sequence.no.attributes", "RUNTIME_0122"), + NO_MESSAGE_ERROR("no.worker.message.received", "RUNTIME_0123" ); private final String errorMsgKey; private final String errorCode; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java index 9daa5d928554..9cdfbf5b10ba 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java @@ -133,6 +133,8 @@ private ErrorReasons() {} public static final BString REGEXP_OPERATION_ERROR = getModulePrefixedReason(REGEXP_LANG_LIB, "RegularExpressionOperationError"); + public static final BString NO_MESSAGE_ERROR = StringUtils.fromString("NoMessageError"); + public static BString getModulePrefixedReason(String moduleName, String identifier) { return StringUtils.fromString(BALLERINA_ORG_PREFIX.concat(moduleName) .concat(CLOSING_CURLY_BRACE).concat(identifier)); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index da179c0260a0..56e05d3f5cce 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -17,6 +17,7 @@ */ package io.ballerina.runtime.internal.scheduling; +import io.ballerina.runtime.internal.ErrorUtils; import io.ballerina.runtime.internal.values.ErrorValue; import java.util.ArrayList; @@ -52,12 +53,16 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { public Object tryTakeData(Strand strand, List channels) throws Throwable { Object result = null; + boolean allChannelsClosed = true; for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); if (channel.isClosed()) { + if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { + errors.add((ErrorValue) ErrorUtils.createNoMessageError(channelName)); + } continue; } - + allChannelsClosed = false; result = channel.tryTakeData(strand, true); if (result != null) { if (result instanceof ErrorValue) { @@ -73,10 +78,10 @@ public Object tryTakeData(Strand strand, List channels) throws Throwable } if (result == null) { - if (errors.size() != channels.size()) { - strand.setState(BLOCK_AND_YIELD); - } else { + if (errors.size() == channels.size()) { result = errors.get(errors.size() - 1); + } else if (!allChannelsClosed) { + strand.setState(BLOCK_AND_YIELD); } } return result; diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 1c9258257a77..f125f771f096 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -17,6 +17,7 @@ */ package io.ballerina.runtime.internal.scheduling; +import io.ballerina.runtime.internal.ErrorUtils; import io.ballerina.runtime.internal.values.ErrorValue; import java.util.LinkedList; @@ -72,11 +73,28 @@ public void releaseChannelLock() { } public boolean isClosed() { - return this.state == State.CLOSED; + return this.state == State.CLOSED || this.state == State.AUTO_CLOSED; + } + + private void close(State state) { + try { + acquireChannelLock(); + this.state = state; + if (this.receiver != null) { + this.receiver.scheduler.unblockStrand(this.receiver); + this.receiver = null; + } + } finally { + releaseChannelLock(); + } + } + + public State getState() { + return this.state; } public enum State { - OPEN, CLOSED + OPEN, AUTO_CLOSED, CLOSED } @SuppressWarnings("rawtypes") @@ -97,8 +115,12 @@ public void sendData(Object data, Strand sender) { } } + public void autoClose() { + close(State.AUTO_CLOSED); + } + public void close() { - this.state = State.CLOSED; + close(State.CLOSED); } /** @@ -162,6 +184,9 @@ public Object tryTakeData(Strand strand) throws Throwable { public Object tryTakeData(Strand strand, boolean isMultiple) throws Throwable { try { acquireChannelLock(); + if (isClosed()) { + throw ErrorUtils.createNoMessageError(chnlName); + } WorkerResult result = this.channel.peek(); if (result != null) { this.receiverCounter++; diff --git a/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties b/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties index 297d6b945c74..f3727c57521e 100644 --- a/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties +++ b/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties @@ -263,3 +263,4 @@ regexp.invalid.unicode.general.category.value = invalid Unicode general category regexp.invalid.unicode.property.value = invalid Unicode property value ''{0}'' regexp.empty.character.class.disallowed = empty character class disallowed regexp.invalid.hex.digit = invalid hexadecimal digit +no.worker.message.received = no worker message received for channel ''{0}'' 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 a6e1fb6de618..451ce0dbb812 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 @@ -1150,7 +1150,8 @@ public void visit(BLangForkJoin forkJoin) { public void visit(BLangAlternateWorkerReceive altWorkerReceive) { BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); addToTrapStack(thenBB); - BIRVariableDcl tempVarDcl = new BIRVariableDcl(altWorkerReceive.getBType(), this.env.nextLocalVarId(names), VarScope.FUNCTION, VarKind.TEMP); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(altWorkerReceive.getBType(), this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); this.env.enclFunc.localVars.add(tempVarDcl); BIROperand lhsOp = new BIROperand(tempVarDcl); this.env.targetOperand = lhsOp; diff --git a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java index fc485e9948f1..000eedddeb19 100644 --- a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java +++ b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java @@ -18,6 +18,9 @@ package org.ballerinalang.langlib.internal; import io.ballerina.runtime.api.values.BString; +import io.ballerina.runtime.internal.scheduling.Scheduler; +import io.ballerina.runtime.internal.scheduling.Strand; +import io.ballerina.runtime.internal.scheduling.WorkerDataChannel; /** * Native implementation of lang.internal:AutoCloseChannels. @@ -32,12 +35,15 @@ public class AutoCloseChannels { * @param channelIds channel IDs of the channels to be closed */ public static void autoClose(BString[] channelIds) { + Strand parent = Scheduler.getStrand().parent; for (BString channelId : channelIds) { - autoCloseChannel(channelId); + String channelName = channelId.getValue() + ":" + (parent.functionInvocation - 1); + autoCloseChannel(channelName, parent); } } - private static void autoCloseChannel(BString channelId) { - // TODO: Close channel if exists. Else close it at the creation in future. + private static void autoCloseChannel(String channelId, Strand parent) { + WorkerDataChannel workerDataChannel = parent.wdChannels.getWorkerDataChannel(channelId); + workerDataChannel.autoClose(); } } From ba12ba61fefddae93ad83db70f0f874b58e36062 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Sat, 9 Dec 2023 17:12:04 +0530 Subject: [PATCH 27/97] Add more tests --- .../test/query/QueryActionOrExprTest.java | 14 +- .../worker/WorkerAlternateReceiveTest.java | 8 +- .../worker/WorkerConditionalSendTest.java | 73 ++++ .../test-src/workers/workers_alt_receive.bal | 116 ++++++ .../workers/workers_conditional_send.bal | 374 ++++++++++++++++++ 5 files changed, 572 insertions(+), 13 deletions(-) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java index ee5cb48fc591..658f912fd9c3 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java @@ -114,18 +114,8 @@ public void testQueryActionOrExprSemanticsNegative() { validateError(negativeResult, i++, "incompatible types: 'other' is not an iterable collection", 151, 27); validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 151, 27); validateError(negativeResult, i++, "incompatible types: 'other' is not an iterable collection", 168, 27); - validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 168, 27); - validateError(negativeResult, i++, "multiple receive action not yet supported", 168, 30); - validateError(negativeResult, i++, "multiple receive action not yet supported", 169, 28); - validateError(negativeResult, i++, "multiple receive action not yet supported", 170, 23); - validateError(negativeResult, i++, "multiple receive action not yet supported", 179, 28); - validateError(negativeResult, i++, "multiple receive action not yet supported", 180, 23); - validateError(negativeResult, i++, "multiple receive action not yet supported", 189, 28); - validateError(negativeResult, i++, "multiple receive action not yet supported", 191, 23); - validateError(negativeResult, i++, "multiple receive action not yet supported", 200, 28); - validateError(negativeResult, i++, "multiple receive action not yet supported", 202, 23); - validateError(negativeResult, i++, "multiple receive action not yet supported", 211, 28); - validateError(negativeResult, i++, "multiple receive action not yet supported", 213, 23); + validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 168, 31); + validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 168, 35); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 279, 15); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 291, 18); validateError(negativeResult, i++, "order by not supported for complex type fields, order key should " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index b42a0dce754a..09b07b7b64d0 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -56,7 +56,13 @@ public static String[] functionProvider() { "alternateReceiveWithMultipleError", "alternateReceiveWithPanicAndError", "alternateReceiveWithReceiverPanic", - "alternateReceiveWithReceiverError" + "alternateReceiveWithReceiverError", + "alternateReceiveWithSameWorkerSend", + "alternateReceiveWithSameWorkerSendError1", + "alternateReceiveWithSameWorkerSendError2", + "alternateReceiveWithSameWorkerSendPanic", + "multilpleAlternateReceive1", + "multilpleAlternateReceive2" }; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java new file mode 100644 index 000000000000..3de594598054 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * + * 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 + * + * 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.worker; + +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * worker conditional send related tests. + */ +public class WorkerConditionalSendTest { + + private CompileResult result; + + @BeforeClass + public void setup() { + this.result = BCompileUtil.compile("test-src/workers/workers_conditional_send.bal"); + Assert.assertEquals(result.getErrorCount(), 0); + } + + @Test(dataProvider = "functionProvider") + public void workerConditionalSendTest(String funcName) { + BRunUtil.invoke(result, funcName, new Object[0]); + } + + @DataProvider + public static String[] functionProvider() { + return new String[] { + "workerConditionalSendTest", + "sameWorkerSendTest", + "sameWorkerSendEitherOnePath", + "sameWorkerSendAltReceiveSendError", + "sameWorkerSendAltReceiveReceiverError", + "sameWorkerSendElse", + "sameWorkerSendSenderPanic", + "sameWorkerSendReceiverPanic", + "sameWorkerSendMultiplePath1", + "sameWorkerSendMultiplePath2", + // TODO: Enable these tests when it is compiling +// "sameWorkerSendMultiplePathError1", +// "sameWorkerSendMultiplePathError2", +// "multipleReceiveConditional" + "multipleReceiveWithNonConditionalSend" + }; + } + + @AfterClass + public void tearDown() { + result = null; + } +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal index cdf2bae3a95c..7f25b63dfb95 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal @@ -262,3 +262,119 @@ function alternateReceiveWithReceiverError() { error e = unionResult; test:assertEquals(e.message(), "Error in worker 2", "Invalid error message"); } + +function alternateReceiveWithSameWorkerSend() { + worker w1 { + 1 -> w2; + 2 -> w2; + } + + worker w2 returns int { + int x = <- w1 | w1; + return x; + } + + int intResult = wait w2; + test:assertEquals(intResult, 1, "Invalid int result"); +} + +function alternateReceiveWithSameWorkerSendError1() { + worker w1 { + int|error x = int:fromString("invalid"); + x -> w2; + 2 -> w2; + } + + worker w2 returns int|error { + int|error x = <- w1 | w1; + return x; + } + + int|error intResult = wait w2; + test:assertEquals(intResult, 2, "Invalid int result"); +} + + +function alternateReceiveWithSameWorkerSendError2() { + worker w1 { + int|error x = int:fromString("invalid"); + x -> w2; + x -> w2; + } + + worker w2 returns int|error { + int|error x = <- w1 | w1; + return x; + } + + int|error intResult = wait w2; + test:assertTrue(intResult is error, "Expected error result"); + error e = intResult; + test:assertEquals(e.message(), "{ballerina/lang.int}NumberParsingError", "Invalid error result"); + test:assertEquals(e.detail().toString(), "{\"message\":\"'string' value 'invalid' cannot be converted to 'int'\"}", + "Invalid error result"); +} + +function alternateReceiveWithSameWorkerSendPanic() { + worker w1 { + int x = checkpanic int:fromString("invalid"); + x -> w2; + 2 -> w2; + } + + worker w2 returns int { + int x = <- w1 | w1; + return x; + } + + int|error intResult = trap wait w2; + test:assertTrue(intResult is error, "Expected error result"); + error e = intResult; + test:assertEquals(e.message(), "{ballerina/lang.int}NumberParsingError", "Invalid error result"); + test:assertEquals(e.detail().toString(), "{\"message\":\"'string' value 'invalid' cannot be converted to 'int'\"}", + "Invalid error result"); + } + + function multilpleAlternateReceive1() { + worker w1 { + 1 -> w2; + 2 -> w2; + } + + worker w2 returns [int, int] { + int x = <- w1 | w3; + int y = <- w1; + return [x, y]; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + [int, int] [x, y] = wait w2; + test:assertEquals(x, 1, "Invalid int result"); + test:assertEquals(y, 2, "Invalid int result"); + } + + function multilpleAlternateReceive2() { + worker w1 { + runtime:sleep(2); + 1 -> w2; + 2 -> w2; + } + + worker w2 returns [int, int] { + int x = <- w1 | w3; + int y = <- w1; + return [x, y]; + } + + worker w3 { + 3 -> w2; + } + + [int, int] [x, y] = wait w2; + test:assertEquals(x, 3, "Invalid int result"); + test:assertEquals(y, 2, "Invalid int result"); + } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal new file mode 100644 index 000000000000..34bd5cb336ff --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -0,0 +1,374 @@ +// Copyright (c) 2023 WSO2 LLC. +// +// 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 +// +// 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/test; + +function workerConditionalSendTest() { + boolean foo = true; + + worker w1 { + if foo { + 1 -> w2; + } else { + 2 -> w3; + } + } + + worker w2 returns int { + int a = <- w1; + return a; + } + + worker w3 { + int b = <- w1; + int c = <- w4; + } + + worker w4 { + if !foo { + 1 -> w3; + } else { + 2 -> w5; + } + } + + worker w5 returns int { + int d = <- w4; + return d; + } + + map results = wait {a: w2, b: w5}; + test:assertEquals(results["a"], 1, "Invalid int result"); + test:assertEquals(results["b"], 2, "Invalid int result"); +} + +function sameWorkerSendTest() { + boolean foo = true; + + worker w1 { + if foo { + 10 -> w2; + } else { + 20 -> w2; + } + } + + worker w2 { + int a = <- w1; + int|error b = trap <- w1; + test:assertEquals(a, 10, "Invalid int result"); + test:assertTrue(b is error); + error e = b; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w2'\"}", "Invalid error detail"); + } + + _ = wait {a: w1, b: w2}; +} + +function sameWorkerSendEitherOnePath() { + boolean foo = true; + + worker w1 { + if foo { + 10 -> w2; + } else { + 20 -> w2; + } + } + + worker w2 { + int a = <- w1 | w1; + test:assertEquals(a, 10, "Invalid int result"); + } + + _ = wait {a: w1, b: w2}; +} + +function sameWorkerSendAltReceiveSendError() { + boolean foo = true; + + worker w1 returns error? { + if foo { + if foo && true { + return error("Error in worker 1"); + } else { + 10 -> w2; + } + } else { + 20 -> w2; + } + } + + worker w2 { + int|error a = <- w1 | w1; + test:assertTrue(a is error, "Invalid error result"); + error e = a; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w2'\"}", "Invalid error detail"); + } + error? unionResult = wait w1; + test:assertTrue(unionResult is error, "Invalid error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} + +function sameWorkerSendAltReceiveReceiverError() { + boolean foo = true; + + worker w1 returns error? { + if foo { + if foo && true { + return error("Error in worker 1"); + } else { + 10 -> w2; + } + } else { + 20 -> w2; + } + } + + worker w2 returns int|error { + int value = 10; + if value == 10 { + return error("Error in worker 2"); + } + int|error a = <- w1 | w1; + return a; + } + + int|error unionResult = wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 2", "Invalid error message"); +} + +function sameWorkerSendElse() { + boolean foo = false; + + worker w1 returns error? { + if foo { + if foo && true { + return error("Error in worker 1"); + } else { + 10 -> w2; + } + } else { + 20 -> w2; + } + } + + worker w2 { + int|error a = <- w1 | w1; + test:assertTrue(a is int, "Invalid int result"); + test:assertEquals(a, 20, "Wrong int value received"); + } + + error? unionResult = wait w1; + test:assertTrue(unionResult is (), "Invalid result"); +} + +function sameWorkerSendSenderPanic() { + + boolean foo = true; + + worker w1 { + if foo { + if foo && true { + panic error("Error in worker 1"); + } else { + 10 -> w2; + } + } else { + 20 -> w2; + } + } + + worker w2 { + int a = <- w1 | w1; + } + + error? unionResult = trap wait w1; + test:assertTrue(unionResult is error, "Invalid error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} + +function sameWorkerSendReceiverPanic() { + boolean foo = true; + + worker w1 { + if foo { + 10 -> w2; + } else { + 20 -> w2; + } + } + + worker w2 returns int { + int value = 10; + if value == 10 { + panic error("Error in worker 2"); + } + int a = <- w1 | w1; + return a; + } + + int|error unionResult = trap wait w2; + test:assertTrue(unionResult is error, "Expected error result"); + error e = unionResult; + test:assertEquals(e.message(), "Error in worker 2", "Invalid error message"); +} + +function sameWorkerSendMultiplePath1() { + boolean foo = true; + + worker w1 { + if foo { + 1 -> w2; + } + 2 -> w2; + } + + worker w2 returns int { + int a = <- w1 | w1; + return a; + } + + int intResult = wait w2; + test:assertEquals(intResult, 1, "Invalid int result"); +} + +function sameWorkerSendMultiplePath2() { + boolean foo = false; + + worker w1 { + if foo { + 1 -> w2; + } + 2 -> w2; + } + + worker w2 returns int { + int a = <- w1 | w1; + return a; + } + + int intResult = wait w2; + test:assertEquals(intResult, 2, "Invalid int result"); +} + +// TODO: Enable these tests when it is compiling +// function sameWorkerSendMultiplePathError1() { +// boolean foo = false; + +// worker w1 returns error? { +// int value = 10; +// if foo { +// if value == 10 { +// return error("Error in worker 1"); +// } +// 1 -> w2; +// } +// 2 -> w2; +// } + +// worker w2 returns int|error { +// int|error a = <- w1 | w1; +// return a; +// } + +// map mapResult = wait { a : w1, b: w2}; +// test:assertTrue(mapResult["a"] is error, "Invalid error result"); +// test:assertEquals(mapResult["b"], 2, "Invalid int result"); +// } + +// function sameWorkerSendMultiplePathError2() { +// boolean foo = false; + +// worker w1 returns error? { +// int value = 10; +// if foo { +// 1 -> w2; +// } +// if value == 10 { +// return error("Error in worker 1"); +// } +// 2 -> w2; +// } + +// worker w2 returns int|error { +// int|error a = <- w1 | w1; +// return a; +// } + +// map mapResult = wait { a : w1, b: w2}; +// test:assertTrue(mapResult["a"] is error, "Invalid error result"); +// test:assertEquals(mapResult["b"], 1, "Invalid int result"); +// } + +// function multipleReceiveConditional() { +// boolean foo = true; +// worker w1 returns int { +// if (foo) { +// 2 -> w2; +// int y = <- w3; +// return y; +// } else { +// 2-> w3; +// } +// return 0; +// } + +// worker w2 returns int { +// int y = <- w1; +// return y; +// } + +// worker w3 returns int { +// int y = <- w1; +// 3 -> w1; +// return y; +// } + +// map mapResult = wait {a: w1, b: w2, c: w3}; +// test:assertEquals(mapResult["a"], 3, "Invalid int result"); +// } + +function multipleReceiveWithNonConditionalSend() { + boolean foo = true; + worker w3 { + int x = <- w1; + int|error y = trap <- w1; + int z = <- w1; + test:assertEquals(x, 2, "Invalid int result"); + test:assertTrue(y is error, "Invalid error result"); + error e = y; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w3'\"}", "Invalid error detail"); + test:assertEquals(z, 4, "Invalid int result"); + } + + worker w1 { + if foo { + 2 -> w3; + } else { + 3 -> w3; + } + 4 -> w3; + } + wait w3; +} From ab50a0d4f7f725fce090233cbc8302aa4dc9cd9d Mon Sep 17 00:00:00 2001 From: Nipuna Fernando Date: Sat, 9 Dec 2023 20:44:30 +0530 Subject: [PATCH 28/97] Update LS tests for display annotation --- .../annotation_ctx/config/startActionAnnotation1.json | 9 +++++++++ .../annotation_ctx/config/startActionAnnotation2.json | 9 +++++++++ .../annotation_ctx/config/workerDeclAnnotation1.json | 9 +++++++++ .../annotation_ctx/config/workerDeclAnnotation2.json | 9 +++++++++ 4 files changed, 36 insertions(+) diff --git a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation1.json b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation1.json index eaf621f46a1f..5e1daca3dc0e 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation1.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation1.json @@ -401,6 +401,15 @@ "sortText": "P", "insertText": "typedesc", "insertTextFormat": "Snippet" + }, + { + "label": "display", + "kind": "Property", + "detail": "Annotation", + "sortText": "B", + "insertText": "display {\n\tlabel: ${1:\"\"}\n}", + "insertTextFormat": "Snippet", + "additionalTextEdits": [] } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation2.json b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation2.json index b71fc0874085..4fd4102cc768 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation2.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/startActionAnnotation2.json @@ -401,6 +401,15 @@ "sortText": "P", "insertText": "typedesc", "insertTextFormat": "Snippet" + }, + { + "label": "display", + "kind": "Property", + "detail": "Annotation", + "sortText": "B", + "insertText": "display {\n\tlabel: ${1:\"\"}\n}", + "insertTextFormat": "Snippet", + "additionalTextEdits": [] } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation1.json b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation1.json index ed4c5d941759..220c7227eda9 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation1.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation1.json @@ -401,6 +401,15 @@ "sortText": "P", "insertText": "typedesc", "insertTextFormat": "Snippet" + }, + { + "label": "display", + "kind": "Property", + "detail": "Annotation", + "sortText": "B", + "insertText": "display {\n\tlabel: ${1:\"\"}\n}", + "insertTextFormat": "Snippet", + "additionalTextEdits": [] } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation2.json b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation2.json index bac02a34004a..71bc7bc43d63 100644 --- a/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation2.json +++ b/language-server/modules/langserver-core/src/test/resources/completion/annotation_ctx/config/workerDeclAnnotation2.json @@ -401,6 +401,15 @@ "sortText": "P", "insertText": "typedesc", "insertTextFormat": "Snippet" + }, + { + "label": "display", + "kind": "Property", + "detail": "Annotation", + "sortText": "B", + "insertText": "display {\n\tlabel: ${1:\"\"}\n}", + "insertTextFormat": "Snippet", + "additionalTextEdits": [] } ] } From 57760c029b4f94d79eee69882e4719b30c306eef Mon Sep 17 00:00:00 2001 From: hindujaB Date: Sat, 9 Dec 2023 22:56:19 +0530 Subject: [PATCH 29/97] Fix checkStyle error --- .../java/io/ballerina/runtime/internal/errors/ErrorCodes.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java index f5e14c224077..574b79c7c680 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorCodes.java @@ -150,7 +150,7 @@ public enum ErrorCodes implements DiagnosticCode { CONFIG_TOML_INVALID_MODULE_STRUCTURE_WITH_VARIABLE("config.toml.invalid.module.structure.with.variable", "RUNTIME_0121"), EMPTY_XML_SEQUENCE_HAS_NO_ATTRIBUTES("empty.xml.sequence.no.attributes", "RUNTIME_0122"), - NO_MESSAGE_ERROR("no.worker.message.received", "RUNTIME_0123" ); + NO_MESSAGE_ERROR("no.worker.message.received", "RUNTIME_0123"); private final String errorMsgKey; private final String errorCode; From 7510300cb3b6d8540b75d9f056844d650cdefb82 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:16:03 +0530 Subject: [PATCH 30/97] Fix syntax tree for receive-field --- .../internal/parser/BallerinaParser.java | 10 +++-- .../receive_action_assert_01.json | 16 ++------ .../receive_action_assert_02.json | 39 +++++-------------- .../receive_action_assert_03.json | 9 +---- .../misc/completion/completion_assert_08.json | 14 ++----- 5 files changed, 25 insertions(+), 63 deletions(-) diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index b61086dcc011..7ac9c3fdf8eb 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13038,14 +13038,18 @@ private STNode parseSyncSendAction(STNode expression) { * @return peer worker name node */ private STNode parsePeerWorkerName() { + return STNodeFactory.createSimpleNameReferenceNode(parsePeerWorkerIdentifier()); + } + + private STNode parsePeerWorkerIdentifier() { STToken token = peek(); switch (token.kind) { case IDENTIFIER_TOKEN: case FUNCTION_KEYWORD: - return STNodeFactory.createSimpleNameReferenceNode(consume()); + return consume(); default: recover(token, ParserRuleContext.PEER_WORKER_NAME); - return parsePeerWorkerName(); + return parsePeerWorkerIdentifier(); } } @@ -13224,7 +13228,7 @@ private STNode createQualifiedReceiveField(STNode identifier) { } STNode colon = parseColon(); - STNode peerWorker = parsePeerWorkerName(); + STNode peerWorker = parsePeerWorkerIdentifier(); return createQualifiedNameReferenceNode(identifier, colon, peerWorker); } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index 3c10de8636e7..f25a4c73b4a4 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -376,13 +376,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "c" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "c" } ] }, @@ -482,12 +477,7 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD" - } - ] + "kind": "FUNCTION_KEYWORD" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index 69578d6cb6f2..42212b374e9d 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -345,13 +345,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "c" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "c" } ] }, @@ -485,13 +480,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "c" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "c" } ] }, @@ -516,17 +506,11 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - } + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" ] } ] @@ -612,12 +596,7 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD" - } - ] + "kind": "FUNCTION_KEYWORD" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json index 22dce87315d4..a83f0ce9abbe 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json @@ -173,13 +173,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "c" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "c" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json index c9b798d8f24e..09604f36a7fb 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json @@ -1200,17 +1200,11 @@ "kind": "COLON_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - } + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" ] } ] From cc7e577660c80c61138a09eafb8560bd98eedd57 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:21:47 +0530 Subject: [PATCH 31/97] Temporary comment-out worker send/receive related error --- .../compiler/semantics/analyzer/CodeAnalyzer.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 91f71ac16ae4..cbb1e55e7164 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -1966,7 +1966,8 @@ private boolean isReceiveAllowedLocation(SymbolEnv env) { } private boolean isSendAllowedLocation(SymbolEnv env) { - return isTopLevel(env) || env.node.parent.getKind() == NodeKind.IF; // TODO: fix properly + return true; +// return isTopLevel(env) || env.node.parent.getKind() == NodeKind.IF; // TODO: fix properly } private boolean isDefaultWorkerCommunication(String workerIdentifier) { @@ -2040,7 +2041,7 @@ private BType createAccumulatedErrorTypeForMatchingReceive(Location pos, BType e if (onlyContainErrors(returnType)) { returnTypeAndSendType.add(returnType); } else { - this.dlog.error(pos, DiagnosticErrorCode.WORKER_SEND_AFTER_RETURN); +// this.dlog.error(pos, DiagnosticErrorCode.WORKER_SEND_AFTER_RETURN); TODO: fix } } returnTypeAndSendType.add(exprType); @@ -2178,7 +2179,7 @@ public BType createAccumulatedErrorTypeForMatchingSyncSend(BLangWorkerReceive wo if (onlyContainErrors(returnType)) { returnTypeAndSendType.add(returnType); } else { - this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.WORKER_RECEIVE_AFTER_RETURN); +// this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.WORKER_RECEIVE_AFTER_RETURN); TODO: fix } } returnTypeAndSendType.add(symTable.nilType); From 2983755e5542e46443869f2400a8bbb8bdd9b8d8 Mon Sep 17 00:00:00 2001 From: Hinduja Balasubramaniyam <28644893+HindujaB@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:32:32 +0530 Subject: [PATCH 32/97] Update bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java Co-authored-by: Nadeeshan Dissanayake <33286289+Nadeeshan96@users.noreply.github.com> --- .../scheduling/WorkerDataChannel.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index f125f771f096..e009b26542c9 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -1,19 +1,20 @@ /* - * Copyright (c) 2019, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +/* + * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). * - * 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 + * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. + * 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 io.ballerina.runtime.internal.scheduling; From d3c6c8f5e72037b4bf2b93f6798bd94c7654fd63 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 11 Dec 2023 11:40:23 +0530 Subject: [PATCH 33/97] Fix failing tests --- .../worker/WorkerConditionalSendTest.java | 10 +- .../workers/workers_conditional_send.bal | 211 ++++++++++++------ 2 files changed, 143 insertions(+), 78 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 3de594598054..7eb765c4af46 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -58,10 +58,12 @@ public static String[] functionProvider() { "sameWorkerSendReceiverPanic", "sameWorkerSendMultiplePath1", "sameWorkerSendMultiplePath2", - // TODO: Enable these tests when it is compiling -// "sameWorkerSendMultiplePathError1", -// "sameWorkerSendMultiplePathError2", -// "multipleReceiveConditional" +// TODO: Enable these tests when it is compiling + "sameWorkerSendMultiplePathError1", + "sameWorkerSendMultiplePathError2", + "sameWorkerSendMultiplePathError3", + "sameWorkerSendMultiplePathError4", + "multipleReceiveConditional", "multipleReceiveWithNonConditionalSend" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index 34bd5cb336ff..5bebe54fe546 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -272,81 +272,144 @@ function sameWorkerSendMultiplePath2() { } // TODO: Enable these tests when it is compiling -// function sameWorkerSendMultiplePathError1() { -// boolean foo = false; - -// worker w1 returns error? { -// int value = 10; -// if foo { -// if value == 10 { -// return error("Error in worker 1"); -// } -// 1 -> w2; -// } -// 2 -> w2; -// } - -// worker w2 returns int|error { -// int|error a = <- w1 | w1; -// return a; -// } - -// map mapResult = wait { a : w1, b: w2}; -// test:assertTrue(mapResult["a"] is error, "Invalid error result"); -// test:assertEquals(mapResult["b"], 2, "Invalid int result"); -// } - -// function sameWorkerSendMultiplePathError2() { -// boolean foo = false; - -// worker w1 returns error? { -// int value = 10; -// if foo { -// 1 -> w2; -// } -// if value == 10 { -// return error("Error in worker 1"); -// } -// 2 -> w2; -// } - -// worker w2 returns int|error { -// int|error a = <- w1 | w1; -// return a; -// } - -// map mapResult = wait { a : w1, b: w2}; -// test:assertTrue(mapResult["a"] is error, "Invalid error result"); -// test:assertEquals(mapResult["b"], 1, "Invalid int result"); -// } - -// function multipleReceiveConditional() { -// boolean foo = true; -// worker w1 returns int { -// if (foo) { -// 2 -> w2; -// int y = <- w3; -// return y; -// } else { -// 2-> w3; -// } -// return 0; -// } +function sameWorkerSendMultiplePathError1() { + boolean foo = false; + + worker w1 returns error? { + int value = 10; + if foo { + if value == 10 { + return error("Error in worker 1"); + } + 1 -> w2; + } + 2 -> w2; + } + + worker w2 returns int|error? { + int|error a = <- w1 | w1; + return a; + } + + map mapResult = wait { a : w1, b: w2}; + test:assertTrue(mapResult["a"] is (), "Invalid nil result"); + test:assertEquals(mapResult["b"], 2, "Invalid int result"); +} + +function sameWorkerSendMultiplePathError2() { + boolean foo = false; + + worker w1 returns error? { + int value = 10; + if foo { + 1 -> w2; + } + if value == 10 { + return error("Error in worker 1"); + } + 2 -> w2; + } + + worker w2 returns int|error { + int|error a = <- w1 | w1; + return a; + } + + map mapResult = wait { a : w1, b: w2}; + test:assertTrue(mapResult["a"] is error, "Invalid error result"); + test:assertTrue(mapResult["b"] is error, "Invalid error result"); + error e = mapResult["a"]; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); + e = mapResult["b"]; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} + +function sameWorkerSendMultiplePathError3() { + boolean foo = true; + + worker w1 returns error? { + int value = 10; + if foo { + if value == 10 { + return error("Error in worker 1"); + } + 1 -> w2; + } + 2 -> w2; + } + + worker w2 returns int|error? { + int|error a = <- w1 | w1; + return a; + } -// worker w2 returns int { -// int y = <- w1; -// return y; -// } - -// worker w3 returns int { -// int y = <- w1; -// 3 -> w1; -// return y; -// } - -// map mapResult = wait {a: w1, b: w2, c: w3}; -// test:assertEquals(mapResult["a"], 3, "Invalid int result"); -// } + map mapResult = wait { a : w1, b: w2}; + test:assertTrue(mapResult["a"] is error, "Invalid error result"); + test:assertTrue(mapResult["b"] is error, "Invalid error result"); + error e = mapResult["a"]; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); + e = mapResult["b"]; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); +} + +function sameWorkerSendMultiplePathError4() { + boolean foo = true; + + worker w1 returns error? { + int value = 10; + if foo { + 1 -> w2; + } + if value == 10 { + return error("Error in worker 1"); + } + 2 -> w2; + } + + worker w2 returns int|error { + int|error a = <- w1 | w1; + return a; + } + + map mapResult = wait { a : w1, b: w2}; + error e = mapResult["a"]; + test:assertEquals(e.message(), "Error in worker 1", "Invalid error message"); + test:assertEquals(mapResult["b"], 1, "Invalid int result"); +} + +function multipleReceiveConditional() { + boolean foo = true; + worker w1 returns int { + if (foo) { + int x = 2; + x -> w2; + return x; + } else { + 2-> w3; + } + int y = <- w3; + return y; + } + + worker w2 returns int { + int y = <- w1; + return y; + } + + worker w3 returns int|error { + int|error y = trap <- w1; + 3 -> w1; + return y; + } + + map mapResult = wait {a: w1, b: w2, c: w3}; + test:assertEquals(mapResult["a"], 2, "Invalid int result"); + test:assertEquals(mapResult["b"], 2, "Invalid int result"); + test:assertTrue(mapResult["c"] is error, "Expected error result"); + error e = mapResult["c"]; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w3'\"}", "Invalid error detail"); +} function multipleReceiveWithNonConditionalSend() { boolean foo = true; From 05b32da0ca8cd6d1440033188344389fc2f85a5f Mon Sep 17 00:00:00 2001 From: Anjana S Porawagama Date: Tue, 28 Nov 2023 17:25:38 +0530 Subject: [PATCH 34/97] Update component fetch logic --- .../ballerina/packages/BallerinaPackageService.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java index 3a00f737896a..7d87fa691e1d 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java @@ -98,15 +98,21 @@ public CompletableFuture components(PackageComponents try { Arrays.stream(documentIdentifiers).iterator().forEachRemaining(documentIdentifier -> { PathUtil.getPathFromURI(documentIdentifier.getUri()).ifPresent(path -> { - Optional project = this.workspaceManager.project(path); - project.ifPresent(value -> jsonPackages.add(getPackageComponents(value))); + Project project = null; + try { + project = this.workspaceManager.loadProject(path); + jsonPackages.add(getPackageComponents(project)); + } catch (Throwable e) { + String msg = "Operation 'ballerinaPackage/components' load project failed!"; + this.clientLogger.logError(PackageContext.PACKAGE_COMPONENTS, msg, e, null, (Position) null); + } }); }); - response.setProjectPackages(jsonPackages); } catch (Throwable e) { String msg = "Operation 'ballerinaPackage/components' failed!"; this.clientLogger.logError(PackageContext.PACKAGE_COMPONENTS, msg, e, null, (Position) null); } + response.setProjectPackages(jsonPackages); return response; }); } From 2922bd6feebadbe3927970ce6cbcf5032edd0615 Mon Sep 17 00:00:00 2001 From: Anjana S Porawagama Date: Wed, 29 Nov 2023 11:00:42 +0530 Subject: [PATCH 35/97] Update checkstyle --- .../extensions/ballerina/packages/BallerinaPackageService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java index 7d87fa691e1d..aaa2a4211f50 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/extensions/ballerina/packages/BallerinaPackageService.java @@ -104,7 +104,7 @@ public CompletableFuture components(PackageComponents jsonPackages.add(getPackageComponents(project)); } catch (Throwable e) { String msg = "Operation 'ballerinaPackage/components' load project failed!"; - this.clientLogger.logError(PackageContext.PACKAGE_COMPONENTS, msg, e, null, (Position) null); + this.clientLogger.logError(PackageContext.PACKAGE_COMPONENTS, msg, e, null); } }); }); From 0a897c9234bd52520d8a5261818fdb2022447f03 Mon Sep 17 00:00:00 2001 From: Anjana S Porawagama Date: Wed, 29 Nov 2023 13:24:19 +0530 Subject: [PATCH 36/97] Update tests --- .../org/ballerinalang/langserver/packages/ComponentsTest.java | 4 ++-- .../packages/components/project-exception_expected.json | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 language-server/modules/langserver-core/src/test/resources/packages/components/project-exception_expected.json diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/packages/ComponentsTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/packages/ComponentsTest.java index bde559486cd7..eeaf2c24a8f8 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/packages/ComponentsTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/packages/ComponentsTest.java @@ -61,7 +61,6 @@ public void packageComponentsTestCase(String[] projects, String expected) throws List filePaths = new ArrayList<>(); for (String project : projects) { Path path = configsPath.resolve(project).resolve("main.bal").toAbsolutePath(); - TestUtil.openDocument(serviceEndpoint, path); filePaths.add(path.toString()); } @@ -133,7 +132,8 @@ public Object[][] getDataProvider() { {new String[]{"project", "project-functions", "project-services", "single-file"}, "multiple-packages_expected.json"}, {new String[]{"single-file"}, "single-file-package_expected.json"}, - {new String[]{"project-other"}, "project-other_expected.json"} + {new String[]{"project-other"}, "project-other_expected.json"}, + {new String[]{"non-exist"}, "project-exception_expected.json"} }; } } diff --git a/language-server/modules/langserver-core/src/test/resources/packages/components/project-exception_expected.json b/language-server/modules/langserver-core/src/test/resources/packages/components/project-exception_expected.json new file mode 100644 index 000000000000..4677642a3ac7 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/packages/components/project-exception_expected.json @@ -0,0 +1,3 @@ +{ + "result": [] +} From f21b33eec41f79fb7e6f7ef31bad5316350ac18c Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 11 Dec 2023 11:47:55 +0530 Subject: [PATCH 37/97] Address suggestions --- .../main/java/io/ballerina/runtime/api/utils/JsonUtils.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/JsonUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/JsonUtils.java index c695db982e6b..7b6b7023cfcc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/JsonUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/utils/JsonUtils.java @@ -34,7 +34,6 @@ import io.ballerina.runtime.api.values.BRefValue; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.api.values.BTable; -import io.ballerina.runtime.api.values.BTypedesc; import io.ballerina.runtime.internal.JsonGenerator; import io.ballerina.runtime.internal.JsonInternalUtils; import io.ballerina.runtime.internal.JsonParser; @@ -77,10 +76,6 @@ public static Object parse(InputStream in) throws BError { return JsonParser.parse(in); } - public static Object parse(InputStream in, BTypedesc td) throws BError { - return JsonParser.parse(in); - } - /** * Parses the contents in the given {@link InputStream} and returns a json. * From e78d90e75333bb158a7c2a6a4985c029586fdf83 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:08:20 +0530 Subject: [PATCH 38/97] Fix peer-worker parsing --- .../compiler/internal/parser/BallerinaParser.java | 5 ++++- .../receive-action/receive_action_assert_01.json | 6 ++++-- .../receive-action/receive_action_assert_02.json | 3 ++- .../receive-action/receive_action_assert_04.json | 15 ++++++++++----- .../send-action/send_action_assert_02.json | 6 ++++-- .../send-action/send_action_assert_04.json | 6 ++++-- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 7ac9c3fdf8eb..252ffbf9ab29 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13045,8 +13045,11 @@ private STNode parsePeerWorkerIdentifier() { STToken token = peek(); switch (token.kind) { case IDENTIFIER_TOKEN: - case FUNCTION_KEYWORD: return consume(); + case FUNCTION_KEYWORD: + STToken functionKeyword = consume(); + return STNodeFactory.createIdentifierToken(functionKeyword.text(), functionKeyword.leadingMinutiae(), + functionKeyword.trailingMinutiae(), functionKeyword.diagnostics()); default: recover(token, ParserRuleContext.PEER_WORKER_NAME); return parsePeerWorkerIdentifier(); diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index f25a4c73b4a4..e67628d782cd 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -83,7 +83,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -477,7 +478,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index 42212b374e9d..edc3ce2d4f64 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -596,7 +596,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 19961f156696..5d1b36d39904 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -334,7 +334,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -357,7 +358,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -558,7 +560,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -581,7 +584,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -681,7 +685,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json index 3bc47de77079..094228f66893 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json @@ -242,7 +242,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -323,7 +324,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json index 8d9b27c8a067..e66253ec076d 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json @@ -310,7 +310,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -406,7 +407,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", From 97562c9f9a0491553869901ec2525f55a4b98a64 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:08:20 +0530 Subject: [PATCH 39/97] Fix peer-worker parsing --- .../compiler/internal/parser/BallerinaParser.java | 5 ++++- .../receive-action/receive_action_assert_01.json | 6 ++++-- .../receive-action/receive_action_assert_02.json | 3 ++- .../receive-action/receive_action_assert_04.json | 15 ++++++++++----- .../send-action/send_action_assert_02.json | 6 ++++-- .../send-action/send_action_assert_04.json | 6 ++++-- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 7ac9c3fdf8eb..252ffbf9ab29 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13045,8 +13045,11 @@ private STNode parsePeerWorkerIdentifier() { STToken token = peek(); switch (token.kind) { case IDENTIFIER_TOKEN: - case FUNCTION_KEYWORD: return consume(); + case FUNCTION_KEYWORD: + STToken functionKeyword = consume(); + return STNodeFactory.createIdentifierToken(functionKeyword.text(), functionKeyword.leadingMinutiae(), + functionKeyword.trailingMinutiae(), functionKeyword.diagnostics()); default: recover(token, ParserRuleContext.PEER_WORKER_NAME); return parsePeerWorkerIdentifier(); diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index f25a4c73b4a4..e67628d782cd 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -83,7 +83,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -477,7 +478,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index 42212b374e9d..edc3ce2d4f64 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -596,7 +596,8 @@ "kind": "COLON_TOKEN" }, { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 19961f156696..5d1b36d39904 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -334,7 +334,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -357,7 +358,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -558,7 +560,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -581,7 +584,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -681,7 +685,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json index 3bc47de77079..094228f66893 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json @@ -242,7 +242,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } @@ -323,7 +324,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "IDENTIFIER_TOKEN", + "value": "function" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json index 8d9b27c8a067..e66253ec076d 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json @@ -310,7 +310,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -406,7 +407,8 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "FUNCTION_KEYWORD", + "kind": "IDENTIFIER_TOKEN", + "value": "function", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", From 27eb93f829e723e08704f1dbf4bf20bd5d7c804c Mon Sep 17 00:00:00 2001 From: poorna2152 Date: Thu, 14 Dec 2023 10:55:10 +0530 Subject: [PATCH 40/97] Fix formatting of multiple receive actions --- .../compiler/parser/BLangNodeBuilder.java | 15 +- .../internal/parser/BallerinaParser.java | 8 +- .../internal/parser/tree/STNodeFactory.java | 11 ++ .../parser/tree/STNodeTransformer.java | 4 + .../internal/parser/tree/STNodeVisitor.java | 4 + .../parser/tree/STReceiveFieldNode.java | 104 ++++++++++++++ .../internal/parser/tree/STTreeModifier.java | 12 ++ .../compiler/syntax/tree/NodeFactory.java | 17 ++- .../compiler/syntax/tree/NodeTransformer.java | 4 + .../compiler/syntax/tree/NodeVisitor.java | 4 + .../syntax/tree/ReceiveFieldNode.java | 132 ++++++++++++++++++ .../syntax/tree/ReceiveFieldsNode.java | 8 +- .../compiler/syntax/tree/SyntaxKind.java | 1 + .../compiler/syntax/tree/TreeModifier.java | 17 ++- .../compiler/parser/test/ParserTestUtils.java | 2 + .../receive_action_assert_01.json | 40 ++++-- .../receive_action_assert_02.json | 90 ++++++++---- .../receive_action_assert_03.json | 20 ++- .../misc/completion/completion_assert_08.json | 45 ++++-- .../misc/completion/completion_source_08.bal | 4 +- .../main/resources/syntax_node_metadata.json | 4 + .../resources/syntax_tree_descriptor.json | 21 ++- .../core/FormattingTreeModifier.java | 27 +++- .../assert/send_receive_action_4.bal | 57 ++++++++ .../source/send_receive_action_4.bal | 46 ++++++ .../api_gen_syntax_tree_descriptor.json | 21 ++- 26 files changed, 641 insertions(+), 77 deletions(-) create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java create mode 100644 misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal create mode 100644 misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 5b92adf5b153..3eacef322e81 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -180,6 +180,7 @@ import io.ballerina.compiler.syntax.tree.ReUnicodePropertyEscapeNode; import io.ballerina.compiler.syntax.tree.ReUnicodeScriptNode; import io.ballerina.compiler.syntax.tree.ReceiveActionNode; +import io.ballerina.compiler.syntax.tree.ReceiveFieldNode; import io.ballerina.compiler.syntax.tree.ReceiveFieldsNode; import io.ballerina.compiler.syntax.tree.RecordFieldNode; import io.ballerina.compiler.syntax.tree.RecordFieldWithDefaultValueNode; @@ -2548,18 +2549,18 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { } ReceiveFieldsNode receiveFieldsNode = (ReceiveFieldsNode) receiveWorkers; - SeparatedNodeList receiveFields = receiveFieldsNode.receiveFields(); + SeparatedNodeList receiveFields = receiveFieldsNode.receiveFields(); List fields = new ArrayList<>(receiveFields.size()); - for (NameReferenceNode nameRef : receiveFields) { + for (Node receiveField : receiveFields) { BLangMultipleWorkerReceive.BLangReceiveField rvField = new BLangMultipleWorkerReceive.BLangReceiveField(); - if (nameRef.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { - Token name = ((SimpleNameReferenceNode) nameRef).name(); + if (receiveField.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { + Token name = ((SimpleNameReferenceNode) receiveField).name(); rvField.setKey(createIdentifier(name)); rvField.setWorkerReceive(createSimpleWorkerReceive(name)); } else { - QualifiedNameReferenceNode qualifiedNameRef = (QualifiedNameReferenceNode) nameRef; - rvField.setKey(createIdentifier(qualifiedNameRef.modulePrefix())); - rvField.setWorkerReceive(createSimpleWorkerReceive(qualifiedNameRef.identifier())); + ReceiveFieldNode receiveFieldNode = (ReceiveFieldNode) receiveField; + rvField.setKey(createIdentifier(receiveFieldNode.fieldName().name())); + rvField.setWorkerReceive(createSimpleWorkerReceive(receiveFieldNode.peerWorker().name())); } fields.add(rvField); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 252ffbf9ab29..d17a061f9a86 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13218,21 +13218,23 @@ private STNode parseReceiveField() { return STNodeFactory.createSimpleNameReferenceNode(functionKeyword); case IDENTIFIER_TOKEN: STNode identifier = parseIdentifier(ParserRuleContext.RECEIVE_FIELD_NAME); - return createQualifiedReceiveField(identifier); + return createReceiveField(identifier); default: recover(peek(), ParserRuleContext.RECEIVE_FIELD); return parseReceiveField(); } } - private STNode createQualifiedReceiveField(STNode identifier) { + private STNode createReceiveField(STNode identifier) { if (peek().kind != SyntaxKind.COLON_TOKEN) { return STNodeFactory.createSimpleNameReferenceNode(identifier); } + identifier = STNodeFactory.createSimpleNameReferenceNode(identifier); STNode colon = parseColon(); STNode peerWorker = parsePeerWorkerIdentifier(); - return createQualifiedNameReferenceNode(identifier, colon, peerWorker); + peerWorker = STNodeFactory.createSimpleNameReferenceNode(peerWorker); + return STNodeFactory.createReceiveFieldNode(identifier, colon, peerWorker); } /** diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index c03a8d0db666..9dd731622273 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -2719,5 +2719,16 @@ public static STNode createMemberTypeDescriptorNode( annotations, typeDescriptor); } + + public static STNode createReceiveFieldNode( + STNode fieldName, + STNode colon, + STNode peerWorker) { + + return new STReceiveFieldNode( + fieldName, + colon, + peerWorker); + } } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java index 8fffa392f44a..295e3c84c5c2 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java @@ -941,6 +941,10 @@ public T transform(STMemberTypeDescriptorNode memberTypeDescriptorNode) { return transformSyntaxNode(memberTypeDescriptorNode); } + public T transform(STReceiveFieldNode receiveFieldNode) { + return transformSyntaxNode(receiveFieldNode); + } + // Tokens public T transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java index 8e20dc2e4cec..1fd5c558a1f7 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java @@ -941,6 +941,10 @@ public void visit(STMemberTypeDescriptorNode memberTypeDescriptorNode) { visitSyntaxNode(memberTypeDescriptorNode); } + public void visit(STReceiveFieldNode receiveFieldNode) { + visitSyntaxNode(receiveFieldNode); + } + // STNodeList public void visit(STNodeList nodeList) { visitChildren(nodeList); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java new file mode 100644 index 000000000000..48312813338d --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.internal.parser.tree; + +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NonTerminalNode; +import io.ballerina.compiler.syntax.tree.ReceiveFieldNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; + +import java.util.Collection; +import java.util.Collections; + +/** + * This is a generated internal syntax tree node. + * + * @since 2201.9.0 + */ +public class STReceiveFieldNode extends STNode { + public final STNode fieldName; + public final STNode colon; + public final STNode peerWorker; + + STReceiveFieldNode( + STNode fieldName, + STNode colon, + STNode peerWorker) { + this( + fieldName, + colon, + peerWorker, + Collections.emptyList()); + } + + STReceiveFieldNode( + STNode fieldName, + STNode colon, + STNode peerWorker, + Collection diagnostics) { + super(SyntaxKind.RECEIVE_FIELD, diagnostics); + this.fieldName = fieldName; + this.colon = colon; + this.peerWorker = peerWorker; + + addChildren( + fieldName, + colon, + peerWorker); + } + + public STNode modifyWith(Collection diagnostics) { + return new STReceiveFieldNode( + this.fieldName, + this.colon, + this.peerWorker, + diagnostics); + } + + public STReceiveFieldNode modify( + STNode fieldName, + STNode colon, + STNode peerWorker) { + if (checkForReferenceEquality( + fieldName, + colon, + peerWorker)) { + return this; + } + + return new STReceiveFieldNode( + fieldName, + colon, + peerWorker, + diagnostics); + } + + public Node createFacade(int position, NonTerminalNode parent) { + return new ReceiveFieldNode(this, position, parent); + } + + @Override + public void accept(STNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(STNodeTransformer transformer) { + return transformer.transform(this); + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index b53a6812ffda..be89fe8f2121 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -2925,6 +2925,18 @@ public STMemberTypeDescriptorNode transform( typeDescriptor); } + @Override + public STReceiveFieldNode transform( + STReceiveFieldNode receiveFieldNode) { + STNode fieldName = modifyNode(receiveFieldNode.fieldName); + STNode colon = modifyNode(receiveFieldNode.colon); + STNode peerWorker = modifyNode(receiveFieldNode.peerWorker); + return receiveFieldNode.modify( + fieldName, + colon, + peerWorker); + } + // Tokens public STToken transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index 947feb04e7c2..b11a56354eaf 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -2417,7 +2417,7 @@ public static ReceiveActionNode createReceiveActionNode( public static ReceiveFieldsNode createReceiveFieldsNode( Token openBrace, - SeparatedNodeList receiveFields, + SeparatedNodeList receiveFields, Token closeBrace) { Objects.requireNonNull(openBrace, "openBrace must not be null"); Objects.requireNonNull(receiveFields, "receiveFields must not be null"); @@ -3622,5 +3622,20 @@ public static MemberTypeDescriptorNode createMemberTypeDescriptorNode( typeDescriptor.internalNode()); return stMemberTypeDescriptorNode.createUnlinkedFacade(); } + + public static ReceiveFieldNode createReceiveFieldNode( + SimpleNameReferenceNode fieldName, + Token colon, + SimpleNameReferenceNode peerWorker) { + Objects.requireNonNull(fieldName, "fieldName must not be null"); + Objects.requireNonNull(colon, "colon must not be null"); + Objects.requireNonNull(peerWorker, "peerWorker must not be null"); + + STNode stReceiveFieldNode = STNodeFactory.createReceiveFieldNode( + fieldName.internalNode(), + colon.internalNode(), + peerWorker.internalNode()); + return stReceiveFieldNode.createUnlinkedFacade(); + } } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java index 856f0a16e8c3..d0557866aaf9 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java @@ -952,6 +952,10 @@ public T transform(MemberTypeDescriptorNode memberTypeDescriptorNode) { return transformSyntaxNode(memberTypeDescriptorNode); } + public T transform(ReceiveFieldNode receiveFieldNode) { + return transformSyntaxNode(receiveFieldNode); + } + // Tokens public T transform(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java index 6ec321663c9b..7b41a3d8d075 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java @@ -951,6 +951,10 @@ public void visit(MemberTypeDescriptorNode memberTypeDescriptorNode) { visitSyntaxNode(memberTypeDescriptorNode); } + public void visit(ReceiveFieldNode receiveFieldNode) { + visitSyntaxNode(receiveFieldNode); + } + // Tokens public void visit(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java new file mode 100644 index 000000000000..068285da324b --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.syntax.tree; + +import io.ballerina.compiler.internal.parser.tree.STNode; + +import java.util.Objects; + +/** + * This is a generated syntax tree node. + * + * @since 2201.9.0 + */ +public class ReceiveFieldNode extends NonTerminalNode { + + public ReceiveFieldNode(STNode internalNode, int position, NonTerminalNode parent) { + super(internalNode, position, parent); + } + + public SimpleNameReferenceNode fieldName() { + return childInBucket(0); + } + + public Token colon() { + return childInBucket(1); + } + + public SimpleNameReferenceNode peerWorker() { + return childInBucket(2); + } + + @Override + public void accept(NodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(NodeTransformer visitor) { + return visitor.transform(this); + } + + @Override + protected String[] childNames() { + return new String[]{ + "fieldName", + "colon", + "peerWorker"}; + } + + public ReceiveFieldNode modify( + SimpleNameReferenceNode fieldName, + Token colon, + SimpleNameReferenceNode peerWorker) { + if (checkForReferenceEquality( + fieldName, + colon, + peerWorker)) { + return this; + } + + return NodeFactory.createReceiveFieldNode( + fieldName, + colon, + peerWorker); + } + + public ReceiveFieldNodeModifier modify() { + return new ReceiveFieldNodeModifier(this); + } + + /** + * This is a generated tree node modifier utility. + * + * @since 2201.9.0 + */ + public static class ReceiveFieldNodeModifier { + private final ReceiveFieldNode oldNode; + private SimpleNameReferenceNode fieldName; + private Token colon; + private SimpleNameReferenceNode peerWorker; + + public ReceiveFieldNodeModifier(ReceiveFieldNode oldNode) { + this.oldNode = oldNode; + this.fieldName = oldNode.fieldName(); + this.colon = oldNode.colon(); + this.peerWorker = oldNode.peerWorker(); + } + + public ReceiveFieldNodeModifier withFieldName( + SimpleNameReferenceNode fieldName) { + Objects.requireNonNull(fieldName, "fieldName must not be null"); + this.fieldName = fieldName; + return this; + } + + public ReceiveFieldNodeModifier withColon( + Token colon) { + Objects.requireNonNull(colon, "colon must not be null"); + this.colon = colon; + return this; + } + + public ReceiveFieldNodeModifier withPeerWorker( + SimpleNameReferenceNode peerWorker) { + Objects.requireNonNull(peerWorker, "peerWorker must not be null"); + this.peerWorker = peerWorker; + return this; + } + + public ReceiveFieldNode apply() { + return oldNode.modify( + fieldName, + colon, + peerWorker); + } + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldsNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldsNode.java index 7e2c646968f9..885d8ecfa569 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldsNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldsNode.java @@ -36,7 +36,7 @@ public Token openBrace() { return childInBucket(0); } - public SeparatedNodeList receiveFields() { + public SeparatedNodeList receiveFields() { return new SeparatedNodeList<>(childInBucket(1)); } @@ -64,7 +64,7 @@ protected String[] childNames() { public ReceiveFieldsNode modify( Token openBrace, - SeparatedNodeList receiveFields, + SeparatedNodeList receiveFields, Token closeBrace) { if (checkForReferenceEquality( openBrace, @@ -91,7 +91,7 @@ public ReceiveFieldsNodeModifier modify() { public static class ReceiveFieldsNodeModifier { private final ReceiveFieldsNode oldNode; private Token openBrace; - private SeparatedNodeList receiveFields; + private SeparatedNodeList receiveFields; private Token closeBrace; public ReceiveFieldsNodeModifier(ReceiveFieldsNode oldNode) { @@ -109,7 +109,7 @@ public ReceiveFieldsNodeModifier withOpenBrace( } public ReceiveFieldsNodeModifier withReceiveFields( - SeparatedNodeList receiveFields) { + SeparatedNodeList receiveFields) { Objects.requireNonNull(receiveFields, "receiveFields must not be null"); this.receiveFields = receiveFields; return this; diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java index 7022853b81b2..84edbf974023 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java @@ -485,6 +485,7 @@ public enum SyntaxKind { GROUP_BY_CLAUSE(3093), COLLECT_CLAUSE(3094), ALTERNATE_RECEIVE_WORKER(3095), + RECEIVE_FIELD(3096), // XML XML_ELEMENT(4000), diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index bd73c125f3c1..ad1fab524d3d 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -2464,7 +2464,7 @@ public ReceiveFieldsNode transform( ReceiveFieldsNode receiveFieldsNode) { Token openBrace = modifyToken(receiveFieldsNode.openBrace()); - SeparatedNodeList receiveFields = + SeparatedNodeList receiveFields = modifySeparatedNodeList(receiveFieldsNode.receiveFields()); Token closeBrace = modifyToken(receiveFieldsNode.closeBrace()); @@ -3687,6 +3687,21 @@ public MemberTypeDescriptorNode transform( typeDescriptor); } + @Override + public ReceiveFieldNode transform( + ReceiveFieldNode receiveFieldNode) { + SimpleNameReferenceNode fieldName = + modifyNode(receiveFieldNode.fieldName()); + Token colon = + modifyToken(receiveFieldNode.colon()); + SimpleNameReferenceNode peerWorker = + modifyNode(receiveFieldNode.peerWorker()); + return receiveFieldNode.modify( + fieldName, + colon, + peerWorker); + } + // Tokens @Override diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java index 7ced96123ba9..e318d246cda2 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java @@ -635,6 +635,8 @@ private static SyntaxKind getNodeKind(String kind) { return SyntaxKind.RESOURCE_ACCESS_REST_SEGMENT; case "ALTERNATE_RECEIVE_WORKER": return SyntaxKind.ALTERNATE_RECEIVE_WORKER; + case "RECEIVE_FIELD": + return SyntaxKind.RECEIVE_FIELD; // Trivia case "EOF_TOKEN": diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index e67628d782cd..1a683f8dd921 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -367,18 +367,28 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "c" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c" + } + ] } ] }, @@ -468,18 +478,28 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "function" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index edc3ce2d4f64..041430fe3cd1 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -335,18 +335,28 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "c" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c" + } + ] } ] }, @@ -465,23 +475,34 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "c" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c" + } + ] } ] }, @@ -495,22 +516,33 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "d" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "d" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] } ] @@ -586,18 +618,28 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "function" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json index a83f0ce9abbe..9c8c50d7b9a7 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_03.json @@ -163,18 +163,28 @@ ] }, { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] }, { "kind": "COLON_TOKEN" }, { - "kind": "IDENTIFIER_TOKEN", - "value": "c" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "c" + } + ] } ] }, diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json index 09604f36a7fb..a8cbb7f6af1b 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json @@ -1189,22 +1189,45 @@ "hasDiagnostics": true, "children": [ { - "kind": "QUALIFIED_NAME_REFERENCE", + "kind": "RECEIVE_FIELD", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "a" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] }, { - "kind": "COLON_TOKEN" + "kind": "COLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] }, { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] } ] @@ -1238,12 +1261,6 @@ }, { "kind": "CLOSE_BRACE_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], "trailingMinutiae": [ { "kind": "END_OF_LINE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal index acf6362f3bd0..b2af46caabd3 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal @@ -26,8 +26,8 @@ function foo6() { function foo7() { <- { -a:} - } + a: } +} function foo8() { flush diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index d4d9de78f262..ea69efacd564 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -138,5 +138,9 @@ "SpreadMemberNode": { "createdYear": "2022", "since": "2201.1.0" + }, + "ReceiveFieldNode": { + "createdYear": "2023", + "since": "2201.9.0" } } diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 2423157312b9..97d843298269 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -3332,7 +3332,7 @@ }, { "name": "receiveFields", - "type": "NameReferenceNode", + "type": "Node", "occurrences": "MULTIPLE_SEPARATED" }, { @@ -4957,6 +4957,25 @@ "type": "TypeDescriptorNode" } ] + }, + { + "name": "ReceiveFieldNode", + "base": "Node", + "kind": "RECEIVE_FIELD", + "attributes": [ + { + "name": "fieldName", + "type": "SimpleNameReferenceNode" + }, + { + "name": "colon", + "type": "Token" + }, + { + "name": "peerWorker", + "type": "SimpleNameReferenceNode" + } + ] } ] } diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 727b7e98f6bd..2ee8a1cb59c1 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -165,6 +165,7 @@ import io.ballerina.compiler.syntax.tree.QueryExpressionNode; import io.ballerina.compiler.syntax.tree.QueryPipelineNode; import io.ballerina.compiler.syntax.tree.ReceiveActionNode; +import io.ballerina.compiler.syntax.tree.ReceiveFieldNode; import io.ballerina.compiler.syntax.tree.ReceiveFieldsNode; import io.ballerina.compiler.syntax.tree.RecordFieldNode; import io.ballerina.compiler.syntax.tree.RecordFieldWithDefaultValueNode; @@ -3007,12 +3008,14 @@ public ReceiveActionNode transform(ReceiveActionNode receiveActionNode) { @Override public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { - Token openBrace = formatToken(receiveFieldsNode.openBrace(), 0, 1); + int trailingNL = shouldExpand(receiveFieldsNode) ? 1 : 0; + Token openBrace = formatToken(receiveFieldsNode.openBrace(), 0, trailingNL); indent(); - SeparatedNodeList receiveFields = formatSeparatedNodeList(receiveFieldsNode.receiveFields(), - 0, 1, 0, 1); - Token closeBrace = formatToken(receiveFieldsNode.closeBrace(), 0, 1); + SeparatedNodeList receiveFields = + formatSeparatedNodeList(receiveFieldsNode.receiveFields(), 0, 0, 1 - trailingNL, trailingNL, 0, + trailingNL); unindent(); + Token closeBrace = formatToken(receiveFieldsNode.closeBrace(), env.trailingWS, env.trailingNL); return receiveFieldsNode.modify() .withOpenBrace(openBrace) .withReceiveFields(receiveFields) @@ -3029,6 +3032,19 @@ public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternate .apply(); } + @Override + public ReceiveFieldNode transform(ReceiveFieldNode receiveFieldNode) { + SimpleNameReferenceNode fieldName = formatNode(receiveFieldNode.fieldName(), 0, 0); + Token colon = formatToken(receiveFieldNode.colon(), 1, 0); + SimpleNameReferenceNode peerWorker = formatNode(receiveFieldNode.peerWorker(), env.trailingWS, env.trailingNL); + + return receiveFieldNode.modify() + .withFieldName(fieldName) + .withColon(colon) + .withPeerWorker(peerWorker) + .apply(); + } + @Override public RestDescriptorNode transform(RestDescriptorNode restDescriptorNode) { TypeDescriptorNode typeDescriptor = formatNode(restDescriptorNode.typeDescriptor(), 0, 0); @@ -4630,6 +4646,9 @@ private boolean shouldExpand(Node node) { case LIST_CONSTRUCTOR: ListConstructorExpressionNode listConstructorExpressionNode = (ListConstructorExpressionNode) node; return listConstructorExpressionNode.toSourceCode().trim().contains(System.lineSeparator()); + case RECEIVE_FIELDS: + ReceiveFieldsNode receiveFieldsNode = (ReceiveFieldsNode) node; + return receiveFieldsNode.toSourceCode().trim().contains(System.lineSeparator()); default: return false; } diff --git a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal new file mode 100644 index 000000000000..8e437cf5bc57 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal @@ -0,0 +1,57 @@ +function foo() { + worker w1 { + 1 -> function; + } + worker w2 { + 2 -> function; + } + map x = <- {a: w1, b: w2}; +} + +function bar() { + worker w1 { + 1 -> function; + } + worker w2 { + 2 -> function; + } + map x = <- {w1, w2}; +} + +function baz() { + worker w1 { + 1 -> function; + } + worker w2 { + 2 -> function; + } + map x = <- { + a: w1, + b: w2 + }; + +} + +function foz() { + worker lengthyWorkerName { + 1 -> resultWorker; + } + worker tooLengthyWorkerName { + 2 -> resultWorker; + } + worker short1 { + true -> resultWorker; + } + worker short2 { + "s" -> resultWorker; + } + + worker resultWorker { + map y = <- { + short1: short1, + short2, + lengthyWorkerName, + tooLengthyWorkerName + }; + } +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal new file mode 100644 index 000000000000..beb15b156a63 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal @@ -0,0 +1,46 @@ +function foo() { + worker w1 { + 1 -> function; + } + worker w2 { + 2 -> function; + } + map x = <- {a:w1,b:w2}; +} + +function bar() { + worker w1 { + 1 -> function; + } + worker w2 { + 2 -> function; + } + map x = <- {w1,w2}; +} + +function baz() { + worker w1 {1->function;} + worker w2 { + 2 -> function;} + map x = <- { + a: w1, + b: w2}; + +} + +function foz() { + worker lengthyWorkerName {1->resultWorker;} + worker tooLengthyWorkerName { + 2 -> resultWorker;} + worker short1 { + true -> resultWorker;} + worker short2 { + "s" -> resultWorker; + } + + worker resultWorker { + map y = <- {short1: short1, short2, + lengthyWorkerName, + tooLengthyWorkerName}; + } +} diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index 686de3e59d76..72f8496140b0 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -3332,7 +3332,7 @@ }, { "name": "receiveFields", - "type": "NameReferenceNode", + "type": "Node", "occurrences": "MULTIPLE_SEPARATED" }, { @@ -4957,6 +4957,25 @@ "type": "TypeDescriptorNode" } ] + }, + { + "name": "ReceiveFieldNode", + "base": "Node", + "kind": "RECEIVE_FIELD", + "attributes": [ + { + "name": "fieldName", + "type": "SimpleNameReferenceNode" + }, + { + "name": "colon", + "type": "Token" + }, + { + "name": "peerWorker", + "type": "SimpleNameReferenceNode" + } + ] } ] } From 15f8195f1a04b293875f9aec277c32080ba53705 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 15 Dec 2023 10:43:15 +0530 Subject: [PATCH 41/97] Improve codegen and alternate receive --- .../runtime/internal/ErrorUtils.java | 5 ++- .../internal/scheduling/WDChannels.java | 42 +++++++++++-------- .../scheduling/WorkerDataChannel.java | 6 +-- .../main/resources/MessagesBundle.properties | 2 +- .../compiler/bir/codegen/JvmSignatures.java | 2 +- .../bir/codegen/JvmTerminatorGen.java | 14 +++---- .../main/ballerina/auto-close-channels.bal | 2 +- ...CloseChannels.java => WorkerChannels.java} | 10 ++--- .../worker/WorkerConditionalSendTest.java | 1 - .../workers/workers_conditional_send.bal | 6 +-- 10 files changed, 47 insertions(+), 43 deletions(-) rename langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/{AutoCloseChannels.java => WorkerChannels.java} (83%) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java index 19b12306d8d7..568bb1177ea6 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java @@ -189,7 +189,10 @@ public static BError createInvalidFractionDigitsError() { } public static BError createNoMessageError(String chnlName) { + String[] splitWorkers = chnlName.split(":")[0].split("->"); + String sender = splitWorkers[0]; + String receiver = splitWorkers[1]; return createError(ErrorReasons.NO_MESSAGE_ERROR, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, - StringUtils.fromString(chnlName.split(":")[0]))); + StringUtils.fromString(sender), StringUtils.fromString(receiver))); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 56e05d3f5cce..ec407de6f8b5 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -51,34 +51,40 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { return channel; } - public Object tryTakeData(Strand strand, List channels) throws Throwable { + public Object tryTakeData(Strand strand, String[] channels) throws Throwable { Object result = null; boolean allChannelsClosed = true; for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); - if (channel.isClosed()) { + if (!channel.isClosed()) { + allChannelsClosed = false; + result = channel.tryTakeData(strand, true); + if (result != null) { + result = handleNonNullResult(channels, result, channel); + } + } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { errors.add((ErrorValue) ErrorUtils.createNoMessageError(channelName)); } - continue; - } - allChannelsClosed = false; - result = channel.tryTakeData(strand, true); - if (result != null) { - if (result instanceof ErrorValue) { - errors.add((ErrorValue) result); - channel.close(); - result = null; - continue; - } else { - closeChannels(channels); - } - break; } + } + return processResulAndError(strand, channels, result, allChannelsClosed); + } + private Object handleNonNullResult(String[] channels, Object result, WorkerDataChannel channel) { + if (result instanceof ErrorValue errorValue) { + errors.add(errorValue); + channel.close(); + result = null; + } else { + closeChannels(channels); } + return result; + } + + private Object processResulAndError(Strand strand, String[] channels, Object result, boolean allChannelsClosed) { if (result == null) { - if (errors.size() == channels.size()) { + if (errors.size() == channels.length) { result = errors.get(errors.size() - 1); } else if (!allChannelsClosed) { strand.setState(BLOCK_AND_YIELD); @@ -87,7 +93,7 @@ public Object tryTakeData(Strand strand, List channels) throws Throwable return result; } - private void closeChannels(List channels) { + private void closeChannels(String[] channels) { for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); channel.close(); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index e009b26542c9..e3437f767f20 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -45,12 +45,12 @@ public class WorkerDataChannel { private int receiverCounter; private boolean reschedule; - private Lock channelLock; + private final Lock channelLock; - public String chnlName; + private String chnlName; @SuppressWarnings("rawtypes") - private Queue channel = new LinkedList<>(); + private final Queue channel = new LinkedList<>(); private State state; public WorkerDataChannel() { diff --git a/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties b/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties index f3727c57521e..f2c2d0cfde50 100644 --- a/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties +++ b/bvm/ballerina-runtime/src/main/resources/MessagesBundle.properties @@ -263,4 +263,4 @@ regexp.invalid.unicode.general.category.value = invalid Unicode general category regexp.invalid.unicode.property.value = invalid Unicode property value ''{0}'' regexp.empty.character.class.disallowed = empty character class disallowed regexp.invalid.hex.digit = invalid hexadecimal digit -no.worker.message.received = no worker message received for channel ''{0}'' +no.worker.message.received = no message received from worker ''{0}'' to worker ''{1}'' 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 a36f35124bf6..206410529067 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 @@ -499,7 +499,7 @@ public class JvmSignatures { public static final String GET_TOML_DETAILS = "()L" + TOML_DETAILS + ";"; public static final String GET_TEST_CONFIG_PATH = "(L" + MODULE + ";L" + STRING_VALUE + ";L" + STRING_VALUE + ";)L" + TOML_DETAILS + ";"; - public static final String ALT_RECEIVE_CALL = "(L" + STRAND_CLASS + ";L" + LIST + ";)L" + OBJECT + ";"; + public static final String ALT_RECEIVE_CALL = "(L" + STRAND_CLASS + ";[L" + STRING_VALUE + ";)L" + OBJECT + ";"; private JvmSignatures() { } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 149d2d2ba0d8..11de7a089a9b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -144,6 +144,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.STRAND_THREAD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.STRAND_VALUE_ANY; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.STRING_CONCAT_FACTORY; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.STRING_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.TYPE_ANYDATA_ARRAY; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.VALUE_OF_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.WD_CHANNELS; @@ -1203,20 +1204,19 @@ private void genWorkerAlternateReceiveIns(BIRTerminator.WorkerAlternateReceive i BIRNode.BIRVariableDcl listVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("channels"), VarScope.FUNCTION, VarKind.LOCAL); int channelIndex = this.getJVMIndexOfVarRef(listVar); - this.mv.visitTypeInsn(NEW, ARRAY_LIST); - this.mv.visitInsn(DUP); - this.mv.visitMethodInsn(INVOKESPECIAL, ARRAY_LIST, JVM_INIT_METHOD, VOID_METHOD_DESC, false); - + int channelSize = ins.channels.size(); + this.mv.visitIntInsn(BIPUSH, channelSize); + this.mv.visitTypeInsn(ANEWARRAY, STRING_VALUE); int i = 0; - while (i < ins.channels.size()) { + while (i < channelSize) { this.mv.visitInsn(DUP); + this.mv.visitIntInsn(BIPUSH, i); this.mv.visitVarInsn(ILOAD, invocationVarIndex); this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), ins.channels.get(i) + START_OF_HEADING_WITH_SEMICOLON); - this.mv.visitMethodInsn(INVOKEINTERFACE, LIST, ADD_METHOD, ANY_TO_JBOOLEAN, true); - this.mv.visitInsn(POP); + this.mv.visitInsn(AASTORE); i += 1; } this.mv.visitVarInsn(ASTORE, channelIndex); diff --git a/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal index 0ffcebca7db8..244e9d722927 100644 --- a/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal +++ b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal @@ -20,6 +20,6 @@ import ballerina/jballerina.java; # # + channelIds - channel IDs of the channels to be closed public function autoClose(string ... channelIds) = @java:Method { - 'class: "org.ballerinalang.langlib.internal.AutoCloseChannels", + 'class: "org.ballerinalang.langlib.internal.WorkerChannels", name: "autoClose" } external; diff --git a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java similarity index 83% rename from langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java rename to langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java index 000eedddeb19..a8fedfb505c3 100644 --- a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/AutoCloseChannels.java +++ b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java @@ -27,7 +27,7 @@ * * @since 2201.9.0 */ -public class AutoCloseChannels { +public class WorkerChannels { /** * Auto-closes the specified worker channels if they exist; otherwise, closes them upon creation. @@ -38,12 +38,8 @@ public static void autoClose(BString[] channelIds) { Strand parent = Scheduler.getStrand().parent; for (BString channelId : channelIds) { String channelName = channelId.getValue() + ":" + (parent.functionInvocation - 1); - autoCloseChannel(channelName, parent); + WorkerDataChannel workerDataChannel = parent.wdChannels.getWorkerDataChannel(channelName); + workerDataChannel.autoClose(); } } - - private static void autoCloseChannel(String channelId, Strand parent) { - WorkerDataChannel workerDataChannel = parent.wdChannels.getWorkerDataChannel(channelId); - workerDataChannel.autoClose(); - } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 7eb765c4af46..58717c212b59 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -58,7 +58,6 @@ public static String[] functionProvider() { "sameWorkerSendReceiverPanic", "sameWorkerSendMultiplePath1", "sameWorkerSendMultiplePath2", -// TODO: Enable these tests when it is compiling "sameWorkerSendMultiplePathError1", "sameWorkerSendMultiplePathError2", "sameWorkerSendMultiplePathError3", diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index 5bebe54fe546..82736b533cdc 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -73,7 +73,7 @@ function sameWorkerSendTest() { test:assertTrue(b is error); error e = b; test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); - test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w2'\"}", "Invalid error detail"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w2'\"}", "Invalid error detail"); } _ = wait {a: w1, b: w2}; @@ -408,7 +408,7 @@ function multipleReceiveConditional() { test:assertTrue(mapResult["c"] is error, "Expected error result"); error e = mapResult["c"]; test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); - test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w3'\"}", "Invalid error detail"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); } function multipleReceiveWithNonConditionalSend() { @@ -421,7 +421,7 @@ function multipleReceiveWithNonConditionalSend() { test:assertTrue(y is error, "Invalid error result"); error e = y; test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); - test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w3'\"}", "Invalid error detail"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); test:assertEquals(z, 4, "Invalid int result"); } From 3064cec0a7d70ad68099a08b22ba0cc48bbd7aa9 Mon Sep 17 00:00:00 2001 From: poorna2152 Date: Fri, 15 Dec 2023 16:56:26 +0530 Subject: [PATCH 42/97] Address review suggestions --- .../compiler/internal/parser/BallerinaParser.java | 14 +++----------- .../receive-action/receive_action_assert_01.json | 6 ++---- .../receive-action/receive_action_assert_02.json | 3 +-- .../receive-action/receive_action_assert_04.json | 15 +++++---------- .../send-action/send_action_assert_02.json | 6 ++---- .../send-action/send_action_assert_04.json | 6 ++---- .../misc/completion/completion_assert_08.json | 6 ++++++ .../misc/completion/completion_source_08.bal | 2 +- .../formatter/core/FormattingTreeModifier.java | 9 +++++++-- .../send-receive/assert/send_receive_action_4.bal | 10 ++++++++++ .../send-receive/source/send_receive_action_4.bal | 9 +++++++++ 11 files changed, 48 insertions(+), 38 deletions(-) diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index d17a061f9a86..4c06f11a3c28 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13038,21 +13038,14 @@ private STNode parseSyncSendAction(STNode expression) { * @return peer worker name node */ private STNode parsePeerWorkerName() { - return STNodeFactory.createSimpleNameReferenceNode(parsePeerWorkerIdentifier()); - } - - private STNode parsePeerWorkerIdentifier() { STToken token = peek(); switch (token.kind) { case IDENTIFIER_TOKEN: - return consume(); case FUNCTION_KEYWORD: - STToken functionKeyword = consume(); - return STNodeFactory.createIdentifierToken(functionKeyword.text(), functionKeyword.leadingMinutiae(), - functionKeyword.trailingMinutiae(), functionKeyword.diagnostics()); + return STNodeFactory.createSimpleNameReferenceNode(consume()); default: recover(token, ParserRuleContext.PEER_WORKER_NAME); - return parsePeerWorkerIdentifier(); + return parsePeerWorkerName(); } } @@ -13232,8 +13225,7 @@ private STNode createReceiveField(STNode identifier) { identifier = STNodeFactory.createSimpleNameReferenceNode(identifier); STNode colon = parseColon(); - STNode peerWorker = parsePeerWorkerIdentifier(); - peerWorker = STNodeFactory.createSimpleNameReferenceNode(peerWorker); + STNode peerWorker = parsePeerWorkerName(); return STNodeFactory.createReceiveFieldNode(identifier, colon, peerWorker); } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index 1a683f8dd921..0614217f73ce 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -83,8 +83,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } @@ -496,8 +495,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index 041430fe3cd1..d3fa057f8f2f 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -636,8 +636,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 5d1b36d39904..19961f156696 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -334,8 +334,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -358,8 +357,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } @@ -560,8 +558,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -584,8 +581,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -685,8 +681,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json index 094228f66893..3bc47de77079 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_02.json @@ -242,8 +242,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } @@ -324,8 +323,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function" + "kind": "FUNCTION_KEYWORD" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json index e66253ec076d..8d9b27c8a067 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/send-action/send_action_assert_04.json @@ -310,8 +310,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", @@ -407,8 +406,7 @@ "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "function", + "kind": "FUNCTION_KEYWORD", "trailingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json index a8cbb7f6af1b..d92545238d4f 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json @@ -1261,6 +1261,12 @@ }, { "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], "trailingMinutiae": [ { "kind": "END_OF_LINE_MINUTIAE", diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal index b2af46caabd3..f738f85855ef 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_source_08.bal @@ -27,7 +27,7 @@ function foo6() { function foo7() { <- { a: } -} + } function foo8() { flush diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 2ee8a1cb59c1..6636979456fd 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -3008,14 +3008,19 @@ public ReceiveActionNode transform(ReceiveActionNode receiveActionNode) { @Override public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { - int trailingNL = shouldExpand(receiveFieldsNode) ? 1 : 0; + boolean preserveIndent = env.preserveIndentation; + preserveIndentation(false); + boolean isMultiline = shouldExpand(receiveFieldsNode); + int trailingNL = isMultiline ? 1 : 0; + int trailingWS = isMultiline ? 0 : 1; Token openBrace = formatToken(receiveFieldsNode.openBrace(), 0, trailingNL); indent(); SeparatedNodeList receiveFields = - formatSeparatedNodeList(receiveFieldsNode.receiveFields(), 0, 0, 1 - trailingNL, trailingNL, 0, + formatSeparatedNodeList(receiveFieldsNode.receiveFields(), 0, 0, trailingWS, trailingNL, 0, trailingNL); unindent(); Token closeBrace = formatToken(receiveFieldsNode.closeBrace(), env.trailingWS, env.trailingNL); + preserveIndentation(preserveIndent); return receiveFieldsNode.modify() .withOpenBrace(openBrace) .withReceiveFields(receiveFields) diff --git a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal index 8e437cf5bc57..22a414bfd67b 100644 --- a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal +++ b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/assert/send_receive_action_4.bal @@ -55,3 +55,13 @@ function foz() { }; } } + +function foooz() { + do { + _ = <- + { + a: w1, + b: w2 + }; + } +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal index beb15b156a63..e93955324332 100644 --- a/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal +++ b/misc/formatter/modules/formatter-core/src/test/resources/actions/send-receive/source/send_receive_action_4.bal @@ -44,3 +44,12 @@ function foz() { tooLengthyWorkerName}; } } + +function foooz() { + do { + _ = <- +{ +a: w1,b: w2 +}; + } +} From 0d2b913e5c25a0191f324f1316fe19576a57a0f2 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 20 Dec 2023 16:38:15 +0530 Subject: [PATCH 43/97] Fix multiple receive type checking --- .../util/diagnostic/DiagnosticErrorCode.java | 3 +- .../semantics/analyzer/TypeChecker.java | 110 +++++++++++++++++- .../src/main/resources/compiler.properties | 6 + 3 files changed, 117 insertions(+), 2 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 9f79e4e65244..981744ce3579 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -584,9 +584,10 @@ public enum DiagnosticErrorCode implements DiagnosticCode { // Worker receive and send related error codes INVALID_TYPE_FOR_RECEIVE("BCE3840", "invalid.type.for.receive"), INVALID_TYPE_FOR_SEND("BCE3841", "invalid.type.for.send"), - INVALID_USAGE_OF_RECEIVE_EXPRESSION("BCE3842", "invalid.usage.of.receive.expression"), INVALID_USE_OF_EXPERIMENTAL_FEATURE("BCE3843", "invalid.use.of.experimental.feature"), + MULTIPLE_RECEIVE_COMPATIBLE_TYPE_NOT_FOUND("BCE3844", "multiple.receive.compatible.type.not.found"), + DUPLICATE_KEY_IN_MULTIPLE_RECEIVE("BCE3845", "duplicate.key.in.multiple.receive"), // LangLib related error codes. TYPE_PARAM_OUTSIDE_LANG_MODULE("BCE3900", "type.param.outside.lang.module"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index e0ef8e985e40..80c21492248a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2861,9 +2861,117 @@ public void visit(BLangAlternateWorkerReceive altWorkerReceive, AnalyzerData dat @Override public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData data) { + BType compatibleType = validateAndGetMultipleReceiveCompatibleType(data.expType, multipleWorkerReceive, data); + if (symTable.semanticError.tag == compatibleType.tag) { + data.resultType = symTable.semanticError; + return; + } + + data.resultType = compatibleType; + + if (TypeTags.RECORD == compatibleType.tag) { + BRecordType recordType = (BRecordType) compatibleType; + for (BLangMultipleWorkerReceive.BLangReceiveField receiveFiled : multipleWorkerReceive.getReceiveFields()) { + BField bField = recordType.fields.get(receiveFiled.getKey().value); + BType receiveFieldExpType; + if (bField != null) { + receiveFieldExpType = bField.type; + } else { + receiveFieldExpType = recordType.restFieldType; + } + + checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); + } + return; + } + + BType receiveFieldExpType; + if (TypeTags.MAP == compatibleType.tag) { + receiveFieldExpType = ((BMapType) compatibleType).constraint; + } else { + assert TypeTags.READONLY == compatibleType.tag; + receiveFieldExpType = compatibleType; + } + for (BLangMultipleWorkerReceive.BLangReceiveField receiveFiled : multipleWorkerReceive.getReceiveFields()) { - receiveFiled.getWorkerReceive().accept(this, data); + checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); + } + } + + private BType validateAndGetMultipleReceiveCompatibleType(BType bType, + BLangMultipleWorkerReceive multipleWorkerReceive, + AnalyzerData data) { + HashSet multipleReceiveFieldNames = new HashSet<>(); + for (BLangMultipleWorkerReceive.BLangReceiveField receiveField : multipleWorkerReceive.getReceiveFields()) { + BLangIdentifier key = receiveField.getKey(); + String fieldName = key.value; + if (!multipleReceiveFieldNames.add(fieldName)) { + dlog.error(key.pos, DiagnosticErrorCode.DUPLICATE_KEY_IN_MULTIPLE_RECEIVE, fieldName); + } + } + + BType impliedType = Types.getImpliedType(bType); + if (impliedType.tag != TypeTags.UNION) { + BType compatibleType = getMappingConstructorCompatibleNonUnionType(impliedType, data); + if (symTable.semanticError.tag == compatibleType.tag || (TypeTags.RECORD == compatibleType.tag && + !fieldsCompatibleWithRecord(multipleReceiveFieldNames, (BRecordType) compatibleType))) { + dlog.error(multipleWorkerReceive.pos, DiagnosticErrorCode.MULTIPLE_RECEIVE_COMPATIBLE_TYPE_NOT_FOUND, + impliedType); + return symTable.semanticError; + } + return compatibleType; } + + List compatibleTypes = new ArrayList<>(); + for (BType memberType : ((BUnionType) impliedType).getMemberTypes()) { + BType impType = Types.getImpliedType(memberType); + BType compatibleType = getMappingConstructorCompatibleNonUnionType(impType, data); + + if (TypeTags.RECORD == compatibleType.tag && + !fieldsCompatibleWithRecord(multipleReceiveFieldNames, (BRecordType) compatibleType)) { + continue; + } + + if (symTable.semanticError.tag != compatibleType.tag) { + compatibleTypes.add(compatibleType); + } + } + + if (compatibleTypes.isEmpty()) { + dlog.error(multipleWorkerReceive.pos, DiagnosticErrorCode.MULTIPLE_RECEIVE_COMPATIBLE_TYPE_NOT_FOUND, + impliedType); + return symTable.semanticError; + } + + if (compatibleTypes.size() > 1) { + dlog.error(multipleWorkerReceive.pos, DiagnosticErrorCode.AMBIGUOUS_TYPES, impliedType); + return symTable.semanticError; + } + + return compatibleTypes.get(0); + } + + private boolean fieldsCompatibleWithRecord(HashSet fieldNames, BRecordType recordType) { + HashSet clonedFieldNames = new HashSet<>(fieldNames); + for (BField field : recordType.fields.values()) { + if (!types.isNeverTypeOrStructureTypeWithARequiredNeverMember(field.type)) { + // matching up field names against the record fields + if (clonedFieldNames.remove(field.name.value)) { + continue; + } + + if (Symbols.isFlagOn(field.symbol.flags, Flags.REQUIRED)) { + return false; + } + } + } + + if (!clonedFieldNames.isEmpty()) { + // matching the remaining field names to record rest field + return recordType.restFieldType != null && recordType.restFieldType.tag != TypeTags.NONE; + } + + return true; } @Override diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 76166a081ed6..d5bc72c9b478 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -441,6 +441,12 @@ error.invalid.type.for.send=\ error.invalid.usage.of.receive.expression=\ invalid usage of receive expression, var not allowed +error.multiple.receive.compatible.type.not.found=\ + a type compatible with multiple receive not found in type ''{0}'' + +error.duplicate.key.in.multiple.receive=\ + invalid multiple receive: duplicate key ''{0}'' + error.invalid.wait.future.expr.mapping.constructors=\ ''wait'' cannot be used with mapping constructors From 96a16d00e7c4404d4ec77926f04c8b7716eac0ca Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:15:26 +0530 Subject: [PATCH 44/97] Fix worker send/receive allowed positions --- .../semantics/analyzer/CodeAnalyzer.java | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index cbb1e55e7164..ddb5958061c8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -72,6 +72,7 @@ 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.BLangFunctionBody; import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; import org.wso2.ballerinalang.compiler.tree.BLangImportPackage; import org.wso2.ballerinalang.compiler.tree.BLangInvokableNode; @@ -262,6 +263,7 @@ import java.util.Objects; import java.util.Set; import java.util.Stack; +import java.util.function.Predicate; import java.util.stream.Collectors; import static org.ballerinalang.model.tree.NodeKind.LITERAL; @@ -1511,15 +1513,12 @@ public void visit(BLangWhile whileNode, AnalyzerData data) { public void visit(BLangDo doNode, AnalyzerData data) { boolean onFailExists = doNode.onFailClause != null; boolean failureHandled = data.failureHandled; - boolean previousWithinDoBlock = data.withinWorkerTopLevelDo; - data.withinWorkerTopLevelDo = isTopLevel(data.env) && isInWorker(data.env); if (onFailExists) { data.failureHandled = true; } analyzeNode(doNode.body, data); data.failureHandled = failureHandled; analyseOnFailClause(onFailExists, doNode.onFailClause, data); - data.withinWorkerTopLevelDo = previousWithinDoBlock; } @@ -1953,21 +1952,41 @@ public void visit(BLangExpressionStmt exprStmtNode, AnalyzerData data) { analyzeExpr(expr, data); } - private boolean isTopLevel(SymbolEnv env) { - return env.enclInvokable.body == env.node; - } - private boolean isInWorker(SymbolEnv env) { return env.enclInvokable.flagSet.contains(Flag.WORKER); } - private boolean isReceiveAllowedLocation(SymbolEnv env) { - return isTopLevel(env); + private boolean isSendAllowedLocation(BLangFunctionBody enclInvokableBody, BLangNode node) { + return isCommunicationAllowedContext(enclInvokableBody, node, this::isSendAllowedContext); } - private boolean isSendAllowedLocation(SymbolEnv env) { - return true; -// return isTopLevel(env) || env.node.parent.getKind() == NodeKind.IF; // TODO: fix properly + private boolean isReceiveAllowedLocation(BLangFunctionBody enclInvokableBody, BLangNode node) { + return isCommunicationAllowedContext(enclInvokableBody, node, this::isReceiveAllowedContext); + } + + private boolean isSendAllowedContext(BLangNode bLangNode) { + return isReceiveAllowedContext(bLangNode) || bLangNode.getKind() == NodeKind.IF; + } + + private boolean isReceiveAllowedContext(BLangNode bLangNode) { + return switch (bLangNode.getKind()) { + case BLOCK_FUNCTION_BODY, BLOCK, ON_FAIL, DO_STMT -> true; + default -> false; + }; + } + + private boolean isCommunicationAllowedContext(BLangFunctionBody enclInvokableBody, BLangNode node, + Predicate contextChecker) { + if (enclInvokableBody == node) { + return true; + } + + BLangNode parentNode = node.parent; + if (contextChecker.test(parentNode)) { + return isCommunicationAllowedContext(enclInvokableBody, parentNode, contextChecker); + } + + return false; } private boolean isDefaultWorkerCommunication(String workerIdentifier) { @@ -2011,8 +2030,8 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } String workerName = asyncSendExpr.workerIdentifier.getValue(); - if (!data.withinWorkerTopLevelDo && (data.withinQuery || - (!isSendAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { + if (data.withinQuery || (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && + !data.inInternallyDefinedBlockStmt)) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2071,8 +2090,8 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - if (!data.withinWorkerTopLevelDo && (data.withinQuery || - (!isSendAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt))) { + if (data.withinQuery || (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && + !data.inInternallyDefinedBlockStmt)) { this.dlog.error(syncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2123,7 +2142,8 @@ public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { } String workerName = workerReceiveNode.workerIdentifier.getValue(); - if (data.withinQuery || (!isReceiveAllowedLocation(data.env) && !data.inInternallyDefinedBlockStmt)) { + if (data.withinQuery || (!isReceiveAllowedLocation(data.env.enclInvokable.body, data.env.node) && + !data.inInternallyDefinedBlockStmt)) { this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.INVALID_WORKER_RECEIVE_POSITION); was.hasErrors = true; } @@ -4274,7 +4294,6 @@ public static class AnalyzerData { boolean loopAlterNotAllowed; // Fields related to worker system boolean inInternallyDefinedBlockStmt; - boolean withinWorkerTopLevelDo; int workerSystemMovementSequence; Stack workerActionSystemStack = new Stack<>(); Map> workerReferences = new HashMap<>(); From b464faed9c8d9ef55209eb94da464ad4855b3200 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 21 Dec 2023 11:45:28 +0530 Subject: [PATCH 45/97] Move negative test to positive --- .../worker/WorkerConditionalSendTest.java | 3 ++- .../test/worker/WorkerFailTest.java | 8 ------- .../workers/invalid-send-with-return.bal | 23 ------------------- .../workers/workers_conditional_send.bal | 22 ++++++++++++++++++ 4 files changed, 24 insertions(+), 32 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 58717c212b59..83760423b7d3 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -63,7 +63,8 @@ public static String[] functionProvider() { "sameWorkerSendMultiplePathError3", "sameWorkerSendMultiplePathError4", "multipleReceiveConditional", - "multipleReceiveWithNonConditionalSend" + "multipleReceiveWithNonConditionalSend", + "testNonTopLevelSend" }; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 23a029fc03e4..ec18c9404f20 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -76,14 +76,6 @@ public void invalidSendInLambda() { Assert.assertTrue(message.contains("undefined worker"), message); } - @Test - public void invalidSendWithReturnTest() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-send-with-return.bal"); - Assert.assertEquals(result.getErrorCount(), 1); - String message = result.getDiagnostics()[0].message(); - Assert.assertTrue(message.contains("can not be used after a non-error return"), message); - } - @Test public void invalidSendWithErrorReturnTest() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-send-with-error-return.bal"); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal deleted file mode 100644 index 21707110cb97..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal +++ /dev/null @@ -1,23 +0,0 @@ -import ballerina/jballerina.java; - -public function main() { - worker w1 returns boolean|error{ - int i = 2; - if (0 > 1) { - return true; - } - i -> w2; - println("w1"); - return false; - } - - worker w2 { - int j = 25; - j = <- w1; - println(j); - } -} - -public function println(any|error... values) = @java:Method { - 'class: "org.ballerinalang.test.utils.interop.Utils" -} external; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index 82736b533cdc..dec4ec02e7cf 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -435,3 +435,25 @@ function multipleReceiveWithNonConditionalSend() { } wait w3; } + +function testNonTopLevelSend() { + worker w1 returns boolean { + int i = 2; + if (0 > 1) { + return true; + } + i -> w2; + return false; + } + + worker w2 returns int { + int j = 25; + j = <- w1; + return j; + } + + map mapResult = wait {a: w1, b: w2}; + test:assertEquals(mapResult["a"], false, "Invalid boolean result"); + test:assertEquals(mapResult["b"], 2, "Invalid int result"); +} + From 2f3570a747669fd2da79c38b901495eea282fefd Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Dec 2023 12:58:57 +0530 Subject: [PATCH 46/97] Temporary disable failing 2 tests --- .../org/ballerinalang/test/query/QueryActionOrExprTest.java | 2 +- .../test/java/org/ballerinalang/test/worker/WorkerFailTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java index 658f912fd9c3..1f9bb3e09d61 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java @@ -89,7 +89,7 @@ public void testQueryingEmptyTuple() { BRunUtil.invoke(compileResult, "testQueryingEmptyTuple"); } - @Test + @Test(enabled = false) // TODO: enable public void testQueryActionOrExprSemanticsNegative() { CompileResult negativeResult = BCompileUtil.compile( "test-src/query/query_action_or_expr_semantic_negative.bal"); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 23a029fc03e4..948df9f6cb10 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -76,7 +76,7 @@ public void invalidSendInLambda() { Assert.assertTrue(message.contains("undefined worker"), message); } - @Test + @Test(enabled = false) // TODO: enable public void invalidSendWithReturnTest() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-send-with-return.bal"); Assert.assertEquals(result.getErrorCount(), 1); From f9d6b59a16de2d8827d65a270a2a75263c23a9e9 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Dec 2023 13:38:48 +0530 Subject: [PATCH 47/97] Fix worker send/receive failure type population --- .../util/diagnostic/DiagnosticErrorCode.java | 4 +- .../semantics/analyzer/CodeAnalyzer.java | 44 +++++++------------ .../semantics/analyzer/TypeChecker.java | 3 ++ .../worker/WorkerConditionalSendTest.java | 1 - 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 981744ce3579..2a7f68084a4f 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -119,8 +119,8 @@ public enum DiagnosticErrorCode implements DiagnosticCode { WORKER_SEND_RECEIVE_PARAMETER_COUNT_MISMATCH("BCE2082", "worker.send.receive.parameter.count.mismatch"), INVALID_WORKER_INTERACTION("BCE2083", "worker.invalid.worker.interaction"), WORKER_INTERACTIONS_ONLY_ALLOWED_BETWEEN_PEERS("BCE2084", "worker.interactions.only.allowed.between.peers"), - WORKER_SEND_AFTER_RETURN("BCE2085", "worker.send.after.return"), - WORKER_RECEIVE_AFTER_RETURN("BCE2086", "worker.receive.after.return"), + // VACANT_ERROR("BCE2085", ""), + // VACANT_ERROR("BCE2086", ""), EXPLICIT_WORKER_CANNOT_BE_DEFAULT("BCE2087", "explicit.worker.cannot.be.default"), INVALID_MULTIPLE_FORK_JOIN_SEND("BCE2088", "worker.multiple.fork.join.send"), INCOMPATIBLE_TYPE_REFERENCE("BCE2089", "incompatible.type.reference"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index ddb5958061c8..f5d7dae0b1d4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -2042,14 +2042,13 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { was.hasErrors = true; } - asyncSendExpr.sendType = - createAccumulatedErrorTypeForMatchingReceive(asyncSendExpr.pos, asyncSendExpr.expr.getBType(), data); + asyncSendExpr.sendType = createAccumulatedErrorTypeForMatchingReceive(asyncSendExpr.expr.getBType(), data); was.addWorkerAction(asyncSendExpr); analyzeExpr(asyncSendExpr.expr, data); validateActionParentNode(asyncSendExpr.pos, asyncSendExpr.expr); } - private BType createAccumulatedErrorTypeForMatchingReceive(Location pos, BType exprType, AnalyzerData data) { + private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, AnalyzerData data) { Set returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>() { { @@ -2057,11 +2056,7 @@ private BType createAccumulatedErrorTypeForMatchingReceive(Location pos, BType e } }; for (BType returnType : returnTypesUpToNow) { - if (onlyContainErrors(returnType)) { - returnTypeAndSendType.add(returnType); - } else { -// this.dlog.error(pos, DiagnosticErrorCode.WORKER_SEND_AFTER_RETURN); TODO: fix - } + returnTypeAndSendType.addAll(getErrorTypes(returnType)); } returnTypeAndSendType.add(exprType); if (returnTypeAndSendType.size() > 1) { @@ -2102,8 +2097,7 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { } syncSendExpr.setBType(BUnionType.create(null, symTable.nilType, symTable.errorType)); - syncSendExpr.sendType = - createAccumulatedErrorTypeForMatchingReceive(syncSendExpr.pos, syncSendExpr.expr.getBType(), data); + syncSendExpr.sendType = createAccumulatedErrorTypeForMatchingReceive(syncSendExpr.expr.getBType(), data); was.addWorkerAction(syncSendExpr); analyzeExpr(syncSendExpr.expr, data); } @@ -2196,11 +2190,7 @@ public BType createAccumulatedErrorTypeForMatchingSyncSend(BLangWorkerReceive wo Set returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>(); for (BType returnType : returnTypesUpToNow) { - if (onlyContainErrors(returnType)) { - returnTypeAndSendType.add(returnType); - } else { -// this.dlog.error(workerReceiveNode.pos, DiagnosticErrorCode.WORKER_RECEIVE_AFTER_RETURN); TODO: fix - } + returnTypeAndSendType.addAll(getErrorTypes(returnType)); } returnTypeAndSendType.add(symTable.nilType); if (returnTypeAndSendType.size() > 1) { @@ -2210,27 +2200,25 @@ public BType createAccumulatedErrorTypeForMatchingSyncSend(BLangWorkerReceive wo } } - private boolean onlyContainErrors(BType returnType) { + private LinkedHashSet getErrorTypes(BType returnType) { + LinkedHashSet errorTypes = new LinkedHashSet<>(); if (returnType == null) { - return false; - } - - returnType = types.getTypeWithEffectiveIntersectionTypes(returnType); - returnType = Types.getImpliedType(returnType); - if (returnType.tag == TypeTags.ERROR) { - return true; + return errorTypes; } - if (returnType.tag == TypeTags.UNION) { + BType effType = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(returnType)); + if (effType.tag == TypeTags.ERROR) { + errorTypes.add(returnType); + } else if (returnType.tag == TypeTags.UNION) { for (BType memberType : ((BUnionType) returnType).getMemberTypes()) { BType t = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(memberType)); - if (t.tag != TypeTags.ERROR) { - return false; + if (t.tag == TypeTags.ERROR) { + errorTypes.add(memberType); } } - return true; } - return false; + + return errorTypes; } @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 80c21492248a..5eee6537772b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2857,6 +2857,8 @@ public void visit(BLangAlternateWorkerReceive altWorkerReceive, AnalyzerData dat for (BLangWorkerReceive bLangWorkerReceive : altWorkerReceive.getWorkerReceives()) { bLangWorkerReceive.accept(this, data); } + altWorkerReceive.setBType(data.expType); + data.resultType = data.expType; } @Override @@ -2867,6 +2869,7 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData return; } + multipleWorkerReceive.setBType(compatibleType); data.resultType = compatibleType; if (TypeTags.RECORD == compatibleType.tag) { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 7eb765c4af46..58717c212b59 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -58,7 +58,6 @@ public static String[] functionProvider() { "sameWorkerSendReceiverPanic", "sameWorkerSendMultiplePath1", "sameWorkerSendMultiplePath2", -// TODO: Enable these tests when it is compiling "sameWorkerSendMultiplePathError1", "sameWorkerSendMultiplePathError2", "sameWorkerSendMultiplePathError3", From 5a4a95fc019b6815534121f90323fc07113d6bdf Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:16:30 +0530 Subject: [PATCH 48/97] Add no message error type for worker interactions --- .../semantics/analyzer/CodeAnalyzer.java | 49 +++++++++++++++---- .../lang.error/src/main/ballerina/error.bal | 3 ++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index f5d7dae0b1d4..84b0c431df87 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -284,8 +284,8 @@ */ public class CodeAnalyzer extends SimpleBLangNodeAnalyzer { - private static final CompilerContext.Key CODE_ANALYZER_KEY = - new CompilerContext.Key<>(); + private static final CompilerContext.Key CODE_ANALYZER_KEY = new CompilerContext.Key<>(); + private static final String NO_MESSAGE_ERROR_TYPE = "NoMessageError"; private final SymbolResolver symResolver; private final SymbolTable symTable; @@ -1989,6 +1989,19 @@ private boolean isCommunicationAllowedContext(BLangFunctionBody enclInvokableBod return false; } + private boolean withinIf(BLangFunctionBody enclInvokableBody, BLangNode node) { + if (enclInvokableBody == node) { + return false; + } + + BLangNode parentNode = node.parent; + if (parentNode.getKind() == NodeKind.IF) { + return true; + } + + return withinIf(enclInvokableBody, parentNode); + } + private boolean isDefaultWorkerCommunication(String workerIdentifier) { return workerIdentifier.equals(DEFAULT_WORKER_NAME); } @@ -2029,26 +2042,30 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { this.dlog.error(asyncSendExpr.expr.pos, DiagnosticErrorCode.INVALID_SEND_EXPR); } - String workerName = asyncSendExpr.workerIdentifier.getValue(); - if (data.withinQuery || (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && - !data.inInternallyDefinedBlockStmt)) { + boolean invalidSendPos = data.withinQuery || + (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && + !data.inInternallyDefinedBlockStmt); + if (invalidSendPos) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } + String workerName = asyncSendExpr.workerIdentifier.getValue(); if (!this.workerExists(asyncSendExpr.workerType, workerName, data.env) || (!isWorkerFromFunction(data.env, names.fromString(workerName)) && !workerName.equals("function"))) { this.dlog.error(asyncSendExpr.pos, DiagnosticErrorCode.UNDEFINED_WORKER, workerName); was.hasErrors = true; } - asyncSendExpr.sendType = createAccumulatedErrorTypeForMatchingReceive(asyncSendExpr.expr.getBType(), data); + boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); + asyncSendExpr.sendType = + createAccumulatedErrorTypeForMatchingReceive(asyncSendExpr.expr.getBType(), withinIf, data); was.addWorkerAction(asyncSendExpr); analyzeExpr(asyncSendExpr.expr, data); validateActionParentNode(asyncSendExpr.pos, asyncSendExpr.expr); } - private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, AnalyzerData data) { + private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, boolean withinIf, AnalyzerData data) { Set returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>() { { @@ -2059,6 +2076,14 @@ private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, Analy returnTypeAndSendType.addAll(getErrorTypes(returnType)); } returnTypeAndSendType.add(exprType); + + if (withinIf || !returnTypesUpToNow.isEmpty()) { + // There is a possibility that the send action may not be executed, thus adding NoMessageError type. + BSymbol noMsgErrSymbol = symTable.langErrorModuleSymbol.scope. + lookup(Names.fromString(NO_MESSAGE_ERROR_TYPE)).symbol; + returnTypeAndSendType.add(noMsgErrSymbol.getType()); + } + if (returnTypeAndSendType.size() > 1) { return BUnionType.create(null, returnTypeAndSendType); } else { @@ -2085,8 +2110,10 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { was.hasErrors = true; } - if (data.withinQuery || (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && - !data.inInternallyDefinedBlockStmt)) { + boolean invalidSendPos = data.withinQuery || + (!isSendAllowedLocation(data.env.enclInvokable.body, data.env.node) && + !data.inInternallyDefinedBlockStmt); + if (invalidSendPos) { this.dlog.error(syncSendExpr.pos, DiagnosticErrorCode.UNSUPPORTED_WORKER_SEND_POSITION); was.hasErrors = true; } @@ -2097,7 +2124,9 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { } syncSendExpr.setBType(BUnionType.create(null, symTable.nilType, symTable.errorType)); - syncSendExpr.sendType = createAccumulatedErrorTypeForMatchingReceive(syncSendExpr.expr.getBType(), data); + boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); + syncSendExpr.sendType = + createAccumulatedErrorTypeForMatchingReceive(syncSendExpr.expr.getBType(), withinIf, data); was.addWorkerAction(syncSendExpr); analyzeExpr(syncSendExpr.expr, data); } diff --git a/langlib/lang.error/src/main/ballerina/error.bal b/langlib/lang.error/src/main/ballerina/error.bal index fc9b87cdac92..95a8fb21a9a3 100644 --- a/langlib/lang.error/src/main/ballerina/error.bal +++ b/langlib/lang.error/src/main/ballerina/error.bal @@ -16,6 +16,9 @@ import ballerina/jballerina.java; +# Error type representing the no message error in worker interactions. +public type NoMessageError distinct error; + # Type for value that can be cloned. # This is the same as in lang.value, but is copied here to avoid a dependency. public type Cloneable readonly|xml|Cloneable[]|map|table>; From c242c8d46e628bb413734151010d12a25895e5d7 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:12:24 +0530 Subject: [PATCH 49/97] Fix result type for multiple receive action --- .../ballerinalang/compiler/semantics/analyzer/TypeChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 5eee6537772b..6b101e6ae4c5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2870,7 +2870,6 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData } multipleWorkerReceive.setBType(compatibleType); - data.resultType = compatibleType; if (TypeTags.RECORD == compatibleType.tag) { BRecordType recordType = (BRecordType) compatibleType; @@ -2899,6 +2898,7 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData for (BLangMultipleWorkerReceive.BLangReceiveField receiveFiled : multipleWorkerReceive.getReceiveFields()) { checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); } + data.resultType = compatibleType; } private BType validateAndGetMultipleReceiveCompatibleType(BType bType, From c786533f6396a4ccd796ecc58a231080359901be Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 2 Jan 2024 15:12:24 +0530 Subject: [PATCH 50/97] Fix result type for multiple receive action --- .../ballerinalang/compiler/semantics/analyzer/TypeChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 5eee6537772b..6b101e6ae4c5 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2870,7 +2870,6 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData } multipleWorkerReceive.setBType(compatibleType); - data.resultType = compatibleType; if (TypeTags.RECORD == compatibleType.tag) { BRecordType recordType = (BRecordType) compatibleType; @@ -2899,6 +2898,7 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData for (BLangMultipleWorkerReceive.BLangReceiveField receiveFiled : multipleWorkerReceive.getReceiveFields()) { checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); } + data.resultType = compatibleType; } private BType validateAndGetMultipleReceiveCompatibleType(BType bType, From f7f73d4793548d4595764016ee4ab991d41d6d6b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:44:35 +0530 Subject: [PATCH 51/97] Fix NoMessageError when there are error only returns --- .../semantics/analyzer/CodeAnalyzer.java | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 84b0c431df87..5f706643c02e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -2072,12 +2072,17 @@ private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, boole Comparator.comparing(BType::toString); } }; + + boolean hasNonErrorReturn = false; for (BType returnType : returnTypesUpToNow) { - returnTypeAndSendType.addAll(getErrorTypes(returnType)); + addErrorTypesToSet(returnType, returnTypeAndSendType); + if (hasNonErrorType(returnType)) { + hasNonErrorReturn = true; + } } returnTypeAndSendType.add(exprType); - if (withinIf || !returnTypesUpToNow.isEmpty()) { + if (withinIf || hasNonErrorReturn) { // There is a possibility that the send action may not be executed, thus adding NoMessageError type. BSymbol noMsgErrSymbol = symTable.langErrorModuleSymbol.scope. lookup(Names.fromString(NO_MESSAGE_ERROR_TYPE)).symbol; @@ -2176,7 +2181,7 @@ public void visit(BLangWorkerReceive workerReceiveNode, AnalyzerData data) { was.hasErrors = true; } - workerReceiveNode.matchingSendsError = createAccumulatedErrorTypeForMatchingSyncSend(workerReceiveNode, data); + workerReceiveNode.matchingSendsError = createAccumulatedErrorTypeForMatchingSyncSend(data); was.addWorkerAction(workerReceiveNode); } @@ -2214,12 +2219,11 @@ private void verifyPeerCommunication(Location pos, BSymbol otherWorker, String o } } - public BType createAccumulatedErrorTypeForMatchingSyncSend(BLangWorkerReceive workerReceiveNode, - AnalyzerData data) { - Set returnTypesUpToNow = data.returnTypes.peek(); + public BType createAccumulatedErrorTypeForMatchingSyncSend(AnalyzerData data) { + LinkedHashSet returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>(); for (BType returnType : returnTypesUpToNow) { - returnTypeAndSendType.addAll(getErrorTypes(returnType)); + addErrorTypesToSet(returnType, returnTypeAndSendType); } returnTypeAndSendType.add(symTable.nilType); if (returnTypeAndSendType.size() > 1) { @@ -2229,25 +2233,44 @@ public BType createAccumulatedErrorTypeForMatchingSyncSend(BLangWorkerReceive wo } } - private LinkedHashSet getErrorTypes(BType returnType) { - LinkedHashSet errorTypes = new LinkedHashSet<>(); + private void addErrorTypesToSet(BType returnType, LinkedHashSet errorTypes) { if (returnType == null) { - return errorTypes; + return; } BType effType = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(returnType)); if (effType.tag == TypeTags.ERROR) { errorTypes.add(returnType); - } else if (returnType.tag == TypeTags.UNION) { - for (BType memberType : ((BUnionType) returnType).getMemberTypes()) { + } else if (effType.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) effType).getMemberTypes()) { BType t = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(memberType)); if (t.tag == TypeTags.ERROR) { errorTypes.add(memberType); } } } + } + + private boolean hasNonErrorType(BType returnType) { + if (returnType == null) { + return false; + } - return errorTypes; + BType effType = Types.getImpliedType(types.getTypeWithEffectiveIntersectionTypes(returnType)); + if (effType.tag == TypeTags.ERROR) { + return false; + } + + if (effType.tag == TypeTags.UNION) { + for (BType memberType : ((BUnionType) returnType).getMemberTypes()) { + if (hasNonErrorType(memberType)) { + return true; + } + } + return false; + } + + return true; } @Override From f601782214edba5d0f679d883b52ac65da579c9e Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:01:27 +0530 Subject: [PATCH 52/97] Temporary disable WorkerConditionalSendTest Failure is due to NoMessageError changes. Need to update the test. --- .../ballerinalang/test/worker/WorkerConditionalSendTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 58717c212b59..ca3ef2337f05 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -37,10 +37,10 @@ public class WorkerConditionalSendTest { @BeforeClass public void setup() { this.result = BCompileUtil.compile("test-src/workers/workers_conditional_send.bal"); - Assert.assertEquals(result.getErrorCount(), 0); +// Assert.assertEquals(result.getErrorCount(), 0); // TODO: Fix for NoMessageError } - @Test(dataProvider = "functionProvider") + @Test(dataProvider = "functionProvider", enabled = false) public void workerConditionalSendTest(String funcName) { BRunUtil.invoke(result, funcName, new Object[0]); } From 15da91b17b46fffc47c4b6c175aff375f23c2c95 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:08:03 +0530 Subject: [PATCH 53/97] Fix jballerina-unit-test:checkstyleTest failure --- .../org/ballerinalang/test/worker/WorkerConditionalSendTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index ca3ef2337f05..8422a02df484 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -21,7 +21,6 @@ import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; -import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; From 9deff3148c823374e805d037d41b1696368deeda Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 5 Jan 2024 14:49:39 +0530 Subject: [PATCH 54/97] Add multiple receive support --- .../internal/scheduling/ReceiveField.java | 46 +++++++++++++ .../runtime/internal/scheduling/Strand.java | 3 + .../internal/scheduling/WDChannels.java | 41 ++++++++++++ .../ballerinalang/compiler/bir/BIRGen.java | 26 ++++++- .../compiler/bir/codegen/JvmConstants.java | 1 + .../compiler/bir/codegen/JvmSignatures.java | 4 ++ .../bir/codegen/JvmTerminatorGen.java | 46 +++++++++++++ .../compiler/bir/model/BIRTerminator.java | 67 +++++++++++++++++++ .../compiler/bir/model/BIRVisitor.java | 3 + .../compiler/bir/model/InstructionKind.java | 1 + .../bir/optimizer/BIRLockOptimizer.java | 5 ++ .../compiler/bir/optimizer/BIROptimizer.java | 5 ++ .../bir/writer/BIRInstructionWriter.java | 13 ++++ .../compiler/parser/NodeCloner.java | 4 +- .../src/main/resources/kaitai/bir.ksy | 40 +++++++++++ 15 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java new file mode 100644 index 000000000000..94f3d7ca85eb --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * + * 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 + * + * 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 io.ballerina.runtime.internal.scheduling; + +/** + * A worker receive field for multiple receive action. + *

+ * e.g., WRK_RECEIVE {w1 , w2}; + * + * @since 2201.9.0 + */ +public class ReceiveField { + + private final String fieldName; + private final String channelName; + + public ReceiveField(String fieldName, String channelName) { + this.fieldName = fieldName; + this.channelName = channelName; + } + + public String getFieldName() { + return fieldName; + } + + public String getChannelName() { + return channelName; + } + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java index 4fce809cf3ce..d87ab6ecd33e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java @@ -23,6 +23,7 @@ import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.api.values.BError; +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.ChannelDetails; @@ -90,6 +91,8 @@ public class Strand { public Stack trxContexts; private State state; private final ReentrantLock strandLock; + public BMap mapResult = null; + public int channelCount = 0; public Strand(String name, StrandMetadata metadata, Scheduler scheduler, Strand parent, Map properties) { diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index ec407de6f8b5..d3992f51e014 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -17,6 +17,11 @@ */ package io.ballerina.runtime.internal.scheduling; +import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.Type; +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.ErrorUtils; import io.ballerina.runtime.internal.values.ErrorValue; @@ -51,6 +56,42 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { return channel; } + public Object takeMultipleChannelData(Strand strand, ReceiveField[] receiveFields, Type targetType) + throws Throwable { + if (strand.mapResult == null) { + strand.mapResult = ValueCreator.createMapValue(targetType); + } + for (ReceiveField field : receiveFields) { + WorkerDataChannel channel = getWorkerDataChannel(field.getChannelName()); + if (!channel.isClosed()) { + Object result = channel.tryTakeData(strand, true); + if (result != null) { + if (result instanceof ErrorValue errorValue) { + errors.add(errorValue); + channel.close(); + } else { + strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); + channel.close(); + } + ++strand.channelCount; + } else { + strand.setState(BLOCK_AND_YIELD); + } + } else { + if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { + errors.add((ErrorValue) ErrorUtils.createNoMessageError(field.getChannelName())); + } + } + } + if (strand.channelCount == receiveFields.length) { + BMap map = strand.mapResult; + strand.mapResult = null; + strand.channelCount = 0; + return map; + } + return null; + } + public Object tryTakeData(Strand strand, String[] channels) throws Throwable { Object result = null; boolean allChannelsClosed = true; 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 451ce0dbb812..90a9b254abba 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 @@ -33,7 +33,6 @@ import org.ballerinalang.model.tree.OperatorKind; import org.ballerinalang.model.tree.TopLevelNode; import org.ballerinalang.model.tree.expressions.RecordLiteralNode; -import org.ballerinalang.util.diagnostic.DiagnosticErrorCode; 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; @@ -1172,10 +1171,31 @@ private List getChannelList(BLangAlternateWorkerReceive alternateWorkerR return channels; } + private List getChannelList( + BLangMultipleWorkerReceive multipleWorkerReceive) { + List channels = new ArrayList<>(); + for (BLangMultipleWorkerReceive.BLangReceiveField workerReceive : multipleWorkerReceive.getReceiveFields()) { + channels.add(new BIRTerminator.WorkerMultipleReceive.ReceiveField(workerReceive.getKey().value, + workerReceive.getWorkerReceive().getChannel().channelId())); + } + return channels; + } + @Override public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { - // TODO: 24/11/23 implement - throw new AssertionError(DiagnosticErrorCode.MULTIPLE_RECEIVE_ACTION_NOT_YET_SUPPORTED); + BIRBasicBlock thenBB = new BIRBasicBlock(this.env.nextBBId()); + addToTrapStack(thenBB); + BIRVariableDcl tempVarDcl = new BIRVariableDcl(multipleWorkerReceive.getBType(), this.env.nextLocalVarId(names), + VarScope.FUNCTION, VarKind.TEMP); + this.env.enclFunc.localVars.add(tempVarDcl); + BIROperand lhsOp = new BIROperand(tempVarDcl); + this.env.targetOperand = lhsOp; + boolean isOnSameStrand = DEFAULT_WORKER_NAME.equals(this.env.enclFunc.workerName.value); + + this.env.enclBB.terminator = new BIRTerminator.WorkerMultipleReceive(multipleWorkerReceive.pos, + getChannelList(multipleWorkerReceive), lhsOp, isOnSameStrand, thenBB, this.currentScope); + this.env.enclBasicBlocks.add(thenBB); + this.env.enclBB = thenBB; } @Override 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 e545a1eee88c..1c409e2003d9 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 @@ -251,6 +251,7 @@ public class JvmConstants { public static final String SYSTEM = "java/lang/System"; public static final String BIG_DECIMAL = "java/math/BigDecimal"; public static final String STRING_CONCAT_FACTORY = "java/lang/invoke/StringConcatFactory"; + public static final String RECEIVE_FIELD = "io/ballerina/runtime/internal/scheduling/ReceiveField"; // service objects, annotation processing related classes public static final String ANNOTATION_UTILS = "io/ballerina/runtime/internal/AnnotationUtils"; 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 206410529067..8674ca3a5257 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 @@ -83,6 +83,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.OPTION; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.PATH; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.READONLY_TYPE; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.RECEIVE_FIELD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REF_VALUE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REG_EXP_ASSERTION; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.REG_EXP_ATOM_QUANTIFIER; @@ -284,6 +285,7 @@ public class JvmSignatures { public static final String INIT_BAL_ENV_WITH_FUNC_NAME = "(L" + STRAND_CLASS + ";L" + MODULE + ";L" + STRING_VALUE + ";[L" + FUNCTION_PARAMETER + ";)V"; public static final String INIT_CHANNEL_DETAILS = "(L" + STRING_VALUE + ";ZZ)V"; + public static final String INIT_RECEIVE_FIELD = "(L" + STRING_VALUE + ";L" + STRING_VALUE + ";)V"; public static final String INIT_CLI_SPEC = "(L" + OPTION + ";[L" + OPERAND + ";[L" + STRING_VALUE + ";)V"; public static final String INIT_CONFIG = "([L" + STRING_VALUE + ";[L" + PATH + ";L" + STRING_VALUE + ";)V"; public static final String INIT_CONFIGURABLES = @@ -500,6 +502,8 @@ public class JvmSignatures { public static final String GET_TEST_CONFIG_PATH = "(L" + MODULE + ";L" + STRING_VALUE + ";L" + STRING_VALUE + ";)L" + TOML_DETAILS + ";"; public static final String ALT_RECEIVE_CALL = "(L" + STRAND_CLASS + ";[L" + STRING_VALUE + ";)L" + OBJECT + ";"; + public static final String MULTIPLE_RECEIVE_CALL = "(L" + STRAND_CLASS + ";[L" + RECEIVE_FIELD + ";L" + TYPE + + ";)L" + OBJECT + ";"; private JvmSignatures() { } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 11de7a089a9b..4bf2484b72ca 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -132,6 +132,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.OBJECT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.PANIC_FIELD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.PREDEFINED_TYPES; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.RECEIVE_FIELD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.SCHEDULER; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.SCHEDULE_FUNCTION_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmConstants.SCHEDULE_LOCAL_METHOD; @@ -179,6 +180,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_ANYDATA_ARRAY; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_BAL_ENV_WITH_FUNC_NAME; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_DECIMAL; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INIT_RECEIVE_FIELD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INT_TO_STRING; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.INT_VALUE_OF_METHOD; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.IS_CONCURRENT; @@ -186,6 +188,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOAD_JOBJECT_TYPE; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.LOCK; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MAP_PUT; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MULTIPLE_RECEIVE_CALL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PANIC_IF_IN_LOCK; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_OBJECT_RETURN_OBJECT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RETURN_OBJECT; @@ -391,6 +394,10 @@ public void genTerminator(BIRTerminator terminator, String moduleClassName, BIRN this.genWorkerAlternateReceiveIns((BIRTerminator.WorkerAlternateReceive) terminator, localVarOffset, invocationVarIndex); return; + case WK_MULTIPLE_RECEIVE: + this.genWorkerMultipleReceiveIns((BIRTerminator.WorkerMultipleReceive) terminator, localVarOffset, + invocationVarIndex); + return; case FLUSH: this.genFlushIns((BIRTerminator.Flush) terminator, localVarOffset, invocationVarIndex); return; @@ -1232,6 +1239,45 @@ private void genWorkerAlternateReceiveIns(BIRTerminator.WorkerAlternateReceive i generateReceiveResultStore(ins.lhsOp); } + + private void genWorkerMultipleReceiveIns(BIRTerminator.WorkerMultipleReceive ins, int localVarOffset, + int invocationVarIndex) { + BIRNode.BIRVariableDcl listVar = new BIRNode.BIRVariableDcl(symbolTable.anyType, new Name("channels"), + VarScope.FUNCTION, VarKind.LOCAL); + int channelIndex = this.getJVMIndexOfVarRef(listVar); + int channelSize = ins.receiveFields.size(); + this.mv.visitIntInsn(BIPUSH, channelSize); + this.mv.visitTypeInsn(ANEWARRAY, RECEIVE_FIELD); + int i = 0; + while (i < channelSize) { + BIRTerminator.WorkerMultipleReceive.ReceiveField receiveField = ins.receiveFields.get(i); + this.mv.visitInsn(DUP); + this.mv.visitIntInsn(BIPUSH, i); + this.mv.visitTypeInsn(NEW, RECEIVE_FIELD); + this.mv.visitInsn(DUP); + this.mv.visitLdcInsn(receiveField.key); + this.mv.visitVarInsn(ILOAD, invocationVarIndex); + this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, + new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, + HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), + receiveField.workerReceive + START_OF_HEADING_WITH_SEMICOLON); + this.mv.visitMethodInsn(INVOKESPECIAL, RECEIVE_FIELD, JVM_INIT_METHOD, INIT_RECEIVE_FIELD, false); + this.mv.visitInsn(AASTORE); + i += 1; + } + this.mv.visitVarInsn(ASTORE, channelIndex); + this.mv.visitVarInsn(ALOAD, localVarOffset); + if (!ins.isSameStrand) { + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); + } + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); + this.mv.visitVarInsn(ALOAD, localVarOffset); + this.mv.visitVarInsn(ALOAD, channelIndex); + jvmTypeGen.loadType(this.mv, ins.targetType); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "takeMultipleChannelData", MULTIPLE_RECEIVE_CALL, false); + generateReceiveResultStore(ins.lhsOp); + } + private void genWorkerReceiveIns(BIRTerminator.WorkerReceive ins, int localVarOffset, int invocationVarIndex) { this.mv.visitVarInsn(ALOAD, localVarOffset); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java index d85d2c2b39f3..47d4fe45821a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java @@ -20,6 +20,7 @@ import io.ballerina.tools.diagnostics.Location; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; +import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.util.Name; import java.util.ArrayList; @@ -727,6 +728,72 @@ public BIRBasicBlock[] getNextBasicBlocks() { } } + /** + * A worker receive instruction for multiple receive. + *

+ * e.g., WRK_RECEIVE {w1 , w2}; + * + * @since 2201.9.0 + */ + public static class WorkerMultipleReceive extends BIRTerminator { + public boolean isSameStrand; + public BType targetType; + public List receiveFields; + + public WorkerMultipleReceive(Location pos, List receiveFields, BIROperand lhsOp, + boolean isSameStrand, BIRBasicBlock thenBB) { + super(pos, InstructionKind.WK_MULTIPLE_RECEIVE); + this.thenBB = thenBB; + this.isSameStrand = isSameStrand; + this.lhsOp = lhsOp; + this.targetType = lhsOp.variableDcl.type; + this.receiveFields = receiveFields; + } + + public WorkerMultipleReceive(Location pos, List receiveFields, BIROperand lhsOp, + boolean isSameStrand, BIRBasicBlock thenBB, BirScope scope) { + this(pos, receiveFields, lhsOp, isSameStrand, thenBB); + this.scope = scope; + } + + @Override + public void accept(BIRVisitor visitor) { + visitor.visit(this); + } + + @Override + public BIROperand[] getRhsOperands() { + return new BIROperand[0]; + } + + @Override + public void setRhsOperands(BIROperand[] operands) { + // do nothing + } + + @Override + public BIRBasicBlock[] getNextBasicBlocks() { + return new BIRBasicBlock[]{thenBB}; + } + + /** + * This static inner class represents key-value pair in a multiple worker. + * + * @since 2201.9.0 + */ + public static class ReceiveField { + public String key; + public String workerReceive; + + public ReceiveField(String key, String workerReceive) { + this.key = key; + this.workerReceive = workerReceive; + } + } + } + + + /** * A worker send instruction. *

diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java index a2c0630ea0f2..3cc44e1d2cb9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRVisitor.java @@ -146,6 +146,9 @@ public void visit(BIRTerminator.WorkerAlternateReceive altReceive) { throw new AssertionError(); } + public void visit(BIRTerminator.WorkerMultipleReceive multipleReceive) { + throw new AssertionError(); + } // Non-terminating instructions diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java index e7fec1928f30..23615b1d931d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/InstructionKind.java @@ -39,6 +39,7 @@ public enum InstructionKind { UNLOCK((byte) 13), WAIT_ALL((byte) 14), WK_ALT_RECEIVE((byte) 15), + WK_MULTIPLE_RECEIVE((byte) 16), // Non-terminating instructions MOVE((byte) 20), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java index f8e3ea7d4781..66871a8ae3c1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIRLockOptimizer.java @@ -253,6 +253,11 @@ public void visit(BIRTerminator.WorkerAlternateReceive workerAlternateReceive) { // Do nothing } + @Override + public void visit(BIRTerminator.WorkerMultipleReceive workerMultipleReceive) { + // Do nothing + } + @Override public void visit(BIRNode.BIRBasicBlock birBasicBlock) { BIRTerminator terminator = birBasicBlock.terminator; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java index 9123ec8d82de..f4c5a177be15 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/optimizer/BIROptimizer.java @@ -473,6 +473,11 @@ public void visit(BIRTerminator.WorkerAlternateReceive workerReceive) { this.optimizeNode(workerReceive.lhsOp, this.env); } + @Override + public void visit(BIRTerminator.WorkerMultipleReceive workerReceive) { + this.optimizeNode(workerReceive.lhsOp, this.env); + } + // Non-terminating instructions @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java index 1d56eef465df..00c3da615c0a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java @@ -241,6 +241,19 @@ public void visit(BIRTerminator.WorkerAlternateReceive entry) { addCpAndWriteString(entry.thenBB.id.value); } + @Override + public void visit(BIRTerminator.WorkerMultipleReceive entry) { + entry.receiveFields.forEach(key -> { + buf.writeInt(addStringCPEntry(key.key)); + buf.writeInt(addStringCPEntry(key.workerReceive)); + }); + writeType(entry.targetType); + entry.lhsOp.accept(this); + buf.writeBoolean(entry.isSameStrand); + addCpAndWriteString(entry.thenBB.id.value); + } + + @Override public void visit(BIRTerminator.WaitAll waitAll) { waitAll.lhsOp.accept(this); buf.writeInt(waitAll.keys.size()); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java index 6cc8064a6e74..4533437a9875 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/NodeCloner.java @@ -1055,7 +1055,9 @@ public void visit(BLangMultipleWorkerReceive source) { BLangMultipleWorkerReceive.BLangReceiveField clonedRvField = new BLangMultipleWorkerReceive.BLangReceiveField(); clonedRvField.setKey(clone(rvField.getKey())); - clonedRvField.setWorkerReceive(clone(rvField.getWorkerReceive())); + BLangWorkerReceive workerReceiveClone = clone(rvField.getWorkerReceive()); + workerReceiveClone.parent = clone; + clonedRvField.setWorkerReceive(workerReceiveClone); cloneFields.add(clonedRvField); } diff --git a/docs/bir-spec/src/main/resources/kaitai/bir.ksy b/docs/bir-spec/src/main/resources/kaitai/bir.ksy index fa1a7fba9f8f..12aacd758075 100644 --- a/docs/bir-spec/src/main/resources/kaitai/bir.ksy +++ b/docs/bir-spec/src/main/resources/kaitai/bir.ksy @@ -1214,6 +1214,8 @@ types: 'instruction_kind_enum::instruction_kind_new_re_flag_expr': instruction_new_re_flag_expr 'instruction_kind_enum::instruction_kind_new_re_flag_on_off': instruction_new_re_flag_on_off 'instruction_kind_enum::instruction_kind_new_re_quantifier': instruction_new_re_quantifier + 'instruction_kind_enum::instruction_kind_wk_alt_receive': instruction_wk_alt_receive + 'instruction_kind_enum::instruction_kind_wk_mul_receive': instruction_wk_mul_receive enums: instruction_kind_enum: 1: instruction_kind_goto @@ -1306,6 +1308,8 @@ types: 99: instruction_kind_new_re_flag_expr 100: instruction_kind_new_re_flag_on_off 101: instruction_kind_new_re_quantifier + 102: instruction_kind_wk_alt_receive + 103: instruction_kind_wk_mul_receive 128: instruction_kind_platform instruction_const_load: seq: @@ -1502,6 +1506,36 @@ types: type: u1 - id: then_bb_id_name_cp_index type: s4 + instruction_wk_alt_receive: + seq: + - id: channel_name_count + type: s4 + - id: channel_name_cp_index + type: s4 + repeat: expr + repeat-expr: channel_name_count + - id: lhs_operand + type: operand + - id: is_same_strand + type: u1 + - id: then_bb_id_name_cp_index + type: s4 + instruction_wk_mul_receive: + seq: + - id: channel_field_count + type: s4 + - id: channel_field_cp_index + type: receive_field + repeat: expr + repeat-expr: channel_field_count + - id: type_cp_index + type: s4 + - id: lhs_operand + type: operand + - id: is_same_strand + type: u1 + - id: then_bb_id_name_cp_index + type: s4 instruction_wk_send: seq: - id: channel_name_cp_index @@ -1905,6 +1939,12 @@ types: - id: variable type: variable if: ignored_variable == 0 + receive_field: + seq: + - id: field_name + type: s4 + - id: channel_name + type: s4 variable: seq: - id: kind From b3ffe0283d69e4ee5f547f622eb7c6a7881adf4e Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 5 Jan 2024 14:50:43 +0530 Subject: [PATCH 55/97] Support NoMessage error return --- .../scheduling/WorkerDataChannel.java | 2 +- .../worker/WorkerConditionalSendTest.java | 8 +- .../workers/workers_conditional_send.bal | 79 ++++++++++++------- 3 files changed, 56 insertions(+), 33 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index e3437f767f20..a3ac6484860d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -186,7 +186,7 @@ public Object tryTakeData(Strand strand, boolean isMultiple) throws Throwable { try { acquireChannelLock(); if (isClosed()) { - throw ErrorUtils.createNoMessageError(chnlName); + return ErrorUtils.createNoMessageError(chnlName); } WorkerResult result = this.channel.peek(); if (result != null) { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 94311a14624f..2d2279c4ed7e 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -21,6 +21,7 @@ import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; @@ -36,10 +37,10 @@ public class WorkerConditionalSendTest { @BeforeClass public void setup() { this.result = BCompileUtil.compile("test-src/workers/workers_conditional_send.bal"); -// Assert.assertEquals(result.getErrorCount(), 0); // TODO: Fix for NoMessageError + Assert.assertEquals(result.getErrorCount(), 0); } - @Test(dataProvider = "functionProvider", enabled = false) + @Test(dataProvider = "functionProvider") public void workerConditionalSendTest(String funcName) { BRunUtil.invoke(result, funcName, new Object[0]); } @@ -63,7 +64,8 @@ public static String[] functionProvider() { "sameWorkerSendMultiplePathError4", "multipleReceiveConditional", "multipleReceiveWithNonConditionalSend", - "testNonTopLevelSend" + "testNonTopLevelSend", + "testSendWithEarlyReturnError" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index dec4ec02e7cf..f0b2d6d827fc 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -15,6 +15,7 @@ // under the License. import ballerina/test; +import ballerina/lang.'error as errorLib; function workerConditionalSendTest() { boolean foo = true; @@ -27,14 +28,14 @@ function workerConditionalSendTest() { } } - worker w2 returns int { - int a = <- w1; + worker w2 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError a = <- w1; return a; } worker w3 { - int b = <- w1; - int c = <- w4; + int|errorLib:NoMessageError b = <- w1; + int|errorLib:NoMessageError c = <- w4; } worker w4 { @@ -45,12 +46,12 @@ function workerConditionalSendTest() { } } - worker w5 returns int { - int d = <- w4; + worker w5 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError d = <- w4; return d; } - map results = wait {a: w2, b: w5}; + map results = wait {a: w2, b: w5}; test:assertEquals(results["a"], 1, "Invalid int result"); test:assertEquals(results["b"], 2, "Invalid int result"); } @@ -67,8 +68,8 @@ function sameWorkerSendTest() { } worker w2 { - int a = <- w1; - int|error b = trap <- w1; + int|errorLib:NoMessageError a = <- w1; + int|errorLib:NoMessageError b = <- w1; test:assertEquals(a, 10, "Invalid int result"); test:assertTrue(b is error); error e = b; @@ -91,7 +92,7 @@ function sameWorkerSendEitherOnePath() { } worker w2 { - int a = <- w1 | w1; + int|errorLib:NoMessageError a = <- w1 | w1; test:assertEquals(a, 10, "Invalid int result"); } @@ -198,7 +199,7 @@ function sameWorkerSendSenderPanic() { } worker w2 { - int a = <- w1 | w1; + int|errorLib:NoMessageError a = <- w1 | w1; } error? unionResult = trap wait w1; @@ -218,12 +219,12 @@ function sameWorkerSendReceiverPanic() { } } - worker w2 returns int { + worker w2 returns int|errorLib:NoMessageError { int value = 10; if value == 10 { panic error("Error in worker 2"); } - int a = <- w1 | w1; + int|errorLib:NoMessageError a = <- w1 | w1; return a; } @@ -243,12 +244,12 @@ function sameWorkerSendMultiplePath1() { 2 -> w2; } - worker w2 returns int { - int a = <- w1 | w1; + worker w2 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError a = <- w1 | w1; return a; } - int intResult = wait w2; + int|errorLib:NoMessageError intResult = wait w2; test:assertEquals(intResult, 1, "Invalid int result"); } @@ -262,16 +263,15 @@ function sameWorkerSendMultiplePath2() { 2 -> w2; } - worker w2 returns int { - int a = <- w1 | w1; + worker w2 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError a = <- w1 | w1; return a; } - int intResult = wait w2; + int|errorLib:NoMessageError intResult = wait w2; test:assertEquals(intResult, 2, "Invalid int result"); } -// TODO: Enable these tests when it is compiling function sameWorkerSendMultiplePathError1() { boolean foo = false; @@ -391,13 +391,13 @@ function multipleReceiveConditional() { return y; } - worker w2 returns int { - int y = <- w1; + worker w2 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError y = <- w1; return y; } - worker w3 returns int|error { - int|error y = trap <- w1; + worker w3 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError y = <- w1; 3 -> w1; return y; } @@ -414,8 +414,8 @@ function multipleReceiveConditional() { function multipleReceiveWithNonConditionalSend() { boolean foo = true; worker w3 { - int x = <- w1; - int|error y = trap <- w1; + int|errorLib:NoMessageError x = <- w1; + int|errorLib:NoMessageError y = <- w1; int z = <- w1; test:assertEquals(x, 2, "Invalid int result"); test:assertTrue(y is error, "Invalid error result"); @@ -446,13 +446,34 @@ function testNonTopLevelSend() { return false; } - worker w2 returns int { - int j = 25; + worker w2 returns int|errorLib:NoMessageError { + int|errorLib:NoMessageError j = 25; j = <- w1; return j; } - map mapResult = wait {a: w1, b: w2}; + map mapResult = wait {a: w1, b: w2}; + test:assertEquals(mapResult["a"], false, "Invalid boolean result"); + test:assertEquals(mapResult["b"], 2, "Invalid int result"); +} + +function testSendWithEarlyReturnError() { + worker w1 returns boolean|error { + int i = 2; + if (0 > 1) { + return error("Error in worker 1"); + } + i -> w2; + return false; + } + + worker w2 returns int|error { + int|error j = 25; + j = <- w1; + return j; + } + + map mapResult = wait {a: w1, b: w2}; test:assertEquals(mapResult["a"], false, "Invalid boolean result"); test:assertEquals(mapResult["b"], 2, "Invalid int result"); } From d9b6da73751a6dcbd58e787b7a3c3e2ca2095a3e Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 5 Jan 2024 14:51:27 +0530 Subject: [PATCH 56/97] Improve tests for multiple receive action --- .../semantics/analyzer/TypeChecker.java | 1 + .../worker/WorkerMultipleReceiveTest.java | 62 ++++++++++ .../ballerinalang/test/worker/WorkerTest.java | 6 +- .../workers/multiple-receive-action.bal | 10 +- .../workers/workers_multiple_receive.bal | 113 ++++++++++++++++++ 5 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 6b101e6ae4c5..49b38ac3c895 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2884,6 +2884,7 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); } + data.resultType = compatibleType; return; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java new file mode 100644 index 000000000000..9739b8814449 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * + * 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 + * + * 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.worker; + +import org.ballerinalang.test.BCompileUtil; +import org.ballerinalang.test.BRunUtil; +import org.ballerinalang.test.CompileResult; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/** + * worker alternative receive related tests. + */ +public class WorkerMultipleReceiveTest { + + private CompileResult result; + + @BeforeClass + public void setup() { + this.result = BCompileUtil.compile("test-src/workers/workers_multiple_receive.bal"); + Assert.assertEquals(result.getErrorCount(), 0); + } + + @Test(dataProvider = "functionProvider") + public void workerAlternateReceiveTest(String funcName) { + BRunUtil.invoke(result, funcName, new Object[0]); + } + + @DataProvider + public static String[] functionProvider() { + return new String[] { + "workerMultipleReceiveTest1", + "workerMultipleReceiveTest2", + "workerMultipleReceiveTest3", + "workerMultipleReceiveWithUserDefinedRecord" + }; + } + + @AfterClass + public void tearDown() { + result = null; + } +} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java index 0699890879ab..5f9b9fa61170 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java @@ -342,12 +342,12 @@ public void testWorkerInsideLock() { BAssertUtil.validateError(result, index++, "cannot use a named worker inside a lock statement", 42, 20); } - @Test (enabled = false) + @Test public void testMultipleReceiveAction() { // Multiple receive action is not yet supported. This is to test the error message. CompileResult result = BCompileUtil.compile("test-src/workers/multiple-receive-action.bal"); - Assert.assertEquals(result.getErrorCount(), 1); - BAssertUtil.validateError(result, 0, "multiple receive action not yet supported", 23, 25); + Assert.assertEquals(result.getErrorCount(), 0); + BRunUtil.invoke(result, "testMultipleReceiveAction"); } @AfterClass diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-action.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-action.bal index 2b9d30d2662c..2420a968742b 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-action.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-action.bal @@ -14,14 +14,18 @@ // specific language governing permissions and limitations // under the License. -public function main() { +import ballerina/test; + +public function testMultipleReceiveAction() { worker w1 { 100 -> w2; } - worker w2 { + worker w2 returns map { map m = <- { w1 }; + return m; } - wait w2; + map m = wait w2; + test:assertEquals(m, { w1: 100 }, "Invalid map returned"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal new file mode 100644 index 000000000000..cfae505e8cb9 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -0,0 +1,113 @@ +// Copyright (c) 2023 WSO2 LLC. +// +// 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 +// +// 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/test; +import ballerina/lang.runtime; + +function workerMultipleReceiveTest1() { + worker w1 { + 2 -> w2; + } + + worker w2 returns map { + map result = <- { w1, w3}; + return result; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + map results = wait w2; + test:assertEquals(results["w1"], 2, "Invalid int result"); + test:assertEquals(results["w3"], 3, "Invalid int result"); +} + +function workerMultipleReceiveTest2() { + worker w1 { + 2 -> w2; + } + + worker w2 returns map { + map result = <- { a:w1, b:w3}; + return result; + } + + worker w3 { + runtime:sleep(2); + 3 -> w2; + } + + map results = wait w2; + test:assertEquals(results["a"], 2, "Invalid int result"); + test:assertEquals(results["b"], 3, "Invalid int result"); +} + +function workerMultipleReceiveTest3() { + worker w1 { + 100 -> w2; + 20 -> w2; + } + + worker w2 returns map { + map result = {} ; + map m = <- { a:w1, b:w3 }; + result["first"] = m; + m = <- { aa:w1, bb:w3 }; + result["second"] = m; + return result; + } + + worker w3 { + 6 -> w2; + 45 -> w2; + } + + map mapResult = wait w2; + test:assertEquals(mapResult["first"], { "a":100, "b":6}, "Invalid map result"); + test:assertEquals(mapResult["second"], { "aa":20, "bb":45}, "Invalid map result"); +} + +type MyRec record {| + int firstValue; + int secondValue; +|}; + +function workerMultipleReceiveWithUserDefinedRecord() { + worker w1 { + 100 -> w2; + 20 -> w2; + } + + worker w2 returns map { + map result = {} ; + MyRec m = <- { firstValue:w1, secondValue:w3 }; + result["first"] = m; + m = <- { firstValue:w1, secondValue:w3 }; + result["second"] = m; + return result; + } + + worker w3 { + 6 -> w2; + 45 -> w2; + } + + map mapResult = wait w2; + test:assertEquals(mapResult["first"], {"firstValue":100,"secondValue":6}, "Invalid map result"); + test:assertEquals(mapResult["second"], {"firstValue":20,"secondValue":45}, "Invalid map result"); +} \ No newline at end of file From b048609286002517a26d61c87fa07b62e4bb8bef Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 5 Jan 2024 15:02:16 +0530 Subject: [PATCH 57/97] Refactor minor errors --- .../main/java/io/ballerina/runtime/internal/ErrorUtils.java | 4 +--- .../resources/test-src/workers/workers_multiple_receive.bal | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java index 568bb1177ea6..8073dccbef42 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java @@ -190,9 +190,7 @@ public static BError createInvalidFractionDigitsError() { public static BError createNoMessageError(String chnlName) { String[] splitWorkers = chnlName.split(":")[0].split("->"); - String sender = splitWorkers[0]; - String receiver = splitWorkers[1]; return createError(ErrorReasons.NO_MESSAGE_ERROR, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, - StringUtils.fromString(sender), StringUtils.fromString(receiver))); + StringUtils.fromString(splitWorkers[0]), StringUtils.fromString(splitWorkers[1]))); } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal index cfae505e8cb9..b677709c57ca 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -110,4 +110,4 @@ function workerMultipleReceiveWithUserDefinedRecord() { map mapResult = wait w2; test:assertEquals(mapResult["first"], {"firstValue":100,"secondValue":6}, "Invalid map result"); test:assertEquals(mapResult["second"], {"firstValue":20,"secondValue":45}, "Invalid map result"); -} \ No newline at end of file +} From 5b0a8d7dd2feb491693b841d974d33aaadd76f1f Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Sun, 7 Jan 2024 17:10:27 +0530 Subject: [PATCH 58/97] Fix regression issue introduced with commit c786533 --- .../ballerinalang/compiler/semantics/analyzer/TypeChecker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 6b101e6ae4c5..49b38ac3c895 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -2884,6 +2884,7 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive, AnalyzerData checkExpr(receiveFiled.getWorkerReceive(), receiveFieldExpType, data); } + data.resultType = compatibleType; return; } From 29ba176f9a6f78321c65d757a12fee90f9904b0d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Sun, 7 Jan 2024 17:12:52 +0530 Subject: [PATCH 59/97] Fix semantic API visitors for alternate and multiple receive AST nodes --- .../compiler/api/impl/NodeFinder.java | 20 ++++++++++++++++++ .../compiler/api/impl/ReferenceFinder.java | 17 +++++++++++++++ .../compiler/api/impl/SymbolFinder.java | 21 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java index 988e496b3467..629a91b7b249 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java @@ -74,6 +74,7 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAnnotAccessExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; @@ -95,6 +96,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr; @@ -584,6 +586,24 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { setEnclosingNode(asyncSendExpr, asyncSendExpr.workerIdentifier.pos); } + @Override + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + for (BLangWorkerReceive workerReceive : alternateWorkerReceive.getWorkerReceives()) { + if (setEnclosingNode(alternateWorkerReceive, workerReceive.workerIdentifier.pos)) { + return; + } + } + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField receiveField : multipleWorkerReceive.getReceiveFields()) { + if (setEnclosingNode(multipleWorkerReceive, receiveField.getWorkerReceive().workerIdentifier.pos)) { + return; + } + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { setEnclosingNode(workerReceiveNode, workerReceiveNode.workerIdentifier.pos); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java index bf3792f0e713..51d90433c385 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java @@ -81,6 +81,7 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAnnotAccessExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; @@ -105,6 +106,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangListConstructorExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -768,6 +770,21 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { addIfSameSymbol(asyncSendExpr.workerSymbol, asyncSendExpr.workerIdentifier.pos); } + @Override + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + for (BLangWorkerReceive workerReceive : alternateWorkerReceive.getWorkerReceives()) { + addIfSameSymbol(workerReceive.workerSymbol, workerReceive.workerIdentifier.pos); + } + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField receiveField : multipleWorkerReceive.getReceiveFields()) { + BLangWorkerReceive workerReceive = receiveField.getWorkerReceive(); + addIfSameSymbol(workerReceive.workerSymbol, workerReceive.workerIdentifier.pos); + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { addIfSameSymbol(workerReceiveNode.workerSymbol, workerReceiveNode.workerIdentifier.pos); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java index 5f2748734b76..9b9ce5a2741a 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java @@ -84,6 +84,7 @@ import org.wso2.ballerinalang.compiler.tree.clauses.BLangOrderKey; import org.wso2.ballerinalang.compiler.tree.clauses.BLangSelectClause; import org.wso2.ballerinalang.compiler.tree.clauses.BLangWhereClause; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangAlternateWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangAnnotAccessExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangArrowFunction; import org.wso2.ballerinalang.compiler.tree.expressions.BLangBinaryExpr; @@ -114,6 +115,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation; import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangMultipleWorkerReceive; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression; import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral; import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction; @@ -822,6 +824,25 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr) { lookupNode(asyncSendExpr.expr); } + @Override + public void visit(BLangAlternateWorkerReceive alternateWorkerReceive) { + for (BLangWorkerReceive workerReceive : alternateWorkerReceive.getWorkerReceives()) { + if (setEnclosingNode(workerReceive.workerSymbol, workerReceive.workerIdentifier.pos)) { + return; + } + } + } + + @Override + public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { + for (BLangMultipleWorkerReceive.BLangReceiveField receiveField : multipleWorkerReceive.getReceiveFields()) { + BLangWorkerReceive workerReceive = receiveField.getWorkerReceive(); + if (setEnclosingNode(workerReceive.workerSymbol, workerReceive.workerIdentifier.pos)) { + return; + } + } + } + @Override public void visit(BLangWorkerReceive workerReceiveNode) { setEnclosingNode(workerReceiveNode.workerSymbol, workerReceiveNode.workerIdentifier.pos); From 967c703c165ae722c446b96a6d35eab8a68b7070 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 8 Jan 2024 11:03:24 +0530 Subject: [PATCH 60/97] Refactor receive methods --- .../internal/scheduling/WDChannels.java | 35 +++++++++++-------- .../bir/codegen/JvmTerminatorGen.java | 5 +-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index d3992f51e014..f15426b5b046 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -56,7 +56,7 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { return channel; } - public Object takeMultipleChannelData(Strand strand, ReceiveField[] receiveFields, Type targetType) + public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveFields, Type targetType) throws Throwable { if (strand.mapResult == null) { strand.mapResult = ValueCreator.createMapValue(targetType); @@ -65,24 +65,31 @@ public Object takeMultipleChannelData(Strand strand, ReceiveField[] receiveField WorkerDataChannel channel = getWorkerDataChannel(field.getChannelName()); if (!channel.isClosed()) { Object result = channel.tryTakeData(strand, true); - if (result != null) { - if (result instanceof ErrorValue errorValue) { - errors.add(errorValue); - channel.close(); - } else { - strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); - channel.close(); - } - ++strand.channelCount; - } else { - strand.setState(BLOCK_AND_YIELD); - } + checkAndPopulateResult(strand, field, result, channel); } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { errors.add((ErrorValue) ErrorUtils.createNoMessageError(field.getChannelName())); } } } + return clearResultCache(strand, receiveFields); + } + + private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { + if (result != null) { + if (result instanceof ErrorValue errorValue) { + errors.add(errorValue); + } else { + strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); + } + channel.close(); + ++strand.channelCount; + } else { + strand.setState(BLOCK_AND_YIELD); + } + } + + private Object clearResultCache(Strand strand, ReceiveField[] receiveFields) { if (strand.channelCount == receiveFields.length) { BMap map = strand.mapResult; strand.mapResult = null; @@ -92,7 +99,7 @@ public Object takeMultipleChannelData(Strand strand, ReceiveField[] receiveField return null; } - public Object tryTakeData(Strand strand, String[] channels) throws Throwable { + public Object receiveDataAlternateChannels(Strand strand, String[] channels) throws Throwable { Object result = null; boolean allChannelsClosed = true; for (String channelName : channels) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 4bf2484b72ca..e2b6e689d7a1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -1234,7 +1234,7 @@ private void genWorkerAlternateReceiveIns(BIRTerminator.WorkerAlternateReceive i this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); this.mv.visitVarInsn(ALOAD, localVarOffset); this.mv.visitVarInsn(ALOAD, channelIndex); - this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "tryTakeData", ALT_RECEIVE_CALL, false); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "receiveDataAlternateChannels", ALT_RECEIVE_CALL, false); generateReceiveResultStore(ins.lhsOp); } @@ -1274,7 +1274,8 @@ private void genWorkerMultipleReceiveIns(BIRTerminator.WorkerMultipleReceive ins this.mv.visitVarInsn(ALOAD, localVarOffset); this.mv.visitVarInsn(ALOAD, channelIndex); jvmTypeGen.loadType(this.mv, ins.targetType); - this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "takeMultipleChannelData", MULTIPLE_RECEIVE_CALL, false); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "receiveDataMultipleChannels", + MULTIPLE_RECEIVE_CALL, false); generateReceiveResultStore(ins.lhsOp); } From a7fb64fbdef71258b7fd9a4635a7e61034a05577 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 8 Jan 2024 13:26:16 +0530 Subject: [PATCH 61/97] Fix nil return bug --- .../runtime/internal/scheduling/WDChannels.java | 13 +++++++++++-- .../internal/scheduling/WorkerDataChannel.java | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index f15426b5b046..5a3a5fea496b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -77,6 +77,7 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { if (result != null) { + result = getResultValue(result); if (result instanceof ErrorValue errorValue) { errors.add(errorValue); } else { @@ -120,7 +121,8 @@ public Object receiveDataAlternateChannels(Strand strand, String[] channels) thr } private Object handleNonNullResult(String[] channels, Object result, WorkerDataChannel channel) { - if (result instanceof ErrorValue errorValue) { + Object resultValue = getResultValue(result); + if (resultValue instanceof ErrorValue errorValue) { errors.add(errorValue); channel.close(); result = null; @@ -130,6 +132,13 @@ private Object handleNonNullResult(String[] channels, Object result, WorkerDataC return result; } + private static Object getResultValue(Object result) { + if (result instanceof WorkerDataChannel.WorkerResult workerResult) { + return workerResult.value; + } + return result; + } + private Object processResulAndError(Strand strand, String[] channels, Object result, boolean allChannelsClosed) { if (result == null) { if (errors.size() == channels.length) { @@ -138,7 +147,7 @@ private Object processResulAndError(Strand strand, String[] channels, Object res strand.setState(BLOCK_AND_YIELD); } } - return result; + return getResultValue(result); } private void closeChannels(String[] channels) { diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index a3ac6484860d..1a6a9a39250e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -213,7 +213,7 @@ public Object tryTakeData(Strand strand, boolean isMultiple) throws Throwable { this.flushSender.waitingStrand.flushDetail.flushLock.unlock(); this.flushSender = null; } - return result.value; + return isMultiple ? result : result.value; } else if (this.panic != null && this.senderCounter == this.receiverCounter + 1) { this.receiverCounter++; throw this.panic; From 92d0475ea2a98283ee4ffd6cb57d794e9d1fb857 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 11 Jan 2024 13:55:03 +0530 Subject: [PATCH 62/97] Add negative tests --- .../internal/scheduling/WDChannels.java | 6 +- .../worker/WorkerMultipleReceiveTest.java | 6 +- .../workers/workers_multiple_receive.bal | 109 ++++++++++++++++++ 3 files changed, 115 insertions(+), 6 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 5a3a5fea496b..513b0c6c8170 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -78,11 +78,7 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { if (result != null) { result = getResultValue(result); - if (result instanceof ErrorValue errorValue) { - errors.add(errorValue); - } else { - strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); - } + strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); channel.close(); ++strand.channelCount; } else { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java index 9739b8814449..f1665572be8c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java @@ -51,7 +51,11 @@ public static String[] functionProvider() { "workerMultipleReceiveTest1", "workerMultipleReceiveTest2", "workerMultipleReceiveTest3", - "workerMultipleReceiveWithUserDefinedRecord" + "workerMultipleReceiveWithUserDefinedRecord", + "workerMultipleReceiveWithErrorReturn", + "workerMultipleReceiveWithAllErrorReturn", + "workerMultipleReceiveWithPanic", + "workerMultipleReceiveWithAllPanic" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal index b677709c57ca..3f4ffba36c13 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -111,3 +111,112 @@ function workerMultipleReceiveWithUserDefinedRecord() { test:assertEquals(mapResult["first"], {"firstValue":100,"secondValue":6}, "Invalid map result"); test:assertEquals(mapResult["second"], {"firstValue":20,"secondValue":45}, "Invalid map result"); } + +function workerMultipleReceiveWithErrorReturn() { + worker w1 returns error?{ + int v = 10; + if v == 10 { + return error("Error in worker w1"); + } + 100 -> w2; + } + + worker w2 returns map { + map m = <- { firstValue:w1, secondValue:w3 }; + return m; + } + + worker w3 { + 6 -> w2; + } + + map mapResult = wait w2; + test:assertTrue(mapResult["firstValue"] is error, "Invalid map result"); + error e = mapResult["firstValue"]; + test:assertEquals(e.message(), "Error in worker w1", "Invalid error message"); + test:assertEquals(mapResult["secondValue"], 6, "Invalid int result"); +} + +function workerMultipleReceiveWithAllErrorReturn() { + worker w1 returns error?{ + int v = 10; + if v == 10 { + return error("Error in worker w1"); + } + 100 -> w2; + } + + worker w2 returns map { + map m = <- { firstValue:w1, secondValue:w3 }; + return m; + } + + worker w3 returns error?{ + int v = 10; + if v == 10 { + return error("Error in worker w3"); + } + 6 -> w2; + } + + map mapResult = wait w2; + test:assertTrue(mapResult["firstValue"] is error, "Invalid map result"); + error e = mapResult["firstValue"]; + test:assertEquals(e.message(), "Error in worker w1", "Invalid error message"); + test:assertTrue(mapResult["secondValue"] is error, "Invalid map result"); + e = mapResult["secondValue"]; + test:assertEquals(e.message(), "Error in worker w3", "Invalid error message"); +} + +function workerMultipleReceiveWithPanic() { + worker w1 { + int v = 10; + if v == 10 { + panic error("Error in worker w1"); + } + 100 -> w2; + } + + worker w2 returns map { + map m = <- { firstValue:w1, secondValue:w3 }; + return m; + } + + worker w3 { + 6 -> w2; + } + + map|error result = trap wait w2; + test:assertTrue(result is error, "Invalid map result"); + error e = result; + test:assertEquals(e.message(), "Error in worker w1", "Invalid error message"); +} + +function workerMultipleReceiveWithAllPanic() { + worker w1 { + runtime:sleep(2); + int v = 10; + if v == 10 { + panic error("Error in worker w1"); + } + 100 -> w2; + } + + worker w2 returns map { + map m = <- { firstValue:w1, secondValue:w3 }; + return m; + } + + worker w3 { + int v = 10; + if v == 10 { + panic error("Error in worker w3"); + } + 6 -> w2; + } + + map|error result = trap wait w2; + test:assertTrue(result is error, "Invalid map result"); + error e = result; + test:assertEquals(e.message(), "Error in worker w3", "Invalid error message"); +} From c32670fd498ca2c7dc71aefece0cb70668b0ca93 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 11 Jan 2024 14:01:35 +0530 Subject: [PATCH 63/97] Address review suggestions --- .../runtime/internal/scheduling/ReceiveField.java | 12 ++---------- .../runtime/internal/scheduling/Strand.java | 2 +- .../runtime/internal/scheduling/WDChannels.java | 14 +++++++------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java index 94f3d7ca85eb..b09c0316ecff 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java @@ -27,20 +27,12 @@ */ public class ReceiveField { - private final String fieldName; - private final String channelName; + public final String fieldName; + public final String channelName; public ReceiveField(String fieldName, String channelName) { this.fieldName = fieldName; this.channelName = channelName; } - public String getFieldName() { - return fieldName; - } - - public String getChannelName() { - return channelName; - } - } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java index d87ab6ecd33e..ac7a4269eab3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/Strand.java @@ -91,7 +91,7 @@ public class Strand { public Stack trxContexts; private State state; private final ReentrantLock strandLock; - public BMap mapResult = null; + public BMap workerReceiveMap = null; public int channelCount = 0; public Strand(String name, StrandMetadata metadata, Scheduler scheduler, Strand parent, diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 513b0c6c8170..03696971da8f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -58,17 +58,17 @@ public synchronized WorkerDataChannel getWorkerDataChannel(String name) { public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveFields, Type targetType) throws Throwable { - if (strand.mapResult == null) { - strand.mapResult = ValueCreator.createMapValue(targetType); + if (strand.workerReceiveMap == null) { + strand.workerReceiveMap = ValueCreator.createMapValue(targetType); } for (ReceiveField field : receiveFields) { - WorkerDataChannel channel = getWorkerDataChannel(field.getChannelName()); + WorkerDataChannel channel = getWorkerDataChannel(field.channelName); if (!channel.isClosed()) { Object result = channel.tryTakeData(strand, true); checkAndPopulateResult(strand, field, result, channel); } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - errors.add((ErrorValue) ErrorUtils.createNoMessageError(field.getChannelName())); + errors.add((ErrorValue) ErrorUtils.createNoMessageError(field.channelName)); } } } @@ -78,7 +78,7 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { if (result != null) { result = getResultValue(result); - strand.mapResult.populateInitialValue(StringUtils.fromString(field.getFieldName()), result); + strand.workerReceiveMap.populateInitialValue(StringUtils.fromString(field.fieldName), result); channel.close(); ++strand.channelCount; } else { @@ -88,8 +88,8 @@ private void checkAndPopulateResult(Strand strand, ReceiveField field, Object re private Object clearResultCache(Strand strand, ReceiveField[] receiveFields) { if (strand.channelCount == receiveFields.length) { - BMap map = strand.mapResult; - strand.mapResult = null; + BMap map = strand.workerReceiveMap; + strand.workerReceiveMap = null; strand.channelCount = 0; return map; } From 6f2389a2b962e758c46e10ba7bfcd01ca9f10308 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Tue, 16 Jan 2024 14:26:08 +0530 Subject: [PATCH 64/97] Fix no message error returning --- .../runtime/internal/ErrorUtils.java | 6 +- .../internal/scheduling/WDChannels.java | 2 +- .../worker/WorkerMultipleReceiveTest.java | 7 +- .../workers/workers_multiple_receive.bal | 92 +++++++++++++++++++ 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java index 8073dccbef42..59fc618655f3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java @@ -30,6 +30,7 @@ import io.ballerina.runtime.internal.values.MapValueImpl; import io.ballerina.runtime.internal.values.MappingInitialValueEntry; +import static io.ballerina.runtime.api.constants.RuntimeConstants.BALLERINA_LANG_ERROR_PKG_ID; import static io.ballerina.runtime.api.constants.RuntimeConstants.FLOAT_LANG_LIB; import static io.ballerina.runtime.api.creators.ErrorCreator.createError; import static io.ballerina.runtime.internal.errors.ErrorCodes.INCOMPATIBLE_CONVERT_OPERATION; @@ -190,7 +191,8 @@ public static BError createInvalidFractionDigitsError() { public static BError createNoMessageError(String chnlName) { String[] splitWorkers = chnlName.split(":")[0].split("->"); - return createError(ErrorReasons.NO_MESSAGE_ERROR, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, - StringUtils.fromString(splitWorkers[0]), StringUtils.fromString(splitWorkers[1]))); + return createError(BALLERINA_LANG_ERROR_PKG_ID, "NoMessageError", ErrorReasons.NO_MESSAGE_ERROR, + null, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, + StringUtils.fromString(splitWorkers[0]), StringUtils.fromString(splitWorkers[1]))); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 03696971da8f..3ed43d6c4938 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -68,7 +68,7 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF checkAndPopulateResult(strand, field, result, channel); } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - errors.add((ErrorValue) ErrorUtils.createNoMessageError(field.channelName)); + checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName), channel); } } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java index f1665572be8c..0ffad6ffe538 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java @@ -41,7 +41,7 @@ public void setup() { } @Test(dataProvider = "functionProvider") - public void workerAlternateReceiveTest(String funcName) { + public void workerMultipleReceiveTest(String funcName) { BRunUtil.invoke(result, funcName, new Object[0]); } @@ -55,7 +55,10 @@ public static String[] functionProvider() { "workerMultipleReceiveWithErrorReturn", "workerMultipleReceiveWithAllErrorReturn", "workerMultipleReceiveWithPanic", - "workerMultipleReceiveWithAllPanic" + "workerMultipleReceiveWithAllPanic", + "workerMultipleReceiveWithErrorReturnRec", + "workerMultipleReceiveWithConditionalSend1", + "workerMultipleReceiveWithConditionalSend2", }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal index 3f4ffba36c13..f443e643deb8 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -16,6 +16,7 @@ import ballerina/test; import ballerina/lang.runtime; +import ballerina/lang.'error as errorLib; function workerMultipleReceiveTest1() { worker w1 { @@ -220,3 +221,94 @@ function workerMultipleReceiveWithAllPanic() { error e = result; test:assertEquals(e.message(), "Error in worker w3", "Invalid error message"); } + +function workerMultipleReceiveWithErrorReturnRec() { + worker w1 returns error?{ + int v = 10; + if v == 10 { + return error("Error in worker w1"); + } + 100 -> w2; + } + + worker w2 returns ErrRec { + ErrRec m = <- { firstValue:w1, secondValue:w3 }; + return m; + } + + worker w3 { + 6 -> w2; + } + + ErrRec mapResult = wait w2; + test:assertTrue(mapResult.firstValue is error, "Invalid map result"); + error e = mapResult.firstValue; + test:assertEquals(e.message(), "Error in worker w1", "Invalid error message"); + test:assertEquals(mapResult.secondValue, 6, "Invalid int result"); +} + +type ErrRec record {| + int|error firstValue; + int secondValue; +|}; + +function workerMultipleReceiveWithConditionalSend1() { + boolean foo = true; + + worker w1 { + if foo { + 1 -> w2; + } else { + 2 -> w3; + } + } + + worker w2 returns map { + map m = <- {w1, w3}; + return m; + } + + worker w3 { + int|errorLib:NoMessageError a = <- w1; + test:assertTrue(a is error, "Invalid result"); + error e = a; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); + 3 -> w2; + } + + map mapResult = wait w2; + test:assertEquals(mapResult["w1"], 1, "Invalid map result"); + test:assertEquals(mapResult["w3"], 3, "Invalid map result"); +} + +function workerMultipleReceiveWithConditionalSend2() { + boolean foo = true; + + worker w1 { + if foo { + 1 -> w3; + } else { + 2 -> w2; + } + } + + worker w2 returns map { + map m = <- {w1, w3}; + return m; + } + + worker w3 { + int|errorLib:NoMessageError a = <- w1; + test:assertTrue(a is int, "Invalid result"); + test:assertEquals(a, 1, "Invalid int result"); + 3 -> w2; + } + + map mapResult = wait w2; + test:assertTrue(mapResult["w1"] is errorLib:NoMessageError, "Invalid map result"); + errorLib:NoMessageError e = mapResult["w1"]; + test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w2'\"}", "Invalid error detail"); + test:assertEquals(mapResult["w3"], 3, "Invalid map result"); +} From 3a75d120485829155b9af2e8f8123dd364e08b54 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 16 Jan 2024 14:13:19 +0530 Subject: [PATCH 65/97] Add stream-receive-action parsing support --- .../util/diagnostic/DiagnosticErrorCode.java | 2 +- .../compiler/parser/BLangNodeBuilder.java | 41 +- .../src/main/resources/compiler.properties | 3 + .../internal/parser/BallerinaParser.java | 126 +- .../parser/BallerinaParserErrorHandler.java | 54 +- .../internal/parser/ParserRuleContext.java | 7 +- ...rNode.java => STAlternateReceiveNode.java} | 20 +- .../internal/parser/tree/STNodeFactory.java | 24 +- .../parser/tree/STNodeTransformer.java | 12 +- .../internal/parser/tree/STNodeVisitor.java | 12 +- .../parser/tree/STSingleReceiveNode.java | 84 ++ .../parser/tree/STStreamReceiveNode.java | 114 ++ .../internal/parser/tree/STTreeModifier.java | 30 +- ...kerNode.java => AlternateReceiveNode.java} | 24 +- .../compiler/syntax/tree/NodeFactory.java | 34 +- .../compiler/syntax/tree/NodeTransformer.java | 12 +- .../compiler/syntax/tree/NodeVisitor.java | 12 +- .../syntax/tree/SingleReceiveNode.java | 96 ++ .../syntax/tree/StreamReceiveNode.java | 150 +++ .../compiler/syntax/tree/SyntaxKind.java | 4 +- .../compiler/syntax/tree/TreeModifier.java | 35 +- .../compiler/parser/test/ParserTestUtils.java | 8 +- .../syntax/actions/ReceiveActionTest.java | 10 + .../receive_action_assert_01.json | 31 +- .../receive_action_assert_02.json | 32 +- .../receive_action_assert_04.json | 14 +- .../receive_action_assert_05.json | 6 +- .../receive_action_assert_06.json | 1074 +++++++++++++++++ .../receive_action_assert_07.json | 802 ++++++++++++ .../receive_action_source_06.bal | 13 + .../receive_action_source_07.bal | 7 + .../misc/completion/completion_assert_08.json | 16 +- .../main/resources/syntax_node_metadata.json | 12 +- .../resources/syntax_tree_descriptor.json | 39 +- .../core/FormattingTreeModifier.java | 29 +- .../formatter/core/ParserTestFormatter.java | 2 +- .../api_gen_syntax_tree_descriptor.json | 39 +- 37 files changed, 2888 insertions(+), 142 deletions(-) rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/{STAlternateReceiveWorkerNode.java => STAlternateReceiveNode.java} (78%) create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/{AlternateReceiveWorkerNode.java => AlternateReceiveNode.java} (73%) create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java create mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal create mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 2a7f68084a4f..d73d74bd11da 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -119,7 +119,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { WORKER_SEND_RECEIVE_PARAMETER_COUNT_MISMATCH("BCE2082", "worker.send.receive.parameter.count.mismatch"), INVALID_WORKER_INTERACTION("BCE2083", "worker.invalid.worker.interaction"), WORKER_INTERACTIONS_ONLY_ALLOWED_BETWEEN_PEERS("BCE2084", "worker.interactions.only.allowed.between.peers"), - // VACANT_ERROR("BCE2085", ""), + STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE2085", "stream.receive.action.not.yet.supported"), // VACANT_ERROR("BCE2086", ""), EXPLICIT_WORKER_CANNOT_BE_DEFAULT("BCE2087", "explicit.worker.cannot.be.default"), INVALID_MULTIPLE_FORK_JOIN_SEND("BCE2088", "worker.multiple.fork.join.send"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 3eacef322e81..c7d1b52d9f0b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -17,7 +17,7 @@ */ package org.wso2.ballerinalang.compiler.parser; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -203,12 +203,14 @@ import io.ballerina.compiler.syntax.tree.SeparatedNodeList; import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; +import io.ballerina.compiler.syntax.tree.SingleReceiveNode; import io.ballerina.compiler.syntax.tree.SingletonTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SpecificFieldNode; import io.ballerina.compiler.syntax.tree.SpreadFieldNode; import io.ballerina.compiler.syntax.tree.SpreadMemberNode; import io.ballerina.compiler.syntax.tree.StartActionNode; import io.ballerina.compiler.syntax.tree.StatementNode; +import io.ballerina.compiler.syntax.tree.StreamReceiveNode; import io.ballerina.compiler.syntax.tree.StreamTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.StreamTypeParamsNode; import io.ballerina.compiler.syntax.tree.SyncSendActionNode; @@ -2527,25 +2529,23 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { Location receiveActionPos = getPosition(receiveActionNode); Node receiveWorkers = receiveActionNode.receiveWorkers(); - if (receiveWorkers.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { - BLangWorkerReceive singleWorkerRecv = - createSimpleWorkerReceive(((SimpleNameReferenceNode) receiveWorkers).name()); + if (receiveWorkers.kind() == SyntaxKind.SINGLE_RECEIVE) { + SingleReceiveNode singleReceiveNode = (SingleReceiveNode) receiveWorkers; + BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive(singleReceiveNode.worker().name()); singleWorkerRecv.pos = receiveActionPos; return singleWorkerRecv; } - if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE_WORKER) { + if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE) { SeparatedNodeList alternateWorkers = - ((AlternateReceiveWorkerNode) receiveWorkers).workers(); - List workerReceives = new ArrayList<>(alternateWorkers.size()); - for (SimpleNameReferenceNode w : alternateWorkers) { - workerReceives.add(createSimpleWorkerReceive(w.name())); - } + ((AlternateReceiveNode) receiveWorkers).workers(); + return createAlternateWorkerReceive(alternateWorkers, receiveActionPos); + } - BLangAlternateWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); - alternateWorkerRecv.setWorkerReceives(workerReceives); - alternateWorkerRecv.pos = receiveActionPos; - return alternateWorkerRecv; + if (receiveWorkers.kind() == SyntaxKind.STREAM_RECEIVE) { + dlog.error(receiveActionPos, DiagnosticErrorCode.STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED); + // mock rest of the flow as an alternative receive + return createAlternateWorkerReceive(((StreamReceiveNode) receiveWorkers).workers(), receiveActionPos); } ReceiveFieldsNode receiveFieldsNode = (ReceiveFieldsNode) receiveWorkers; @@ -2571,6 +2571,19 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { return multipleWorkerRv; } + private BLangAlternateWorkerReceive createAlternateWorkerReceive( + SeparatedNodeList alternateWorkers, Location receiveActionPos) { + List workerReceives = new ArrayList<>(alternateWorkers.size()); + for (SimpleNameReferenceNode w : alternateWorkers) { + workerReceives.add(createSimpleWorkerReceive(w.name())); + } + + BLangAlternateWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); + alternateWorkerRecv.setWorkerReceives(workerReceives); + alternateWorkerRecv.pos = receiveActionPos; + return alternateWorkerRecv; + } + private BLangWorkerReceive createSimpleWorkerReceive(Token workerRef) { BLangWorkerReceive workerReceiveExpr = (BLangWorkerReceive) TreeBuilder.createWorkerReceiveNode(); workerReceiveExpr.setWorkerName(createIdentifier(workerRef)); diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index d5bc72c9b478..12871b613adb 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -2021,3 +2021,6 @@ error.inferred.query.construct.type.as.stream=\ error.invalid.binding.pattern.in.on.fail=\ invalid binding pattern in ''on fail'' clause: only a capture binding pattern or an error binding pattern is allowed + +error.stream.receive.action.not.yet.supported=\ + stream receive action not yet supported diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 4c06f11a3c28..b9c4e94fa205 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13076,63 +13076,147 @@ private STNode parseSyncSendToken() { * multiple-receive-action := <- { receive-field (, receive-field)* } *

* alternate-receive-action := <- peer-worker (| peer-worker)* + *

+ * stream-receive-action := <- stream `(` peer-worker (| peer-worker)* `)` * * * @return Receive action */ private STNode parseReceiveAction() { STNode leftArrow = parseLeftArrowToken(); - STNode receiveWorkers = parseReceiveWorkers(); - return STNodeFactory.createReceiveActionNode(leftArrow, receiveWorkers); + STNode receiveRhs = parseReceiveActionRhs(); + return STNodeFactory.createReceiveActionNode(leftArrow, receiveRhs); } - private STNode parseReceiveWorkers() { + private STNode parseReceiveActionRhs() { switch (peek().kind) { case FUNCTION_KEYWORD: case IDENTIFIER_TOKEN: - return parseSingleOrAlternateReceiveWorkers(); + return parseSingleOrAlternateReceiveRhs(); case OPEN_BRACE_TOKEN: - return parseMultipleReceiveWorkers(); + return parseMultipleReceiveRhs(); + case STREAM_KEYWORD: + return parseStreamReceiveRhs(); default: - recover(peek(), ParserRuleContext.RECEIVE_WORKERS); - return parseReceiveWorkers(); + recover(peek(), ParserRuleContext.RECEIVE_ACTION_RHS); + return parseReceiveActionRhs(); } } - private STNode parseSingleOrAlternateReceiveWorkers() { - startContext(ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER); - List workers = new ArrayList<>(); - // Parse first peer worker name, that has no leading comma - STNode peerWorker = parsePeerWorkerName(); - workers.add(peerWorker); - + /** + * Parse single or alternate receive action rhs. + *

+ *

+ * single-receive-rhs := peer-worker + *

+ * alternate-receive-rhs := peer-worker (| peer-worker)* + *
+ * + * @return Receive action + */ + private STNode parseSingleOrAlternateReceiveRhs() { + startContext(ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS); + STNode firstPeerWorker = parsePeerWorkerName(); STToken nextToken = peek(); if (nextToken.kind != SyntaxKind.PIPE_TOKEN) { endContext(); - return peerWorker; + return STNodeFactory.createSingleReceiveNode(firstPeerWorker); } + STNode peerWorkers = parsePeerWorkers(firstPeerWorker); + endContext(); + return STNodeFactory.createAlternateReceiveNode(peerWorkers); + } + + /** + * Parse peer worker list separated by `|`. + * + * @param firstPeerWorker first peer worker node + * @return Parsed node + */ + private STNode parsePeerWorkers(STNode firstPeerWorker) { + List workers = new ArrayList<>(); + workers.add(firstPeerWorker); + // Parse the remaining peer worker names + STToken nextToken = peek(); while (nextToken.kind == SyntaxKind.PIPE_TOKEN) { STNode pipeToken = consume(); workers.add(pipeToken); - peerWorker = parsePeerWorkerName(); + STNode peerWorker = parsePeerWorkerName(); workers.add(peerWorker); nextToken = peek(); } + return STNodeFactory.createNodeList(workers); + } + + /** + * Parse stream receive action rhs. + *

+ * + * stream-receive-rhs := stream `(` peer-worker (| peer-worker)* `)` + * + * + * @return Parsed node + */ + private STNode parseStreamReceiveRhs() { + startContext(ParserRuleContext.STREAM_RECEIVE_RHS); + STNode streamKeyword = parseStreamKeyword(); + STNode openParen = parseOpenParenthesis(); + STNode workers = parseStreamPeerWorkers(); + STNode closeParen = parseCloseParenthesis(); endContext(); - return STNodeFactory.createAlternateReceiveWorkerNode(STNodeFactory.createNodeList(workers)); + return STNodeFactory.createStreamReceiveNode(streamKeyword, openParen, workers, closeParen); + } + + /** + * Parse stream-keyword. + * + * @return Parsed node + */ + private STNode parseStreamKeyword() { + STToken token = peek(); + if (token.kind == SyntaxKind.STREAM_KEYWORD) { + return consume(); + } else { + recover(token, ParserRuleContext.STREAM_KEYWORD); + return parseStreamKeyword(); + } } /** - * Parse multiple worker receivers. + * Parse stream receive peer worker list. *

- * { receive-field (, receive-field)* } + * + * stream-receive-peer-workers := peer-worker (| peer-worker)* + * * - * @return Multiple worker receiver node + * @return Parsed node + */ + private STNode parseStreamPeerWorkers() { + STNode firstPeerWorker = parsePeerWorkerName(); + + STToken nextToken = peek(); + if (nextToken.kind != SyntaxKind.PIPE_TOKEN) { + return STNodeFactory.createNodeList(new ArrayList<>(Collections.singletonList(firstPeerWorker))); + } + + return parsePeerWorkers(firstPeerWorker); + } + + /** + * Parse multiple receive action rhs. + *

+ * + * multiple-receive-rhs := { receive-field (, receive-field)* } + *

+ * receive-field := peer-worker | field-name : peer-worker + *
+ * + * @return Parsed node */ - private STNode parseMultipleReceiveWorkers() { + private STNode parseMultipleReceiveRhs() { startContext(ParserRuleContext.MULTI_RECEIVE_WORKERS); STNode openBrace = parseOpenBrace(); STNode receiveFields = parseReceiveFields(); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java index 20b922cfe6bf..258c9c62cfc4 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java @@ -521,12 +521,16 @@ public class BallerinaParserErrorHandler extends AbstractParserErrorHandler { private static final ParserRuleContext[] REMOTE_CALL_OR_ASYNC_SEND_END = { ParserRuleContext.ARG_LIST_OPEN_PAREN, ParserRuleContext.SEMICOLON }; - private static final ParserRuleContext[] RECEIVE_WORKERS = - { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER, ParserRuleContext.MULTI_RECEIVE_WORKERS }; + private static final ParserRuleContext[] RECEIVE_ACTION_RHS = + { ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS, ParserRuleContext.STREAM_RECEIVE_RHS, + ParserRuleContext.MULTI_RECEIVE_WORKERS }; private static final ParserRuleContext[] SINGLE_OR_ALTERNATE_WORKER_SEPARATOR = { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END, ParserRuleContext.PIPE }; + private static final ParserRuleContext[] STREAM_WORKER_SEPARATOR = + { ParserRuleContext.STREAM_WORKER_END, ParserRuleContext.PIPE }; + private static final ParserRuleContext[] RECEIVE_FIELD = { ParserRuleContext.PEER_WORKER_NAME, ParserRuleContext.RECEIVE_FIELD_NAME }; @@ -1478,7 +1482,7 @@ protected boolean hasAlternativePaths(ParserRuleContext currentCtx) { case NIL_OR_PARENTHESISED_TYPE_DESC_RHS: case REMOTE_OR_RESOURCE_CALL_OR_ASYNC_SEND_RHS: case REMOTE_CALL_OR_ASYNC_SEND_END: - case RECEIVE_WORKERS: + case RECEIVE_ACTION_RHS: case RECEIVE_FIELD: case RECEIVE_FIELD_END: case WAIT_KEYWORD_RHS: @@ -1611,6 +1615,7 @@ protected boolean hasAlternativePaths(ParserRuleContext currentCtx) { case GROUPING_KEY_LIST_ELEMENT_END: case RESULT_CLAUSE: case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: + case STREAM_WORKER_SEPARATOR: return true; default: return false; @@ -1837,7 +1842,7 @@ protected ParserRuleContext getShortestAlternative(ParserRuleContext currentCtx) return ParserRuleContext.PEER_WORKER_NAME; case REMOTE_CALL_OR_ASYNC_SEND_END: return ParserRuleContext.SEMICOLON; - case RECEIVE_WORKERS: + case RECEIVE_ACTION_RHS: case RECEIVE_FIELD: return ParserRuleContext.PEER_WORKER_NAME; case RECEIVE_FIELD_END: @@ -2081,6 +2086,8 @@ protected ParserRuleContext getShortestAlternative(ParserRuleContext currentCtx) return ParserRuleContext.SELECT_CLAUSE; case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END; + case STREAM_WORKER_SEPARATOR: + return ParserRuleContext.STREAM_WORKER_END; default: throw new IllegalStateException("Alternative path entry not found"); } @@ -2571,8 +2578,8 @@ private Result seekMatchInStmtRelatedAlternativePaths(ParserRuleContext currentC case OPTIONAL_RESOURCE_ACCESS_ACTION_ARG_LIST: alternativeRules = OPTIONAL_RESOURCE_ACCESS_ACTION_ARG_LIST; break; - case RECEIVE_WORKERS: - alternativeRules = RECEIVE_WORKERS; + case RECEIVE_ACTION_RHS: + alternativeRules = RECEIVE_ACTION_RHS; break; case RECEIVE_FIELD: alternativeRules = RECEIVE_FIELD; @@ -2854,6 +2861,9 @@ private Result seekMatchInExprRelatedAlternativePaths(ParserRuleContext currentC case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: alternativeRules = SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; break; + case STREAM_WORKER_SEPARATOR: + alternativeRules = STREAM_WORKER_SEPARATOR; + break; default: throw new IllegalStateException("seekMatchInExprRelatedAlternativePaths found: " + currentCtx); } @@ -3490,11 +3500,15 @@ protected ParserRuleContext getNextRule(ParserRuleContext currentCtx, int nextLo return getNextRuleForBindingPattern(); case TUPLE_MEMBERS: return ParserRuleContext.TUPLE_MEMBER; - case SINGLE_OR_ALTERNATE_WORKER: + case SINGLE_OR_ALTERNATE_RECEIVE_RHS: return ParserRuleContext.PEER_WORKER_NAME; case SINGLE_OR_ALTERNATE_WORKER_END: endContext(); // end single-or-alternate-worker return ParserRuleContext.EXPRESSION_RHS; + case STREAM_RECEIVE_RHS: + return ParserRuleContext.STREAM_KEYWORD; + case STREAM_WORKER_END: + return ParserRuleContext.CLOSE_PARENTHESIS; default: return getNextRuleInternal(currentCtx, nextLookahead); } @@ -3518,7 +3532,8 @@ private ParserRuleContext getNextRuleInternal(ParserRuleContext currentCtx, int return ParserRuleContext.XML_ATOMIC_NAME_PATTERN; } else if (parentCtx == ParserRuleContext.MATCH_PATTERN) { return ParserRuleContext.MATCH_PATTERN_START; - } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS || + parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { return ParserRuleContext.PEER_WORKER_NAME; } return ParserRuleContext.TYPE_DESCRIPTOR; @@ -3727,7 +3742,7 @@ private ParserRuleContext getNextRuleInternal(ParserRuleContext currentCtx, int case SYNC_SEND_TOKEN: return ParserRuleContext.PEER_WORKER_NAME; case LEFT_ARROW_TOKEN: - return ParserRuleContext.RECEIVE_WORKERS; + return ParserRuleContext.RECEIVE_ACTION_RHS; case MULTI_RECEIVE_WORKERS: return ParserRuleContext.OPEN_BRACE; case RECEIVE_FIELD_NAME: @@ -4064,6 +4079,8 @@ private ParserRuleContext getNextRuleForKeywords(ParserRuleContext currentCtx, i parentCtx = getParentContext(); if (parentCtx == ParserRuleContext.TABLE_CONSTRUCTOR_OR_QUERY_EXPRESSION) { return ParserRuleContext.QUERY_EXPRESSION; + } else if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { + return ParserRuleContext.OPEN_PARENTHESIS; } return ParserRuleContext.STREAM_TYPE_PARAM_START_TOKEN; case NEW_KEYWORD: @@ -4110,8 +4127,10 @@ private ParserRuleContext getNextRuleForKeywords(ParserRuleContext currentCtx, i parentCtx = getParentContext(); if (parentCtx == ParserRuleContext.MULTI_RECEIVE_WORKERS) { return ParserRuleContext.RECEIVE_FIELD_END; - } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS) { return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; + } else if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { + return ParserRuleContext.STREAM_WORKER_SEPARATOR; } return ParserRuleContext.EXPRESSION_RHS; case WAIT_KEYWORD: @@ -4288,7 +4307,8 @@ private void startContextIfRequired(ParserRuleContext currentCtx) { case BRACED_EXPRESSION: case CLIENT_RESOURCE_ACCESS_ACTION: case TUPLE_MEMBERS: - case SINGLE_OR_ALTERNATE_WORKER: + case SINGLE_OR_ALTERNATE_RECEIVE_RHS: + case STREAM_RECEIVE_RHS: // Contexts that expect a type case TYPE_DESC_IN_ANNOTATION_DECL: @@ -4325,9 +4345,11 @@ private void startContextIfRequired(ParserRuleContext currentCtx) { } private ParserRuleContext getNextRuleForCloseParenthesis() { - ParserRuleContext parentCtx; - parentCtx = getParentContext(); - if (parentCtx == ParserRuleContext.PARAM_LIST) { + ParserRuleContext parentCtx = getParentContext(); + if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { + endContext(); // end stream-receive-rhs + return ParserRuleContext.EXPRESSION_RHS; + } else if (parentCtx == ParserRuleContext.PARAM_LIST) { endContext(); // end parameters return ParserRuleContext.FUNC_OPTIONAL_RETURNS; } else if (isParameter(parentCtx)) { @@ -4374,7 +4396,9 @@ private ParserRuleContext getNextRuleForCloseParenthesis() { private ParserRuleContext getNextRuleForOpenParenthesis() { ParserRuleContext parentCtx = getParentContext(); - if (parentCtx == ParserRuleContext.EXPRESSION_STATEMENT) { + if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { + return ParserRuleContext.PEER_WORKER_NAME; + } else if (parentCtx == ParserRuleContext.EXPRESSION_STATEMENT) { return ParserRuleContext.EXPRESSION_STATEMENT_START; } else if (isStatement(parentCtx) || isExpressionContext(parentCtx) || parentCtx == ParserRuleContext.ARRAY_TYPE_DESCRIPTOR || diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java index 7463f0a3281b..4ad9fe6eb5b6 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java @@ -223,7 +223,7 @@ public enum ParserRuleContext { REMOTE_OR_RESOURCE_CALL_OR_ASYNC_SEND_RHS("remote-or-resource-call-or-async-send-rhs"), REMOTE_CALL_OR_ASYNC_SEND_END("remote-call-or-async-send-end"), DEFAULT_WORKER_NAME_IN_ASYNC_SEND("default-worker-name-in-async-send"), - RECEIVE_WORKERS("receive-workers"), + RECEIVE_ACTION_RHS("receive-action-rhs"), MULTI_RECEIVE_WORKERS("multi-receive-workers"), RECEIVE_FIELD_END("receive-field-end"), RECEIVE_FIELD("receive-field"), @@ -733,9 +733,12 @@ public enum ParserRuleContext { OPTIONAL_TOP_LEVEL_SEMICOLON("optional-top-level-semicolon"), TUPLE_MEMBERS("tuple-members"), TUPLE_MEMBER("tuple-member"), - SINGLE_OR_ALTERNATE_WORKER("single-or-alternate-worker"), + SINGLE_OR_ALTERNATE_RECEIVE_RHS("single-or-alternate-receive-rhs"), SINGLE_OR_ALTERNATE_WORKER_SEPARATOR("single-or-alternate-worker-separator"), SINGLE_OR_ALTERNATE_WORKER_END("single-or-alternate-worker-end"), + STREAM_RECEIVE_RHS("stream-receive-rhs"), + STREAM_WORKER_SEPARATOR("stream-worker-separator"), + STREAM_WORKER_END("stream-worker-end"), ; private String value; diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java similarity index 78% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java index cdf5bbd00e4b..63f3f4c92977 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -17,7 +17,7 @@ */ package io.ballerina.compiler.internal.parser.tree; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NonTerminalNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; @@ -30,20 +30,20 @@ * * @since 2201.9.0 */ -public class STAlternateReceiveWorkerNode extends STNode { +public class STAlternateReceiveNode extends STNode { public final STNode workers; - STAlternateReceiveWorkerNode( + STAlternateReceiveNode( STNode workers) { this( workers, Collections.emptyList()); } - STAlternateReceiveWorkerNode( + STAlternateReceiveNode( STNode workers, Collection diagnostics) { - super(SyntaxKind.ALTERNATE_RECEIVE_WORKER, diagnostics); + super(SyntaxKind.ALTERNATE_RECEIVE, diagnostics); this.workers = workers; addChildren( @@ -51,25 +51,25 @@ public class STAlternateReceiveWorkerNode extends STNode { } public STNode modifyWith(Collection diagnostics) { - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( this.workers, diagnostics); } - public STAlternateReceiveWorkerNode modify( + public STAlternateReceiveNode modify( STNode workers) { if (checkForReferenceEquality( workers)) { return this; } - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( workers, diagnostics); } public Node createFacade(int position, NonTerminalNode parent) { - return new AlternateReceiveWorkerNode(this, position, parent); + return new AlternateReceiveNode(this, position, parent); } @Override diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index 9dd731622273..3e758e91c0a1 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -1826,10 +1826,10 @@ public static STNode createReceiveFieldsNode( closeBrace); } - public static STNode createAlternateReceiveWorkerNode( + public static STNode createAlternateReceiveNode( STNode workers) { - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( workers); } @@ -2730,5 +2730,25 @@ public static STNode createReceiveFieldNode( colon, peerWorker); } + + public static STNode createStreamReceiveNode( + STNode streamKeyword, + STNode openParenthesis, + STNode workers, + STNode closeParenthesis) { + + return new STStreamReceiveNode( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + + public static STNode createSingleReceiveNode( + STNode worker) { + + return new STSingleReceiveNode( + worker); + } } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java index 295e3c84c5c2..28394b8054e1 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java @@ -621,8 +621,8 @@ public T transform(STReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - return transformSyntaxNode(alternateReceiveWorkerNode); + public T transform(STAlternateReceiveNode alternateReceiveNode) { + return transformSyntaxNode(alternateReceiveNode); } public T transform(STRestDescriptorNode restDescriptorNode) { @@ -945,6 +945,14 @@ public T transform(STReceiveFieldNode receiveFieldNode) { return transformSyntaxNode(receiveFieldNode); } + public T transform(STStreamReceiveNode streamReceiveNode) { + return transformSyntaxNode(streamReceiveNode); + } + + public T transform(STSingleReceiveNode singleReceiveNode) { + return transformSyntaxNode(singleReceiveNode); + } + // Tokens public T transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java index 1fd5c558a1f7..fb00f619afaf 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java @@ -621,8 +621,8 @@ public void visit(STReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - visitSyntaxNode(alternateReceiveWorkerNode); + public void visit(STAlternateReceiveNode alternateReceiveNode) { + visitSyntaxNode(alternateReceiveNode); } public void visit(STRestDescriptorNode restDescriptorNode) { @@ -945,6 +945,14 @@ public void visit(STReceiveFieldNode receiveFieldNode) { visitSyntaxNode(receiveFieldNode); } + public void visit(STStreamReceiveNode streamReceiveNode) { + visitSyntaxNode(streamReceiveNode); + } + + public void visit(STSingleReceiveNode singleReceiveNode) { + visitSyntaxNode(singleReceiveNode); + } + // STNodeList public void visit(STNodeList nodeList) { visitChildren(nodeList); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java new file mode 100644 index 000000000000..32e4b3259509 --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.internal.parser.tree; + +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NonTerminalNode; +import io.ballerina.compiler.syntax.tree.SingleReceiveNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; + +import java.util.Collection; +import java.util.Collections; + +/** + * This is a generated internal syntax tree node. + * + * @since 2201.9.0 + */ +public class STSingleReceiveNode extends STNode { + public final STNode worker; + + STSingleReceiveNode( + STNode worker) { + this( + worker, + Collections.emptyList()); + } + + STSingleReceiveNode( + STNode worker, + Collection diagnostics) { + super(SyntaxKind.SINGLE_RECEIVE, diagnostics); + this.worker = worker; + + addChildren( + worker); + } + + public STNode modifyWith(Collection diagnostics) { + return new STSingleReceiveNode( + this.worker, + diagnostics); + } + + public STSingleReceiveNode modify( + STNode worker) { + if (checkForReferenceEquality( + worker)) { + return this; + } + + return new STSingleReceiveNode( + worker, + diagnostics); + } + + public Node createFacade(int position, NonTerminalNode parent) { + return new SingleReceiveNode(this, position, parent); + } + + @Override + public void accept(STNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(STNodeTransformer transformer) { + return transformer.transform(this); + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java new file mode 100644 index 000000000000..e7f2385d4392 --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.internal.parser.tree; + +import io.ballerina.compiler.syntax.tree.Node; +import io.ballerina.compiler.syntax.tree.NonTerminalNode; +import io.ballerina.compiler.syntax.tree.StreamReceiveNode; +import io.ballerina.compiler.syntax.tree.SyntaxKind; + +import java.util.Collection; +import java.util.Collections; + +/** + * This is a generated internal syntax tree node. + * + * @since 2201.9.0 + */ +public class STStreamReceiveNode extends STNode { + public final STNode streamKeyword; + public final STNode openParenthesis; + public final STNode workers; + public final STNode closeParenthesis; + + STStreamReceiveNode( + STNode streamKeyword, + STNode openParenthesis, + STNode workers, + STNode closeParenthesis) { + this( + streamKeyword, + openParenthesis, + workers, + closeParenthesis, + Collections.emptyList()); + } + + STStreamReceiveNode( + STNode streamKeyword, + STNode openParenthesis, + STNode workers, + STNode closeParenthesis, + Collection diagnostics) { + super(SyntaxKind.STREAM_RECEIVE, diagnostics); + this.streamKeyword = streamKeyword; + this.openParenthesis = openParenthesis; + this.workers = workers; + this.closeParenthesis = closeParenthesis; + + addChildren( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + + public STNode modifyWith(Collection diagnostics) { + return new STStreamReceiveNode( + this.streamKeyword, + this.openParenthesis, + this.workers, + this.closeParenthesis, + diagnostics); + } + + public STStreamReceiveNode modify( + STNode streamKeyword, + STNode openParenthesis, + STNode workers, + STNode closeParenthesis) { + if (checkForReferenceEquality( + streamKeyword, + openParenthesis, + workers, + closeParenthesis)) { + return this; + } + + return new STStreamReceiveNode( + streamKeyword, + openParenthesis, + workers, + closeParenthesis, + diagnostics); + } + + public Node createFacade(int position, NonTerminalNode parent) { + return new StreamReceiveNode(this, position, parent); + } + + @Override + public void accept(STNodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(STNodeTransformer transformer) { + return transformer.transform(this); + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index be89fe8f2121..88ac4ad28f95 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -1956,10 +1956,10 @@ public STReceiveFieldsNode transform( } @Override - public STAlternateReceiveWorkerNode transform( - STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - STNode workers = modifyNode(alternateReceiveWorkerNode.workers); - return alternateReceiveWorkerNode.modify( + public STAlternateReceiveNode transform( + STAlternateReceiveNode alternateReceiveNode) { + STNode workers = modifyNode(alternateReceiveNode.workers); + return alternateReceiveNode.modify( workers); } @@ -2937,6 +2937,28 @@ public STReceiveFieldNode transform( peerWorker); } + @Override + public STStreamReceiveNode transform( + STStreamReceiveNode streamReceiveNode) { + STNode streamKeyword = modifyNode(streamReceiveNode.streamKeyword); + STNode openParenthesis = modifyNode(streamReceiveNode.openParenthesis); + STNode workers = modifyNode(streamReceiveNode.workers); + STNode closeParenthesis = modifyNode(streamReceiveNode.closeParenthesis); + return streamReceiveNode.modify( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + + @Override + public STSingleReceiveNode transform( + STSingleReceiveNode singleReceiveNode) { + STNode worker = modifyNode(singleReceiveNode.worker); + return singleReceiveNode.modify( + worker); + } + // Tokens public STToken transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java similarity index 73% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java index 9faf603d867d..c8f94dad42cd 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -26,9 +26,9 @@ * * @since 2201.9.0 */ -public class AlternateReceiveWorkerNode extends NonTerminalNode { +public class AlternateReceiveNode extends NonTerminalNode { - public AlternateReceiveWorkerNode(STNode internalNode, int position, NonTerminalNode parent) { + public AlternateReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { super(internalNode, position, parent); } @@ -52,19 +52,19 @@ protected String[] childNames() { "workers"}; } - public AlternateReceiveWorkerNode modify( + public AlternateReceiveNode modify( SeparatedNodeList workers) { if (checkForReferenceEquality( workers.underlyingListNode())) { return this; } - return NodeFactory.createAlternateReceiveWorkerNode( + return NodeFactory.createAlternateReceiveNode( workers); } - public AlternateReceiveWorkerNodeModifier modify() { - return new AlternateReceiveWorkerNodeModifier(this); + public AlternateReceiveNodeModifier modify() { + return new AlternateReceiveNodeModifier(this); } /** @@ -72,23 +72,23 @@ public AlternateReceiveWorkerNodeModifier modify() { * * @since 2201.9.0 */ - public static class AlternateReceiveWorkerNodeModifier { - private final AlternateReceiveWorkerNode oldNode; + public static class AlternateReceiveNodeModifier { + private final AlternateReceiveNode oldNode; private SeparatedNodeList workers; - public AlternateReceiveWorkerNodeModifier(AlternateReceiveWorkerNode oldNode) { + public AlternateReceiveNodeModifier(AlternateReceiveNode oldNode) { this.oldNode = oldNode; this.workers = oldNode.workers(); } - public AlternateReceiveWorkerNodeModifier withWorkers( + public AlternateReceiveNodeModifier withWorkers( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); this.workers = workers; return this; } - public AlternateReceiveWorkerNode apply() { + public AlternateReceiveNode apply() { return oldNode.modify( workers); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index b11a56354eaf..a49fcbad3117 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -2430,13 +2430,13 @@ public static ReceiveFieldsNode createReceiveFieldsNode( return stReceiveFieldsNode.createUnlinkedFacade(); } - public static AlternateReceiveWorkerNode createAlternateReceiveWorkerNode( + public static AlternateReceiveNode createAlternateReceiveNode( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); - STNode stAlternateReceiveWorkerNode = STNodeFactory.createAlternateReceiveWorkerNode( + STNode stAlternateReceiveNode = STNodeFactory.createAlternateReceiveNode( workers.underlyingListNode().internalNode()); - return stAlternateReceiveWorkerNode.createUnlinkedFacade(); + return stAlternateReceiveNode.createUnlinkedFacade(); } public static RestDescriptorNode createRestDescriptorNode( @@ -3637,5 +3637,31 @@ public static ReceiveFieldNode createReceiveFieldNode( peerWorker.internalNode()); return stReceiveFieldNode.createUnlinkedFacade(); } -} + public static StreamReceiveNode createStreamReceiveNode( + Token streamKeyword, + Token openParenthesis, + SeparatedNodeList workers, + Token closeParenthesis) { + Objects.requireNonNull(streamKeyword, "streamKeyword must not be null"); + Objects.requireNonNull(openParenthesis, "openParenthesis must not be null"); + Objects.requireNonNull(workers, "workers must not be null"); + Objects.requireNonNull(closeParenthesis, "closeParenthesis must not be null"); + + STNode stStreamReceiveNode = STNodeFactory.createStreamReceiveNode( + streamKeyword.internalNode(), + openParenthesis.internalNode(), + workers.underlyingListNode().internalNode(), + closeParenthesis.internalNode()); + return stStreamReceiveNode.createUnlinkedFacade(); + } + + public static SingleReceiveNode createSingleReceiveNode( + SimpleNameReferenceNode worker) { + Objects.requireNonNull(worker, "worker must not be null"); + + STNode stSingleReceiveNode = STNodeFactory.createSingleReceiveNode( + worker.internalNode()); + return stSingleReceiveNode.createUnlinkedFacade(); + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java index d0557866aaf9..726778d6ddd5 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java @@ -632,8 +632,8 @@ public T transform(ReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { - return transformSyntaxNode(alternateReceiveWorkerNode); + public T transform(AlternateReceiveNode alternateReceiveNode) { + return transformSyntaxNode(alternateReceiveNode); } public T transform(RestDescriptorNode restDescriptorNode) { @@ -956,6 +956,14 @@ public T transform(ReceiveFieldNode receiveFieldNode) { return transformSyntaxNode(receiveFieldNode); } + public T transform(StreamReceiveNode streamReceiveNode) { + return transformSyntaxNode(streamReceiveNode); + } + + public T transform(SingleReceiveNode singleReceiveNode) { + return transformSyntaxNode(singleReceiveNode); + } + // Tokens public T transform(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java index 7b41a3d8d075..ec48cdfd9ce3 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java @@ -631,8 +631,8 @@ public void visit(ReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { - visitSyntaxNode(alternateReceiveWorkerNode); + public void visit(AlternateReceiveNode alternateReceiveNode) { + visitSyntaxNode(alternateReceiveNode); } public void visit(RestDescriptorNode restDescriptorNode) { @@ -955,6 +955,14 @@ public void visit(ReceiveFieldNode receiveFieldNode) { visitSyntaxNode(receiveFieldNode); } + public void visit(StreamReceiveNode streamReceiveNode) { + visitSyntaxNode(streamReceiveNode); + } + + public void visit(SingleReceiveNode singleReceiveNode) { + visitSyntaxNode(singleReceiveNode); + } + // Tokens public void visit(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java new file mode 100644 index 000000000000..2f53f65a3e2c --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.syntax.tree; + +import io.ballerina.compiler.internal.parser.tree.STNode; + +import java.util.Objects; + +/** + * This is a generated syntax tree node. + * + * @since 2201.9.0 + */ +public class SingleReceiveNode extends NonTerminalNode { + + public SingleReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { + super(internalNode, position, parent); + } + + public SimpleNameReferenceNode worker() { + return childInBucket(0); + } + + @Override + public void accept(NodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(NodeTransformer visitor) { + return visitor.transform(this); + } + + @Override + protected String[] childNames() { + return new String[]{ + "worker"}; + } + + public SingleReceiveNode modify( + SimpleNameReferenceNode worker) { + if (checkForReferenceEquality( + worker)) { + return this; + } + + return NodeFactory.createSingleReceiveNode( + worker); + } + + public SingleReceiveNodeModifier modify() { + return new SingleReceiveNodeModifier(this); + } + + /** + * This is a generated tree node modifier utility. + * + * @since 2201.9.0 + */ + public static class SingleReceiveNodeModifier { + private final SingleReceiveNode oldNode; + private SimpleNameReferenceNode worker; + + public SingleReceiveNodeModifier(SingleReceiveNode oldNode) { + this.oldNode = oldNode; + this.worker = oldNode.worker(); + } + + public SingleReceiveNodeModifier withWorker( + SimpleNameReferenceNode worker) { + Objects.requireNonNull(worker, "worker must not be null"); + this.worker = worker; + return this; + } + + public SingleReceiveNode apply() { + return oldNode.modify( + worker); + } + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java new file mode 100644 index 000000000000..c476b6d8f56b --- /dev/null +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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 io.ballerina.compiler.syntax.tree; + +import io.ballerina.compiler.internal.parser.tree.STNode; + +import java.util.Objects; + +/** + * This is a generated syntax tree node. + * + * @since 2201.9.0 + */ +public class StreamReceiveNode extends NonTerminalNode { + + public StreamReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { + super(internalNode, position, parent); + } + + public Token streamKeyword() { + return childInBucket(0); + } + + public Token openParenthesis() { + return childInBucket(1); + } + + public SeparatedNodeList workers() { + return new SeparatedNodeList<>(childInBucket(2)); + } + + public Token closeParenthesis() { + return childInBucket(3); + } + + @Override + public void accept(NodeVisitor visitor) { + visitor.visit(this); + } + + @Override + public T apply(NodeTransformer visitor) { + return visitor.transform(this); + } + + @Override + protected String[] childNames() { + return new String[]{ + "streamKeyword", + "openParenthesis", + "workers", + "closeParenthesis"}; + } + + public StreamReceiveNode modify( + Token streamKeyword, + Token openParenthesis, + SeparatedNodeList workers, + Token closeParenthesis) { + if (checkForReferenceEquality( + streamKeyword, + openParenthesis, + workers.underlyingListNode(), + closeParenthesis)) { + return this; + } + + return NodeFactory.createStreamReceiveNode( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + + public StreamReceiveNodeModifier modify() { + return new StreamReceiveNodeModifier(this); + } + + /** + * This is a generated tree node modifier utility. + * + * @since 2201.9.0 + */ + public static class StreamReceiveNodeModifier { + private final StreamReceiveNode oldNode; + private Token streamKeyword; + private Token openParenthesis; + private SeparatedNodeList workers; + private Token closeParenthesis; + + public StreamReceiveNodeModifier(StreamReceiveNode oldNode) { + this.oldNode = oldNode; + this.streamKeyword = oldNode.streamKeyword(); + this.openParenthesis = oldNode.openParenthesis(); + this.workers = oldNode.workers(); + this.closeParenthesis = oldNode.closeParenthesis(); + } + + public StreamReceiveNodeModifier withStreamKeyword( + Token streamKeyword) { + Objects.requireNonNull(streamKeyword, "streamKeyword must not be null"); + this.streamKeyword = streamKeyword; + return this; + } + + public StreamReceiveNodeModifier withOpenParenthesis( + Token openParenthesis) { + Objects.requireNonNull(openParenthesis, "openParenthesis must not be null"); + this.openParenthesis = openParenthesis; + return this; + } + + public StreamReceiveNodeModifier withWorkers( + SeparatedNodeList workers) { + Objects.requireNonNull(workers, "workers must not be null"); + this.workers = workers; + return this; + } + + public StreamReceiveNodeModifier withCloseParenthesis( + Token closeParenthesis) { + Objects.requireNonNull(closeParenthesis, "closeParenthesis must not be null"); + this.closeParenthesis = closeParenthesis; + return this; + } + + public StreamReceiveNode apply() { + return oldNode.modify( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + } +} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java index 84edbf974023..c03b1a64044f 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java @@ -484,8 +484,10 @@ public enum SyntaxKind { GROUPING_KEY_VAR_NAME(3092), GROUP_BY_CLAUSE(3093), COLLECT_CLAUSE(3094), - ALTERNATE_RECEIVE_WORKER(3095), + ALTERNATE_RECEIVE(3095), RECEIVE_FIELD(3096), + STREAM_RECEIVE(3097), + SINGLE_RECEIVE(3098), // XML XML_ELEMENT(4000), diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index ad1fab524d3d..a2e782f98e7e 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -2475,11 +2475,11 @@ public ReceiveFieldsNode transform( } @Override - public AlternateReceiveWorkerNode transform( - AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + public AlternateReceiveNode transform( + AlternateReceiveNode alternateReceiveNode) { SeparatedNodeList workers = - modifySeparatedNodeList(alternateReceiveWorkerNode.workers()); - return alternateReceiveWorkerNode.modify( + modifySeparatedNodeList(alternateReceiveNode.workers()); + return alternateReceiveNode.modify( workers); } @@ -3702,6 +3702,33 @@ public ReceiveFieldNode transform( peerWorker); } + @Override + public StreamReceiveNode transform( + StreamReceiveNode streamReceiveNode) { + Token streamKeyword = + modifyToken(streamReceiveNode.streamKeyword()); + Token openParenthesis = + modifyToken(streamReceiveNode.openParenthesis()); + SeparatedNodeList workers = + modifySeparatedNodeList(streamReceiveNode.workers()); + Token closeParenthesis = + modifyToken(streamReceiveNode.closeParenthesis()); + return streamReceiveNode.modify( + streamKeyword, + openParenthesis, + workers, + closeParenthesis); + } + + @Override + public SingleReceiveNode transform( + SingleReceiveNode singleReceiveNode) { + SimpleNameReferenceNode worker = + modifyNode(singleReceiveNode.worker()); + return singleReceiveNode.modify( + worker); + } + // Tokens @Override diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java index e318d246cda2..9c1b032b10dc 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java @@ -633,8 +633,12 @@ private static SyntaxKind getNodeKind(String kind) { return SyntaxKind.COMPUTED_RESOURCE_ACCESS_SEGMENT; case "RESOURCE_ACCESS_REST_SEGMENT": return SyntaxKind.RESOURCE_ACCESS_REST_SEGMENT; - case "ALTERNATE_RECEIVE_WORKER": - return SyntaxKind.ALTERNATE_RECEIVE_WORKER; + case "ALTERNATE_RECEIVE": + return SyntaxKind.ALTERNATE_RECEIVE; + case "STREAM_RECEIVE": + return SyntaxKind.STREAM_RECEIVE; + case "SINGLE_RECEIVE": + return SyntaxKind.SINGLE_RECEIVE; case "RECEIVE_FIELD": return SyntaxKind.RECEIVE_FIELD; diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java index 446896beb7c9..f9b0d921a774 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java @@ -38,6 +38,11 @@ public void testAlternateReceiveAction() { testFile("receive-action/receive_action_source_04.bal", "receive-action/receive_action_assert_04.json"); } + @Test + public void testStreamReceiveAction() { + testFile("receive-action/receive_action_source_06.bal", "receive-action/receive_action_assert_06.json"); + } + // Recover tests @Test @@ -54,4 +59,9 @@ public void testInvalidNodeInReceiveAction() { public void testAlternateReceiveActionRecovery() { testFile("receive-action/receive_action_source_05.bal", "receive-action/receive_action_assert_05.json"); } + + @Test + public void testStreamReceiveActionRecovery() { + testFile("receive-action/receive_action_source_07.bal", "receive-action/receive_action_assert_07.json"); + } } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index 0614217f73ce..87a1ed4e266f 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -80,10 +80,15 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "children": [ { - "kind": "FUNCTION_KEYWORD" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD" + } + ] } ] } @@ -122,11 +127,16 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] } ] } @@ -189,11 +199,16 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "children": [ { - "kind": "IDENTIFIER_TOKEN", - "value": "b" + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b" + } + ] } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index d3fa057f8f2f..fdcc7307c187 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -79,15 +79,21 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] } ] @@ -147,15 +153,21 @@ "kind": "LEFT_ARROW_TOKEN" }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] } ] diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 19961f156696..9743ea8f002f 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -186,7 +186,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -325,7 +325,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -400,7 +400,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -525,7 +525,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -672,7 +672,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -772,7 +772,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -920,7 +920,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json index 4ae969c3f442..4f7122368510 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json @@ -85,7 +85,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { @@ -260,7 +260,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { @@ -430,7 +430,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json new file mode 100644 index 000000000000..87d5f15449fd --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json @@ -0,0 +1,1074 @@ +{ + "kind": "FUNCTION_DEFINITION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "foo" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "NAMED_WORKER_DECLARATOR", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "NAMED_WORKER_DECLARATION", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "WORKER_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "E", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "FOREACH_STATEMENT", + "children": [ + { + "kind": "FOREACH_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "VAR_TYPE_DESC", + "children": [ + { + "kind": "VAR_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "err", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "IN_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "BLOCK_STATEMENT", + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ACTION_STATEMENT", + "children": [ + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "LOCAL_VAR_DECL", + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "b", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json new file mode 100644 index 000000000000..819947e4ce86 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json @@ -0,0 +1,802 @@ +{ + "kind": "FUNCTION_DEFINITION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "bar" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_BODY_BLOCK", + "hasDiagnostics": true, + "children": [ + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "ACTION_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "hasDiagnostics": true, + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ], + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IMPORT_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "C", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "hasDiagnostics": true, + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ], + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IMPORT_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "D" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN" + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "hasDiagnostics": true, + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OPEN_PAREN_TOKEN" + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_CLOSE_PAREN_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "ASSIGNMENT_STATEMENT", + "hasDiagnostics": true, + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "hasDiagnostics": true, + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OPEN_PAREN_TOKEN" + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "PIPE_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "B" + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_CLOSE_PAREN_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "LOCAL_VAR_DECL", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "children": [ + { + "kind": "INT_TYPE_DESC", + "children": [ + { + "kind": "INT_KEYWORD", + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ], + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "a", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "RECEIVE_ACTION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LEFT_ARROW_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "STREAM_RECEIVE", + "hasDiagnostics": true, + "children": [ + { + "kind": "STREAM_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [ + { + "kind": "SIMPLE_NAME_REFERENCE", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "A", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "hasDiagnostics": true, + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ], + "value": "B" + } + ] + } + } + ] + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal new file mode 100644 index 000000000000..73bccf465337 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal @@ -0,0 +1,13 @@ +function foo() { + worker E { + foreach var err in <- stream (A | B) { + } + } + + <- stream (function | function); + <- stream (A | B | C | D); + <- stream (A | function | D); + a = <- stream (function | A); + a = <- stream (A | B | C); + int b = <- stream (B | C); +} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal new file mode 100644 index 000000000000..ec0bc71423a1 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal @@ -0,0 +1,7 @@ +function bar() { + <- stream (A | import| C | D); + a = <- stream (A | B | import| D); + a = <- stream A; + a = <- stream A | B; + int a = <- stream (A B); +} diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json index d92545238d4f..16a3f949203c 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json @@ -1039,15 +1039,21 @@ ] }, { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "SINGLE_RECEIVE", "hasDiagnostics": true, "children": [ { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } ] } ] diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index ea69efacd564..88e548f67246 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -1,6 +1,14 @@ { - "AlternateReceiveWorkerNode": { - "createdYear": "2023", + "SingleReceiveNode": { + "createdYear": "2024", + "since": "2201.9.0" + }, + "StreamReceiveNode": { + "createdYear": "2024", + "since": "2201.9.0" + }, + "AlternateReceiveNode": { + "createdYear": "2024", "since": "2201.9.0" }, "ClientResourceActionNode": { diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 97d843298269..53a0b59ecb8d 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveWorkerNode", + "name": "AlternateReceiveNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "attributes": [ { "name": "workers", @@ -4976,6 +4976,41 @@ "type": "SimpleNameReferenceNode" } ] + }, + { + "name": "StreamReceiveNode", + "base": "Node", + "kind": "STREAM_RECEIVE", + "attributes": [ + { + "name": "streamKeyword", + "type": "Token" + }, + { + "name": "openParenthesis", + "type": "Token" + }, + { + "name": "workers", + "type": "SimpleNameReferenceNode", + "occurrences": "MULTIPLE_SEPARATED" + }, + { + "name": "closeParenthesis", + "type": "Token" + } + ] + }, + { + "name": "SingleReceiveNode", + "base": "Node", + "kind": "SINGLE_RECEIVE", + "attributes": [ + { + "name": "worker", + "type": "SimpleNameReferenceNode" + } + ] } ] } diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 6636979456fd..27a4af5d12d4 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -17,7 +17,7 @@ */ package org.ballerinalang.formatter.core; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -189,12 +189,14 @@ import io.ballerina.compiler.syntax.tree.SeparatedNodeList; import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; +import io.ballerina.compiler.syntax.tree.SingleReceiveNode; import io.ballerina.compiler.syntax.tree.SingletonTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SpecificFieldNode; import io.ballerina.compiler.syntax.tree.SpreadFieldNode; import io.ballerina.compiler.syntax.tree.SpreadMemberNode; import io.ballerina.compiler.syntax.tree.StartActionNode; import io.ballerina.compiler.syntax.tree.StatementNode; +import io.ballerina.compiler.syntax.tree.StreamReceiveNode; import io.ballerina.compiler.syntax.tree.StreamTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.StreamTypeParamsNode; import io.ballerina.compiler.syntax.tree.SyncSendActionNode; @@ -3029,7 +3031,7 @@ public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { } @Override - public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + public AlternateReceiveNode transform(AlternateReceiveNode alternateReceiveWorkerNode) { SeparatedNodeList workers = formatSeparatedNodeList(alternateReceiveWorkerNode.workers(), 1, 0, env.trailingWS, env.trailingNL); return alternateReceiveWorkerNode.modify() @@ -3037,6 +3039,29 @@ public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternate .apply(); } + @Override + public SingleReceiveNode transform(SingleReceiveNode singleReceiveNode) { + SimpleNameReferenceNode worker = formatNode(singleReceiveNode.worker(), env.trailingWS, env.trailingNL); + return singleReceiveNode.modify() + .withWorker(worker) + .apply(); + } + + @Override + public StreamReceiveNode transform(StreamReceiveNode streamReceiveNode) { + Token streamKeyword = formatToken(streamReceiveNode.streamKeyword(), 1, 0); + Token openParenthesis = formatToken(streamReceiveNode.openParenthesis(), 0, 0); + SeparatedNodeList workers = + formatSeparatedNodeList(streamReceiveNode.workers(), 1, 0, 0, 0); + Token closeParenthesis = formatToken(streamReceiveNode.closeParenthesis(), env.trailingWS, env.trailingNL); + return streamReceiveNode.modify() + .withStreamKeyword(streamKeyword) + .withOpenParenthesis(openParenthesis) + .withWorkers(workers) + .withCloseParenthesis(closeParenthesis) + .apply(); + } + @Override public ReceiveFieldNode transform(ReceiveFieldNode receiveFieldNode) { SimpleNameReferenceNode fieldName = formatNode(receiveFieldNode.fieldName(), 0, 0); diff --git a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java index 6f06b62f41dd..0efb89b92c5b 100644 --- a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java +++ b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java @@ -92,7 +92,7 @@ public List skipList() { // The following tests are disabled due to tokens merging together after formatting. issue #35240 "query_expr_source_121.bal", "query_expr_source_123.bal", "query_expr_source_124.bal", "query_expr_source_126.bal", "match_stmt_source_21.bal", - "func_params_source_27.bal", + "func_params_source_27.bal", "receive_action_source_07.bal", "separated_node_list_import_decl.bal", "node_location_test_03.bal", diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index 72f8496140b0..e0e4c20ae861 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveWorkerNode", + "name": "AlternateReceiveNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "attributes": [ { "name": "workers", @@ -4976,6 +4976,41 @@ "type": "SimpleNameReferenceNode" } ] + }, + { + "name": "StreamReceiveNode", + "base": "Node", + "kind": "STREAM_RECEIVE", + "attributes": [ + { + "name": "streamKeyword", + "type": "Token" + }, + { + "name": "openParenthesis", + "type": "Token" + }, + { + "name": "workers", + "type": "SimpleNameReferenceNode", + "occurrences": "MULTIPLE_SEPARATED" + }, + { + "name": "closeParenthesis", + "type": "Token" + } + ] + }, + { + "name": "SingleReceiveNode", + "base": "Node", + "kind": "SINGLE_RECEIVE", + "attributes": [ + { + "name": "worker", + "type": "SimpleNameReferenceNode" + } + ] } ] } From adf365bc1a7dbad3d7819376d5b09f16294c1e7d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 17 Jan 2024 13:24:34 +0530 Subject: [PATCH 66/97] Improve error message for mismatch in worker send-receive pairing --- .../util/diagnostic/DiagnosticErrorCode.java | 7 +- .../semantics/analyzer/CodeAnalyzer.java | 26 +++- .../src/main/resources/compiler.properties | 6 + .../test/worker/WaitActionsNegativeTest.java | 7 +- .../test/worker/WorkerFailTest.java | 26 +++- .../workers/invalid-worker-send-receive.bal | 113 ++++++++++++++---- 6 files changed, 153 insertions(+), 32 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index d73d74bd11da..f187da6475b6 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -119,8 +119,8 @@ public enum DiagnosticErrorCode implements DiagnosticCode { WORKER_SEND_RECEIVE_PARAMETER_COUNT_MISMATCH("BCE2082", "worker.send.receive.parameter.count.mismatch"), INVALID_WORKER_INTERACTION("BCE2083", "worker.invalid.worker.interaction"), WORKER_INTERACTIONS_ONLY_ALLOWED_BETWEEN_PEERS("BCE2084", "worker.interactions.only.allowed.between.peers"), - STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE2085", "stream.receive.action.not.yet.supported"), - // VACANT_ERROR("BCE2086", ""), + INVALID_WORKER_SEND_NO_MATCHING_WORKER_RECEIVE("BCE2085", "invalid.worker.send.no.matching.worker.receive"), + INVALID_WORKER_RECEIVE_NO_MATCHING_WORKER_SEND("BCE2086", "invalid.worker.receive.no.matching.worker.send"), EXPLICIT_WORKER_CANNOT_BE_DEFAULT("BCE2087", "explicit.worker.cannot.be.default"), INVALID_MULTIPLE_FORK_JOIN_SEND("BCE2088", "worker.multiple.fork.join.send"), INCOMPATIBLE_TYPE_REFERENCE("BCE2089", "incompatible.type.reference"), @@ -815,7 +815,8 @@ public enum DiagnosticErrorCode implements DiagnosticCode { "cannot.use.alternate.wait.action.within.multiple.wait.action"), EXPRESSION_OF_FUTURE_TYPE_EXPECTED("BCE4057", "future.expression.expected"), INSTANTIATION_ERROR("BCE4058", "instantiation.error"), - INVALID_BINDING_PATTERN_IN_ON_FAIL("BCE4059", "invalid.binding.pattern.in.on.fail") + INVALID_BINDING_PATTERN_IN_ON_FAIL("BCE4059", "invalid.binding.pattern.in.on.fail"), + STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE4060", "stream.receive.action.not.yet.supported") ; private String diagnosticId; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 5f706643c02e..091e009e664f 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -3667,6 +3667,13 @@ private static boolean isWorkerSyncSend(BLangNode action) { return action.getKind() == NodeKind.WORKER_SYNC_SEND; } + private static boolean isWorkerSendOrReceive(BLangNode action) { + return switch (action.getKind()) { + case WORKER_ASYNC_SEND, WORKER_SYNC_SEND, WORKER_RECEIVE -> true; + default -> false; + }; + } + private static boolean isWaitAction(BLangNode action) { return action.getKind() == NodeKind.WAIT_EXPR; } @@ -3900,8 +3907,23 @@ private boolean isWorkerSymbol(BSymbol symbol) { } private void reportInvalidWorkerInteractionDiagnostics(WorkerActionSystem workerActionSystem) { - this.dlog.error(workerActionSystem.getRootPosition(), DiagnosticErrorCode.INVALID_WORKER_INTERACTION, - workerActionSystem.toString()); + boolean hasSendReceivePairingError = false; + for (WorkerActionStateMachine worker : workerActionSystem.finshedWorkers) { + for (BLangNode action : worker.actions) { + if (isWorkerSendOrReceive(action) && ((BLangWorkerSendReceiveExpr) action).getChannel() == null) { + hasSendReceivePairingError = true; + DiagnosticErrorCode errorCode = action.getKind() == NodeKind.WORKER_RECEIVE ? + DiagnosticErrorCode.INVALID_WORKER_RECEIVE_NO_MATCHING_WORKER_SEND : + DiagnosticErrorCode.INVALID_WORKER_SEND_NO_MATCHING_WORKER_RECEIVE; + dlog.error(action.pos, errorCode); + } + } + } + + if (!hasSendReceivePairingError) { + this.dlog.error(workerActionSystem.getRootPosition(), DiagnosticErrorCode.INVALID_WORKER_INTERACTION, + workerActionSystem.toString()); + } } private void validateWorkerActionParameters(BLangWorkerSendReceiveExpr send, BLangWorkerReceive receive) { diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 12871b613adb..acd4b097ceca 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -453,6 +453,12 @@ error.invalid.wait.future.expr.mapping.constructors=\ error.invalid.wait.future.expr.actions=\ ''wait'' cannot be used with actions +error.invalid.worker.send.no.matching.worker.receive=\ + invalid worker send, no matching worker receive + +error.invalid.worker.receive.no.matching.worker.send=\ + invalid worker receive, no matching worker send + error.invalid.send.expr=\ expected an expression, but found an action diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java index 559420eaa2a2..c56b0e5d6c61 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WaitActionsNegativeTest.java @@ -197,12 +197,13 @@ public void testWaitCausingADeadlockNegative() { String msg = "worker send/receive interactions are invalid; worker(s) cannot move onwards from the state: '%s'"; BAssertUtil.validateError(result, index++, String.format(msg, "[wait v, wait w, FINISHED]"), 19, 14); BAssertUtil.validateError(result, index++, String.format(msg, "[wait v, wait w, wait x, FINISHED]"), 29, 14); - BAssertUtil.validateError(result, index++, String.format(msg, "[wait w2, <- w, wait w1, FINISHED]"), 43, 14); + BAssertUtil.validateError(result, index++, "invalid worker send, no matching worker receive", 46, 9); + BAssertUtil.validateError(result, index++, "invalid worker receive, no matching worker send", 50, 17); BAssertUtil.validateError(result, index++, String.format(msg, "[wait v, wait w, wait x, FINISHED]"), 61, 18); BAssertUtil.validateError(result, index++, String.format(msg, "[wait vi, wait wi, wait xi, FINISHED, FINISHED]"), 78, 23); - BAssertUtil.validateError(result, index++, - String.format(msg, "[11 -> w3, FINISHED, FINISHED, wait {w1,w2,w3}]"), 94, 15); + BAssertUtil.validateError(result, index++, "invalid worker send, no matching worker receive", 95, 9); + BAssertUtil.validateError(result, index++, "invalid worker receive, no matching worker send", 96, 20); Assert.assertEquals(result.getErrorCount(), index); } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 948df9f6cb10..c2db0f97e817 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -32,11 +32,29 @@ public class WorkerFailTest { @Test - public void invalidWorkerSendReceive() { + public void testMismatchInSendReceivePairing() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-worker-send-receive.bal"); - String message = Arrays.toString(result.getDiagnostics()); - Assert.assertEquals(result.getErrorCount(), 1); - Assert.assertTrue(message.contains(" interactions are invalid"), message); + String invalidSendErrMsg = "invalid worker send, no matching worker receive"; + String invalidReceiveErrMsg = "invalid worker receive, no matching worker send"; + int index = 0; + validateError(result, index++, invalidSendErrMsg, 3, 9); + validateError(result, index++, invalidSendErrMsg, 7, 9); + validateError(result, index++, invalidReceiveErrMsg, 13, 17); + validateError(result, index++, invalidReceiveErrMsg, 17, 20); + validateError(result, index++, invalidSendErrMsg, 29, 9); + validateError(result, index++, invalidReceiveErrMsg, 44, 21); + validateError(result, index++, invalidReceiveErrMsg, 54, 34); + validateError(result, index++, invalidReceiveErrMsg, 67, 20); + validateError(result, index++, invalidReceiveErrMsg, 67, 27); + validateError(result, index++, invalidReceiveErrMsg, 67, 34); + validateError(result, index++, invalidSendErrMsg, 71, 9); + validateWarning(result, index++, "unused variable 'b'", 79, 13); + validateError(result, index++, invalidReceiveErrMsg, 81, 17); + validateWarning(result, index++, "unused variable 'b'", 85, 13); + validateWarning(result, index++, "unused variable 'a'", 90, 13); + validateWarning(result, index++, "unused variable 'b'", 91, 13); + Assert.assertEquals(result.getErrorCount(), index - 4); + Assert.assertEquals(result.getWarnCount(), 4); } @Test diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal index b1d3899311dd..7721b789372a 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal @@ -1,22 +1,95 @@ +function case1() { + worker w1 { + 20 -> w2; + } + + worker w2 { + "xxx" -> w1; + } +} + +function case2() { + worker w1 { + int _ = <- w2; + } + + worker w2 { + string _ = <- w1; + } +} + +function case3() { + boolean foo = true; + worker w1 { + if foo { + 2 -> w2; + } else { + 3 -> w2; + } + 4 -> w2; + } + + worker w2 returns error? { + _ = check <- w1; + _ = check <- w1; + } +} + +function case4() { + worker w1 { + "xxx" -> w2; + } + + worker w2 { + _ = <- w1 | w1; + } +} + +function case5() { + worker w1 { + "xxx" -> w2; + } + + worker w2 { + _ = <- {a: w1, b: w3, c: w3}; + } + + worker w3 { + "yyy" -> w2; + } +} -function invalidWorkerSendReceive() { +function case6() { + worker w1 { + } + + worker w2 { + _ = <- {a: w1, b: w3, c: w3}; + } + + worker w3 { + "yyy" -> w2; + } +} + +function case7() { fork { - worker w1 { - int a = 5; - int b = 0; - a -> w2; - b = <- w3; - } - worker w2 { - int a = 0; - int b = 15; - a = <- w1; - a -> w3; - } - worker w3 { - int a = 0; - int b = 15; - a = <- w2; - } - } -} \ No newline at end of file + worker w1 { + int a = 5; + int b = 0; + a -> w2; + b = <- w3; + } + worker w2 { + int a = 0; + int b = 15; + a = <- w1; + a -> w3; + } + worker w3 { + int a = 0; + int b = 15; + a = <- w2; + } + } +} From 5752c5938fc87f8b2aaa36d338fb1270ac687450 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 24 Jan 2024 07:36:43 +0530 Subject: [PATCH 67/97] Rename `error:NoMessageError` to `error:NoMessage` --- .../ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java | 2 +- langlib/lang.error/src/main/ballerina/error.bal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 091e009e664f..9340a8aeac3e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -285,7 +285,7 @@ public class CodeAnalyzer extends SimpleBLangNodeAnalyzer { private static final CompilerContext.Key CODE_ANALYZER_KEY = new CompilerContext.Key<>(); - private static final String NO_MESSAGE_ERROR_TYPE = "NoMessageError"; + private static final String NO_MESSAGE_ERROR_TYPE = "NoMessage"; private final SymbolResolver symResolver; private final SymbolTable symTable; diff --git a/langlib/lang.error/src/main/ballerina/error.bal b/langlib/lang.error/src/main/ballerina/error.bal index 95a8fb21a9a3..3d6dc9740585 100644 --- a/langlib/lang.error/src/main/ballerina/error.bal +++ b/langlib/lang.error/src/main/ballerina/error.bal @@ -17,7 +17,7 @@ import ballerina/jballerina.java; # Error type representing the no message error in worker interactions. -public type NoMessageError distinct error; +public type NoMessage distinct error; # Type for value that can be cloned. # This is the same as in lang.value, but is copied here to avoid a dependency. From 632175d0c682577de1c7cf926c6d4ea447ad2fe0 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Fri, 26 Jan 2024 15:17:00 +0530 Subject: [PATCH 68/97] Remove channels after message passing --- .../internal/scheduling/WDChannels.java | 13 +++++++++++++ .../scheduling/WorkerDataChannel.java | 16 +++++++++++++++- .../compiler/bir/codegen/JvmSignatures.java | 1 + .../bir/codegen/JvmTerminatorGen.java | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 3ed43d6c4938..4bb76121e388 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -91,6 +91,7 @@ private Object clearResultCache(Strand strand, ReceiveField[] receiveFields) { BMap map = strand.workerReceiveMap; strand.workerReceiveMap = null; strand.channelCount = 0; + strand.setState(State.RUNNABLE); return map; } return null; @@ -142,6 +143,8 @@ private Object processResulAndError(Strand strand, String[] channels, Object res } else if (!allChannelsClosed) { strand.setState(BLOCK_AND_YIELD); } + } else { + strand.setState(State.RUNNABLE); } return getResultValue(result); } @@ -150,6 +153,16 @@ private void closeChannels(String[] channels) { for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); channel.close(); + channel.setRemovable(); + } + } + + public synchronized void removeCompletedChannels(String channelName) { + if (this.wDChannels != null) { + WorkerDataChannel channel = this.wDChannels.get(channelName); + if (channel != null && (channel.callCount == 2 || channel.isRemovable)) { + this.wDChannels.remove(channelName); + } } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 1a6a9a39250e..ed74b5650577 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -47,7 +47,9 @@ public class WorkerDataChannel { private final Lock channelLock; - private String chnlName; + protected String chnlName; + protected int callCount = 0; + protected boolean isRemovable; @SuppressWarnings("rawtypes") private final Queue channel = new LinkedList<>(); @@ -94,6 +96,10 @@ public State getState() { return this.state; } + public void setRemovable() { + this.isRemovable = true; + } + public enum State { OPEN, AUTO_CLOSED, CLOSED } @@ -101,6 +107,7 @@ public enum State { @SuppressWarnings("rawtypes") public void sendData(Object data, Strand sender) { if (isClosed()) { + callCount++; return; } try { @@ -111,6 +118,7 @@ public void sendData(Object data, Strand sender) { this.receiver.scheduler.unblockStrand(this.receiver); this.receiver = null; } + callCount++; } finally { releaseChannelLock(); } @@ -163,14 +171,17 @@ public Object syncSendData(Object data, Strand strand) throws Throwable { reschedule = false; if (this.panic != null && this.channel.peek() != null) { Throwable e = this.panic; + callCount++; throw e; } else if (this.error != null && this.channel.peek() != null) { ErrorValue ret = this.error; this.waitingSender = null; + callCount++; return ret; } // sync send done + callCount++; return null; } finally { releaseChannelLock(); @@ -213,12 +224,15 @@ public Object tryTakeData(Strand strand, boolean isMultiple) throws Throwable { this.flushSender.waitingStrand.flushDetail.flushLock.unlock(); this.flushSender = null; } + callCount++; return isMultiple ? result : result.value; } else if (this.panic != null && this.senderCounter == this.receiverCounter + 1) { this.receiverCounter++; + callCount++; throw this.panic; } else if (this.error != null && this.senderCounter == this.receiverCounter + 1) { this.receiverCounter++; + callCount++; return error; } else { this.receiver = strand; 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 8674ca3a5257..16178778cdf6 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 @@ -264,6 +264,7 @@ public class JvmSignatures { public static final String GET_TYPE_REF_TYPE_IMPL = "L" + TYPE_REF_TYPE_IMPL + ";"; public static final String GET_WD_CHANNELS = "L" + WD_CHANNELS + ";"; public static final String GET_WORKER_DATA_CHANNEL = "(L" + STRING_VALUE + ";)L" + WORKER_DATA_CHANNEL + ";"; + public static final String REMOVE_WORKER_DATA_CHANNEL = "(L" + STRING_VALUE + ";)V"; public static final String GET_XML = "L" + XML_VALUE + ";"; public static final String HANDLE_CHANNEL_ERROR = "([L" + CHANNEL_DETAILS + ";L" + ERROR_VALUE + ";)V"; public static final String HANDLE_ERROR_RETURN = "(L" + OBJECT + ";)V"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index e2b6e689d7a1..66b017f69109 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -45,6 +45,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.BPackageSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.Symbols; import org.wso2.ballerinalang.compiler.semantics.model.types.BFutureType; import org.wso2.ballerinalang.compiler.semantics.model.types.BInvokableType; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; @@ -52,6 +53,7 @@ import org.wso2.ballerinalang.compiler.util.Name; import org.wso2.ballerinalang.compiler.util.TypeTags; import org.wso2.ballerinalang.compiler.util.Unifier; +import org.wso2.ballerinalang.util.Flags; import java.util.ArrayList; import java.util.Arrays; @@ -191,6 +193,7 @@ import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.MULTIPLE_RECEIVE_CALL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PANIC_IF_IN_LOCK; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.PASS_OBJECT_RETURN_OBJECT; +import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.REMOVE_WORKER_DATA_CHANNEL; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.RETURN_OBJECT; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SCHEDULE_FUNCTION; import static org.wso2.ballerinalang.compiler.bir.codegen.JvmSignatures.SCHEDULE_LOCAL; @@ -1414,6 +1417,22 @@ private void genResourcePathArgs(List pathArgs) { public void genReturnTerm(int returnVarRefIndex, BIRNode.BIRFunction func, int invocationVarIndex, int localVarOffset) { + if (func.workerChannels != null) { + Arrays.stream(func.workerChannels).distinct().forEach(channel -> { + this.mv.visitVarInsn(ALOAD, localVarOffset); + if (Symbols.isFlagOn(func.flags, Flags.WORKER)) { + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); + } + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); + this.mv.visitVarInsn(ILOAD, invocationVarIndex); + this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, + new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, + HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), channel.name + + START_OF_HEADING_WITH_SEMICOLON); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "removeCompletedChannels", + REMOVE_WORKER_DATA_CHANNEL, false); + }); + } BType bType = unifier.build(func.type.retType); generateReturnTermFromType(returnVarRefIndex, bType, func, invocationVarIndex, localVarOffset); } From 00bd0cf1b0b96e687de994eb8526762669ddbd81 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 29 Jan 2024 11:37:48 +0530 Subject: [PATCH 69/97] Remove channel details after message passing --- .../io/ballerina/runtime/internal/scheduling/WDChannels.java | 4 +++- .../ballerinalang/compiler/bir/codegen/JvmSignatures.java | 2 +- .../ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 4bb76121e388..7490974b3f74 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -23,6 +23,7 @@ import io.ballerina.runtime.api.values.BMap; import io.ballerina.runtime.api.values.BString; import io.ballerina.runtime.internal.ErrorUtils; +import io.ballerina.runtime.internal.values.ChannelDetails; import io.ballerina.runtime.internal.values.ErrorValue; import java.util.ArrayList; @@ -157,11 +158,12 @@ private void closeChannels(String[] channels) { } } - public synchronized void removeCompletedChannels(String channelName) { + public synchronized void removeCompletedChannels(Strand strand, String channelName) { if (this.wDChannels != null) { WorkerDataChannel channel = this.wDChannels.get(channelName); if (channel != null && (channel.callCount == 2 || channel.isRemovable)) { this.wDChannels.remove(channelName); + strand.channelDetails.remove(new ChannelDetails(channelName, true, false)); } } } 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 16178778cdf6..1935d4c9126d 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 @@ -264,7 +264,7 @@ public class JvmSignatures { public static final String GET_TYPE_REF_TYPE_IMPL = "L" + TYPE_REF_TYPE_IMPL + ";"; public static final String GET_WD_CHANNELS = "L" + WD_CHANNELS + ";"; public static final String GET_WORKER_DATA_CHANNEL = "(L" + STRING_VALUE + ";)L" + WORKER_DATA_CHANNEL + ";"; - public static final String REMOVE_WORKER_DATA_CHANNEL = "(L" + STRING_VALUE + ";)V"; + public static final String REMOVE_WORKER_DATA_CHANNEL = "(L" + STRAND_CLASS + ";L" + STRING_VALUE + ";)V"; public static final String GET_XML = "L" + XML_VALUE + ";"; public static final String HANDLE_CHANNEL_ERROR = "([L" + CHANNEL_DETAILS + ";L" + ERROR_VALUE + ";)V"; public static final String HANDLE_ERROR_RETURN = "(L" + OBJECT + ";)V"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 66b017f69109..f2baa6924ea4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -1424,6 +1424,7 @@ public void genReturnTerm(int returnVarRefIndex, BIRNode.BIRFunction func, int i this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); } this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); + this.mv.visitVarInsn(ALOAD, localVarOffset); this.mv.visitVarInsn(ILOAD, invocationVarIndex); this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, From 2a6837ae2afaab1e19b08af2bea722e1cb953514 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Sun, 28 Jan 2024 18:41:03 +0530 Subject: [PATCH 70/97] Add `error:NoMessage` iff all receives have it in alternate receive --- .../compiler/desugar/QueryDesugar.java | 1 - .../semantics/analyzer/CodeAnalyzer.java | 122 ++++++++++++------ .../expressions/BLangWorkerAsyncSendExpr.java | 34 +---- .../tree/expressions/BLangWorkerReceive.java | 10 +- .../tree/expressions/BLangWorkerSendExpr.java | 57 ++++++++ .../BLangWorkerSendReceiveExpr.java | 20 +-- .../expressions/BLangWorkerSyncSendExpr.java | 35 +---- .../worker/WorkerAlternateReceiveTest.java | 28 +++- .../workers/workers_alt_receive_negative.bal | 63 +++++++++ 9 files changed, 237 insertions(+), 133 deletions(-) create mode 100644 compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendExpr.java create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java index 90bc4b0202b1..d2c838e4b4e2 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java @@ -2736,7 +2736,6 @@ public void visit(BLangMultipleWorkerReceive multipleWorkerReceive) { @Override public void visit(BLangWorkerReceive workerReceiveNode) { - workerReceiveNode.sendExpression = rewrite(workerReceiveNode.sendExpression); result = workerReceiveNode; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java index 9340a8aeac3e..c5c5eb759a53 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/CodeAnalyzer.java @@ -172,6 +172,7 @@ import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerAsyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerFlushExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerReceive; +import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSendReceiveExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangWorkerSyncSendExpr; import org.wso2.ballerinalang.compiler.tree.expressions.BLangXMLAttribute; @@ -2058,14 +2059,14 @@ public void visit(BLangWorkerAsyncSendExpr asyncSendExpr, AnalyzerData data) { } boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); - asyncSendExpr.sendType = - createAccumulatedErrorTypeForMatchingReceive(asyncSendExpr.expr.getBType(), withinIf, data); + setWorkerSendSendTypeDetails(asyncSendExpr, asyncSendExpr.expr.getBType(), withinIf, data); was.addWorkerAction(asyncSendExpr); analyzeExpr(asyncSendExpr.expr, data); validateActionParentNode(asyncSendExpr.pos, asyncSendExpr.expr); } - private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, boolean withinIf, AnalyzerData data) { + private void setWorkerSendSendTypeDetails(BLangWorkerSendExpr workerSendExpr, BType exprType, + boolean withinIf, AnalyzerData data) { Set returnTypesUpToNow = data.returnTypes.peek(); LinkedHashSet returnTypeAndSendType = new LinkedHashSet<>() { { @@ -2082,18 +2083,32 @@ private BType createAccumulatedErrorTypeForMatchingReceive(BType exprType, boole } returnTypeAndSendType.add(exprType); - if (withinIf || hasNonErrorReturn) { + BType sendTypeWithNoMsgIgnored; + if (returnTypeAndSendType.size() > 1) { + sendTypeWithNoMsgIgnored = BUnionType.create(null, returnTypeAndSendType); + } else { + sendTypeWithNoMsgIgnored = exprType; + } + + BType sendType; + boolean noMessagePossible = withinIf || hasNonErrorReturn; + if (noMessagePossible) { // There is a possibility that the send action may not be executed, thus adding NoMessageError type. BSymbol noMsgErrSymbol = symTable.langErrorModuleSymbol.scope. lookup(Names.fromString(NO_MESSAGE_ERROR_TYPE)).symbol; returnTypeAndSendType.add(noMsgErrSymbol.getType()); - } - - if (returnTypeAndSendType.size() > 1) { - return BUnionType.create(null, returnTypeAndSendType); + if (returnTypeAndSendType.size() > 1) { + sendType = BUnionType.create(null, returnTypeAndSendType); + } else { + sendType = exprType; + } } else { - return exprType; + sendType = sendTypeWithNoMsgIgnored; } + + workerSendExpr.sendType = sendType; + workerSendExpr.sendTypeWithNoMsgIgnored = sendTypeWithNoMsgIgnored; + workerSendExpr.noMessagePossible = noMessagePossible; } @Override @@ -2130,14 +2145,14 @@ public void visit(BLangWorkerSyncSendExpr syncSendExpr, AnalyzerData data) { syncSendExpr.setBType(BUnionType.create(null, symTable.nilType, symTable.errorType)); boolean withinIf = !invalidSendPos && withinIf(data.env.enclInvokable.body, data.env.node); - syncSendExpr.sendType = - createAccumulatedErrorTypeForMatchingReceive(syncSendExpr.expr.getBType(), withinIf, data); + setWorkerSendSendTypeDetails(syncSendExpr, syncSendExpr.expr.getBType(), withinIf, data); was.addWorkerAction(syncSendExpr); analyzeExpr(syncSendExpr.expr, data); } @Override public void visit(BLangAlternateWorkerReceive altWorkerReceive, AnalyzerData data) { + data.workerActionSystemStack.peek().alternateWorkerReceives.add(altWorkerReceive); for (BLangWorkerReceive bLangWorkerReceive : altWorkerReceive.getWorkerReceives()) { analyzeExpr(bLangWorkerReceive, data); } @@ -3728,7 +3743,7 @@ private void validateWorkerInteractions(WorkerActionSystem workerActionSystem, A continue; } BLangWorkerReceive receive = (BLangWorkerReceive) otherSM.currentAction(); - BLangWorkerSendReceiveExpr send = (BLangWorkerSendReceiveExpr) currentAction; + BLangWorkerSendExpr send = (BLangWorkerSendExpr) currentAction; validateWorkerActionParameters(send, receive); BLangWorkerSendReceiveExpr.Channel channel = createChannel(workerActionSystem, worker, otherSM); @@ -3756,11 +3771,44 @@ private void validateWorkerInteractions(WorkerActionSystem workerActionSystem, A } } while (systemRunning); - if (!workerActionSystem.everyoneDone()) { + if (workerActionSystem.everyoneDone()) { + // By now, alternative receive corresponding senders have been paired. Hence, doing type-checking here + for (BLangAlternateWorkerReceive alternateWorkerRv : workerActionSystem.alternateWorkerReceives) { + typeCheckAlternateReceive(alternateWorkerRv); + } + } else { this.reportInvalidWorkerInteractionDiagnostics(workerActionSystem); } } + private void typeCheckAlternateReceive(BLangAlternateWorkerReceive altWorkerRv) { + LinkedHashSet altTypes = new LinkedHashSet<>(); + boolean noMessagePossible = true; + + // Result will have error:NoMessage if and only if all receives have it. + for (BLangWorkerReceive workerRv : altWorkerRv.getWorkerReceives()) { + altTypes.add(workerRv.send.sendTypeWithNoMsgIgnored); + if (!workerRv.send.noMessagePossible) { + noMessagePossible = false; + } + } + + if (noMessagePossible) { + BSymbol noMsgErrSymbol = symTable.langErrorModuleSymbol.scope. + lookup(Names.fromString(NO_MESSAGE_ERROR_TYPE)).symbol; + altTypes.add(noMsgErrSymbol.getType()); + } + + BType actualType; + if (altTypes.size() > 1) { + actualType = BUnionType.create(null, altTypes); + } else { + actualType = altTypes.iterator().next(); + } + + types.checkType(altWorkerRv, actualType, altWorkerRv.expectedType); + } + private static BLangWorkerSendReceiveExpr.Channel createChannel(WorkerActionSystem workerActionSystem, WorkerActionStateMachine worker, WorkerActionStateMachine otherSM) { @@ -3926,31 +3974,27 @@ private void reportInvalidWorkerInteractionDiagnostics(WorkerActionSystem worker } } - private void validateWorkerActionParameters(BLangWorkerSendReceiveExpr send, BLangWorkerReceive receive) { - if (isWorkerSyncSend(send)) { - validateWorkerActionParameters((BLangWorkerSyncSendExpr) send, receive); - } else if (isWorkerSend(send)) { - validateWorkerActionParameters((BLangWorkerAsyncSendExpr) send, receive); + private void validateWorkerActionParameters(BLangWorkerSendExpr send, BLangWorkerReceive receive) { + send.receive = receive; + receive.send = send; + + NodeKind parentKind = receive.parent.getKind(); + if (NodeKind.ALTERNATE_WORKER_RECEIVE != receive.parent.getKind()) { + types.checkType(receive, send.sendType, receive.getBType()); + addImplicitCast(send.sendType, receive); } - } - private void validateWorkerActionParameters(BLangWorkerAsyncSendExpr send, BLangWorkerReceive receive) { - send.receive = receive; - types.checkType(send.pos, symTable.nilType, send.expectedType, - DiagnosticErrorCode.INCOMPATIBLE_TYPES); - - types.checkType(receive, send.sendType, receive.getBType()); - addImplicitCast(send.sendType, receive); - NodeKind kind = receive.parent.getKind(); - if (kind == NodeKind.TRAP_EXPR || kind == NodeKind.CHECK_EXPR || kind == NodeKind.CHECK_PANIC_EXPR || - kind == NodeKind.FAIL) { + if (parentKind == NodeKind.TRAP_EXPR || parentKind == NodeKind.CHECK_EXPR || + parentKind == NodeKind.CHECK_PANIC_EXPR || parentKind == NodeKind.FAIL) { typeChecker.checkExpr((BLangExpression) receive.parent, receive.env); } - receive.sendExpression = send.expr; - } - private void validateWorkerActionParameters(BLangWorkerSyncSendExpr send, BLangWorkerReceive receive) { - send.receive = receive; + if (send.getKind() == NodeKind.WORKER_ASYNC_SEND) { + types.checkType(send.pos, symTable.nilType, send.expectedType, + DiagnosticErrorCode.INCOMPATIBLE_TYPES); + return; + } + NodeKind parentNodeKind = send.parent.getKind(); if (parentNodeKind == NodeKind.VARIABLE) { BLangSimpleVariable variable = (BLangSimpleVariable) send.parent; @@ -3972,17 +4016,8 @@ private void validateWorkerActionParameters(BLangWorkerSyncSendExpr send, BLangW dlog.error(send.pos, DiagnosticErrorCode.ASSIGNMENT_REQUIRED, send.workerSymbol); } else { types.checkType(send.pos, receive.matchingSendsError, send.expectedType, - DiagnosticErrorCode.INCOMPATIBLE_TYPES); - } - - types.checkType(receive, send.sendType, receive.getBType()); - - addImplicitCast(send.sendType, receive); - NodeKind kind = receive.parent.getKind(); - if (kind == NodeKind.TRAP_EXPR || kind == NodeKind.CHECK_EXPR || kind == NodeKind.CHECK_PANIC_EXPR) { - typeChecker.checkExpr((BLangExpression) receive.parent, receive.env); + DiagnosticErrorCode.INCOMPATIBLE_TYPES); } - receive.sendExpression = send; } private void addImplicitCast(BType actualType, BLangWorkerReceive receive) { @@ -4108,6 +4143,7 @@ private boolean reportIfDeprecatedUsage(BSymbol constructSymbol, BLangExpression */ private static class WorkerActionSystem { + public final List alternateWorkerReceives = new ArrayList<>(); public List finshedWorkers = new ArrayList<>(); private Stack workerActionStateMachines = new Stack<>(); private Map workerInteractionEnvironments = new IdentityHashMap<>(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java index da4dc4fda60c..b0c07f3d6594 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerAsyncSendExpr.java @@ -17,13 +17,7 @@ */ package org.wso2.ballerinalang.compiler.tree.expressions; -import org.ballerinalang.model.tree.IdentifierNode; import org.ballerinalang.model.tree.NodeKind; -import org.ballerinalang.model.tree.expressions.WorkerSendExpressionNode; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; -import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; import org.wso2.ballerinalang.compiler.tree.BLangNodeAnalyzer; import org.wso2.ballerinalang.compiler.tree.BLangNodeTransformer; import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; @@ -33,33 +27,7 @@ * * @since 0.94 */ -public class BLangWorkerAsyncSendExpr extends BLangWorkerSendReceiveExpr implements WorkerSendExpressionNode { - - // BLangNodes - public BLangExpression expr; - public BLangIdentifier workerIdentifier; - - // Semantic Data - public BLangWorkerReceive receive; - public SymbolEnv env; - public BSymbol workerSymbol; - public BType workerType; - public BType sendType; - - @Override - public BLangExpression getExpression() { - return expr; - } - - @Override - public BLangIdentifier getWorkerName() { - return workerIdentifier; - } - - @Override - public void setWorkerName(IdentifierNode identifierNode) { - this.workerIdentifier = (BLangIdentifier) identifierNode; - } +public class BLangWorkerAsyncSendExpr extends BLangWorkerSendExpr { @Override public NodeKind getKind() { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java index d62e6a23e530..b078a5c7a5c3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerReceive.java @@ -20,8 +20,6 @@ import org.ballerinalang.model.tree.IdentifierNode; import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.tree.statements.WorkerReceiveNode; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; import org.wso2.ballerinalang.compiler.semantics.model.types.BType; import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; import org.wso2.ballerinalang.compiler.tree.BLangNodeAnalyzer; @@ -35,14 +33,8 @@ */ public class BLangWorkerReceive extends BLangWorkerSendReceiveExpr implements WorkerReceiveNode { - // BLangNodes - public BLangIdentifier workerIdentifier; - // Semantic Data - public BLangExpression sendExpression; // TODO: #AST_CLEAN - No Transformer ? - public BSymbol workerSymbol; // TODO: 22/11/23 Seems no usage. Clean. - public SymbolEnv env; - public BType workerType; + public BLangWorkerSendExpr send; public BType matchingSendsError; @Override diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendExpr.java new file mode 100644 index 000000000000..ac912998943b --- /dev/null +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendExpr.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * + * 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 + * + * 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.wso2.ballerinalang.compiler.tree.expressions; + +import org.ballerinalang.model.tree.IdentifierNode; +import org.ballerinalang.model.tree.expressions.WorkerSendExpressionNode; +import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; + +/** + * Represents commons in worker async-send and sync-send. + * + * @since 2201.9.0 + */ +public abstract class BLangWorkerSendExpr extends BLangWorkerSendReceiveExpr implements WorkerSendExpressionNode { + + // BLangNodes + public BLangExpression expr; + + // Semantic Data + public BLangWorkerReceive receive; + public BType sendType; + + // For alternate receive type inference + public boolean noMessagePossible; + public BType sendTypeWithNoMsgIgnored; + + @Override + public BLangExpression getExpression() { + return expr; + } + + @Override + public BLangIdentifier getWorkerName() { + return workerIdentifier; + } + + @Override + public void setWorkerName(IdentifierNode identifierNode) { + this.workerIdentifier = (BLangIdentifier) identifierNode; + } +} diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java index 81d80d5590e8..23ec0f31a717 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java @@ -17,6 +17,11 @@ */ package org.wso2.ballerinalang.compiler.tree.expressions; +import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; +import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; +import org.wso2.ballerinalang.compiler.semantics.model.types.BType; +import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; + /** * Represents commons in worker async-send, sync-send and single-receive. * @@ -24,6 +29,10 @@ */ public abstract class BLangWorkerSendReceiveExpr extends BLangExpression { + public SymbolEnv env; + public BSymbol workerSymbol; + public BType workerType; + public BLangIdentifier workerIdentifier; private Channel channel; public Channel getChannel() { @@ -34,16 +43,7 @@ public void setChannel(Channel channel) { this.channel = channel; } - public static final class Channel { - public final String sender; - public final String receiver; - public final int eventIndex; - - public Channel(String sender, String receiver, int eventIndex) { - this.sender = sender; - this.receiver = receiver; - this.eventIndex = eventIndex; - } + public record Channel(String sender, String receiver, int eventIndex) { public String workerPairId() { return workerPairId(sender, receiver); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java index 4362be409b54..16a0b9e32fbc 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSyncSendExpr.java @@ -17,14 +17,7 @@ */ package org.wso2.ballerinalang.compiler.tree.expressions; -import org.ballerinalang.model.tree.IdentifierNode; import org.ballerinalang.model.tree.NodeKind; -import org.ballerinalang.model.tree.expressions.ExpressionNode; -import org.ballerinalang.model.tree.expressions.WorkerSendExpressionNode; -import org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv; -import org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol; -import org.wso2.ballerinalang.compiler.semantics.model.types.BType; -import org.wso2.ballerinalang.compiler.tree.BLangIdentifier; import org.wso2.ballerinalang.compiler.tree.BLangNodeAnalyzer; import org.wso2.ballerinalang.compiler.tree.BLangNodeTransformer; import org.wso2.ballerinalang.compiler.tree.BLangNodeVisitor; @@ -34,18 +27,7 @@ * * @since 0.985 */ -public class BLangWorkerSyncSendExpr extends BLangWorkerSendReceiveExpr implements WorkerSendExpressionNode { - - // BLangNodes - public BLangIdentifier workerIdentifier; - public BLangExpression expr; - - // Semantic Data - public BLangWorkerReceive receive; - public BSymbol workerSymbol; - public SymbolEnv env; - public BType workerType; - public BType sendType; +public class BLangWorkerSyncSendExpr extends BLangWorkerSendExpr { @Override public NodeKind getKind() { @@ -67,21 +49,6 @@ public R apply(BLangNodeTransformer modifier, T props) { return modifier.transform(this, props); } - @Override - public ExpressionNode getExpression() { - return expr; - } - - @Override - public IdentifierNode getWorkerName() { - return workerIdentifier; - } - - @Override - public void setWorkerName(IdentifierNode identifierNode) { - this.workerIdentifier = (BLangIdentifier) identifierNode; - } - public String toActionString() { return this.expr + " ->> " + this.workerIdentifier; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index 09b07b7b64d0..de8e2de4d5ec 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -15,9 +15,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.ballerinalang.test.worker; +import org.ballerinalang.test.BAssertUtil; import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; @@ -32,12 +32,13 @@ */ public class WorkerAlternateReceiveTest { - private CompileResult result; + private CompileResult result, negativeResult; @BeforeClass public void setup() { - this.result = BCompileUtil.compile("test-src/workers/workers_alt_receive.bal"); + result = BCompileUtil.compile("test-src/workers/workers_alt_receive.bal"); Assert.assertEquals(result.getErrorCount(), 0); + negativeResult = BCompileUtil.compile("test-src/workers/workers_alt_receive_negative.bal"); } @Test(dataProvider = "functionProvider") @@ -66,8 +67,29 @@ public static String[] functionProvider() { }; } + @Test(description = "Test negative scenarios of alternate receive action.") + public void testAltWorkerReceiveNegative() { + int index = 0; + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 53, + 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + + "(int|ballerina/lang.error:0.0.0:NoMessage)'", 54, 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 55, + 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 56, + 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 57, + 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + + "(decimal|string|int|boolean)'", 58, 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + + "(decimal|string|int|boolean|ballerina/lang.error:0.0.0:NoMessage)'", 59, 20); + Assert.assertEquals(negativeResult.getErrorCount(), index); + } + @AfterClass public void tearDown() { result = null; + negativeResult = null; } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal new file mode 100644 index 000000000000..66be34e4f346 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal @@ -0,0 +1,63 @@ +function testAltReceiveNoMessageErrorType(boolean b) { + worker w1 { + // case 1 + 1 -> w2; + 2 -> w2; + + // case 2 + if b { + 3 -> w2; + 4 -> w2; + } + + // case 3 + if b { + 5 -> w2; + } + 6 -> w2; + + // case 4 + 7 -> w2; + if b { + 8 -> w2; + } + + // case 5 + 9 -> w2; + 10 -> w2; + if b { + 11 -> w2; + } + 12 -> w2; + + // case 5 + 13.3d -> w2; + if b { + "xx" -> w2; + 14 -> w2; + true -> w2; + } + + // case 6 + if !b { + 13.3d -> w2; + } + if b { + "xx" -> w2; + 14 -> w2; + true -> w2; + } + } + + worker w2 { + string _ = <- w1|w1; // found 'int' + string _ = <- w1|w1; // found 'int|error:NoMessage' + string _ = <- w1|w1; // found 'int' + string _ = <- w1|w1; // found 'int' + string _ = <- w1|w1|w1|w1; // found 'int' + string _ = <- w1|w1|w1|w1; // found 'decimal|string|int|boolean' + string _ = <- w1|w1|w1|w1; // found 'decimal|string|int|boolean|error:NoMessage' + } + + _ = wait {a: w1, b: w2}; +} From d4b7c159ec72cc961a8af980b23b82174c558ece Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:42:32 +0530 Subject: [PATCH 71/97] Refactor alternate receive type checking test --- .../test/worker/WorkerAlternateReceiveTest.java | 9 ++++----- ..._negative.bal => alternate_receive_type_checking.bal} | 0 2 files changed, 4 insertions(+), 5 deletions(-) rename tests/jballerina-unit-test/src/test/resources/test-src/workers/{workers_alt_receive_negative.bal => alternate_receive_type_checking.bal} (100%) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index de8e2de4d5ec..b3243ac2624b 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -32,13 +32,12 @@ */ public class WorkerAlternateReceiveTest { - private CompileResult result, negativeResult; + private CompileResult result; @BeforeClass public void setup() { result = BCompileUtil.compile("test-src/workers/workers_alt_receive.bal"); Assert.assertEquals(result.getErrorCount(), 0); - negativeResult = BCompileUtil.compile("test-src/workers/workers_alt_receive_negative.bal"); } @Test(dataProvider = "functionProvider") @@ -67,8 +66,9 @@ public static String[] functionProvider() { }; } - @Test(description = "Test negative scenarios of alternate receive action.") - public void testAltWorkerReceiveNegative() { + @Test(description = "Test alternate receive type checking") + public void testAltWorkerReceiveTypeChecking() { + CompileResult negativeResult = BCompileUtil.compile("test-src/workers/alternate_receive_type_checking.bal"); int index = 0; BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 53, 20); @@ -90,6 +90,5 @@ public void testAltWorkerReceiveNegative() { @AfterClass public void tearDown() { result = null; - negativeResult = null; } } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal similarity index 100% rename from tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive_negative.bal rename to tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal From 9039f513e2921cec78086cf3ac47b0483cef7a18 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 09:59:19 +0530 Subject: [PATCH 72/97] Add multiple receive type checking tests --- .../ballerinalang/test/worker/WorkerTest.java | 28 +++++++ .../multiple-receive-type-checking.bal | 76 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java index 0699890879ab..8ee88881368d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java @@ -350,6 +350,34 @@ public void testMultipleReceiveAction() { BAssertUtil.validateError(result, 0, "multiple receive action not yet supported", 23, 25); } + @Test(description = "Test multiple receive type checking") + public void testMultipleWorkerReceiveTypeChecking() { + CompileResult negativeResult = BCompileUtil.compile("test-src/workers/multiple-receive-type-checking.bal"); + int index = 0; + BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 11, 24); + BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 22, 24); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in " + + "type 'int'", 39, 17); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " 'record {| int c; int a; int b; |}'", 41, 45); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " 'record {| |} & readonly'", 46, 25); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " 'ABCRecord'", 51, 23); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " '(string|record {| int a; int b; int c; anydata...; |}|int)'", 56, 54); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " '(string|boolean|int)'", 57, 32); + BAssertUtil.validateError(negativeResult, index++, "ambiguous type '(map|record {| int a; int b; anydata" + + "...; |})'", 58, 45); + BAssertUtil.validateError(negativeResult, index++, "ambiguous type '(map|record {| int...; |})'", 59, 42); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " '(int|record {| int a; int c; anydata...; |})'", 61, 40); + BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + + " 'record {| readonly int a; readonly int c; |} & readonly'", 69, 49); + Assert.assertEquals(negativeResult.getErrorCount(), index); + } + @AfterClass public void tearDown() { result = null; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal new file mode 100644 index 000000000000..35cd70f4878d --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal @@ -0,0 +1,76 @@ +public function testMultipleReceiveDuplicateKey1() { + worker w1 { + 50 -> w3; + } + + worker w2 { + 100 -> w3; + } + + worker w3 { + _ = <- {a: w1, a: w2}; // error: duplicate key + } +} + +public function testMultipleReceiveDuplicateKey2() { + worker w1 { + 50 -> w2; + 100 -> w2; + } + + worker w2 { + _ = <- {a: w1, a: w1}; // error: duplicate key + } +} + +type MapOfInt map; + +type IntType int; + +type MapOfInt2 map; + +type ABRecord record {|int a; int b;|}; + +type ABCRecord record {|int a; int b; string c;|}; + +public function testMultipleReceiveTypeChecking1() { + worker w2 { + // Non-union cases + int _ = <- {a: w1, b: w1}; // error: incompatible type + map _ = <- {a: w1, b: w1}; // OK + record {|int c; int a; int b;|} _ = <- {a: w1, b: w1}; // error: incompatible type + record {|int c?; int a; int b;|} _ = <- {a: w1, b: w1}; // OK + record {|int a; int b;|} _ = <- {a: w1, b: w1}; // OK + record {|int a; int b; int...;|} _ = <- {a: w1, b: w1}; // OK + record {|int...;|} _ = <- {a: w1, b: w1}; // OK + record {||} _ = <- {a: w1, b: w1}; // error: incompatible type + record {} _ = <- {a: w1, b: w1}; // OK + MapOfInt _ = <- {a: w1, b: w1}; // OK + MapOfInt2 _ = <- {a: w1, b: w1}; // OK + ABRecord _ = <- {a: w1, b: w1}; // OK + ABCRecord _ = <- {a: w1, b: w1}; // error: incompatible type + + // Union cases + string|int|map _ = <- {a: w1, b: w1}; // OK + string|record {int a; int b;}|int _ = <- {a: w1, b: w1}; // OK + string|record {int a; int b; int c;}|int _ = <- {a: w1, b: w1}; // error: incompatible type + string|boolean|int _ = <- {a: w1, b: w1}; // error: incompatible type + map|record {int a; int b;} _ = <- {a: w1, b: w1}; // error: ambiguous type + map|record {|int ...;|} _ = <- {a: w1, b: w1}; // error: ambiguous type + map|record {int a; int c;} _ = <- {a: w1, b: w1}; // OK + int|record {int a; int c;} _ = <- {a: w1, b: w1}; // error: incompatible type + + // Special cases + readonly r = <- {a: w1, b: w1}; // OK + json _ = <- {a: w1, b: w1}; // OK + anydata _ = <- {a: w1, b: w1}; // OK + any _ = <- {a: w1, b: w1}; // OK + record {|int a; int b;|} & readonly _ = <- {a: w1, b: w1}; // OK + record {|int a; int c;|} & readonly _ = <- {a: w1, b: w1}; // error: incompatible type + } + + worker w1 { + 1 ->> w2; + 2 ->> w2; + } +} From 4e3050e6c406c3c7abe9312750532e6cd951edb3 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:06:47 +0530 Subject: [PATCH 73/97] Add test for worker send receive allowed positions --- .../test/worker/WorkerFailTest.java | 21 ++++ .../send-receive-allowed-positions.bal | 107 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index c2db0f97e817..1f4a931ada8e 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -31,6 +31,27 @@ */ public class WorkerFailTest { + @Test + public void testSendReceiveAllowedSyntacticPositions() { + CompileResult result = BCompileUtil.compile("test-src/workers/send-receive-allowed-positions.bal"); + String sendNotAllowedError = "worker send statement position not supported yet, " + + "must be a top level statement in a worker"; + String receiveNotAllowedError = "invalid worker receive statement position, " + + "must be a top level statement in a worker"; + int index = 0; + validateError(result, index++, sendNotAllowedError, 4, 13); + validateError(result, index++, sendNotAllowedError, 8, 13); + validateError(result, index++, "using send action within the lock statement is not allowed to prevent " + + "possible deadlocks", 12, 13); + validateError(result, index++, receiveNotAllowedError, 50, 17); + validateError(result, index++, receiveNotAllowedError, 54, 17); + validateError(result, index++, "using receive action within the lock statement is not allowed to prevent " + + "possible deadlocks", 58, 17); + validateError(result, index++, receiveNotAllowedError, 63, 15); + validateError(result, index++, receiveNotAllowedError, 65, 21); + Assert.assertEquals(result.getErrorCount(), index); + } + @Test public void testMismatchInSendReceivePairing() { CompileResult result = BCompileUtil.compile("test-src/workers/invalid-worker-send-receive.bal"); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal new file mode 100644 index 000000000000..29104222c54e --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal @@ -0,0 +1,107 @@ +// Copyright (c) 2024 WSO2 LLC. +// +// 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 +// +// 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. + +public function testSendAllowedLocations(boolean b) returns error? { + worker w1 { + foreach var i in [1, 2, 3] { + i -> function; // error: position not allowed + } + + while b { + 119 -> function; // error: position not allowed + } + + lock { + 120 -> function; // error: position not allowed + } + + 1 -> function; // OK + if b { + 2 -> function; // OK + if b { + 3 -> function; // OK + } + } + () _ = 4 -> function; // OK + () _ = (4 -> function); // OK + do { + 5 -> function; // OK + } + { + 5 -> function; // OK + } + } on fail { + 6 -> function; // OK + } + + _ = <- w1; + _ = check <- w1; + _ = check <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; + _ = <- w1; +} + +public function testReceiveAllowedLocations(boolean b) returns error? { + worker w1 { + foreach int _ in [1, 2, 3] { + _ = <- function; // error: position not allowed + } + + while b { + _ = <- function; // error: position not allowed + } + + lock { + _ = <- function; // error: position not allowed + } + + _ = <- function; // OK + if b { + _ = <- function; // error: position not allowed + if b { + _ = <- function; // error: position not allowed + } + } + _ = <- function; // OK + _ = (<- function); // OK + do { + _ = <- function; // OK + } + { + _ = <- function; // OK + } + } on fail { + _ = <- function; // OK + } + + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; + 1 -> w1; +} From 529f9784ee661de61c093cf4e91b1eaa0ca38e96 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:13:14 +0530 Subject: [PATCH 74/97] Refactor worker send receive tests --- .../worker/WorkerAlternateReceiveTest.java | 14 +++--- .../test/worker/WorkerFailTest.java | 50 +++++++++---------- .../ballerinalang/test/worker/WorkerTest.java | 24 ++++----- .../alternate_receive_type_checking.bal | 16 ++++++ .../multiple-receive-type-checking.bal | 16 ++++++ ...-receive.bal => send-receive-mismatch.bal} | 16 ++++++ 6 files changed, 92 insertions(+), 44 deletions(-) rename tests/jballerina-unit-test/src/test/resources/test-src/workers/{invalid-worker-send-receive.bal => send-receive-mismatch.bal} (67%) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index b3243ac2624b..1bf4e2124446 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -70,20 +70,20 @@ public static String[] functionProvider() { public void testAltWorkerReceiveTypeChecking() { CompileResult negativeResult = BCompileUtil.compile("test-src/workers/alternate_receive_type_checking.bal"); int index = 0; - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 53, + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 69, 20); BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + - "(int|ballerina/lang.error:0.0.0:NoMessage)'", 54, 20); - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 55, + "(int|ballerina/lang.error:0.0.0:NoMessage)'", 70, 20); + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 71, 20); - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 56, + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 72, 20); - BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 57, + BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found 'int'", 73, 20); BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + - "(decimal|string|int|boolean)'", 58, 20); + "(decimal|string|int|boolean)'", 74, 20); BAssertUtil.validateError(negativeResult, index++, "incompatible types: expected 'string', found '" + - "(decimal|string|int|boolean|ballerina/lang.error:0.0.0:NoMessage)'", 59, 20); + "(decimal|string|int|boolean|ballerina/lang.error:0.0.0:NoMessage)'", 75, 20); Assert.assertEquals(negativeResult.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index 1f4a931ada8e..fd02b9b0c0de 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -39,41 +39,41 @@ public void testSendReceiveAllowedSyntacticPositions() { String receiveNotAllowedError = "invalid worker receive statement position, " + "must be a top level statement in a worker"; int index = 0; - validateError(result, index++, sendNotAllowedError, 4, 13); - validateError(result, index++, sendNotAllowedError, 8, 13); + validateError(result, index++, sendNotAllowedError, 20, 13); + validateError(result, index++, sendNotAllowedError, 24, 13); validateError(result, index++, "using send action within the lock statement is not allowed to prevent " + - "possible deadlocks", 12, 13); - validateError(result, index++, receiveNotAllowedError, 50, 17); - validateError(result, index++, receiveNotAllowedError, 54, 17); + "possible deadlocks", 28, 13); + validateError(result, index++, receiveNotAllowedError, 66, 17); + validateError(result, index++, receiveNotAllowedError, 70, 17); validateError(result, index++, "using receive action within the lock statement is not allowed to prevent " + - "possible deadlocks", 58, 17); - validateError(result, index++, receiveNotAllowedError, 63, 15); - validateError(result, index++, receiveNotAllowedError, 65, 21); + "possible deadlocks", 74, 17); + validateError(result, index++, receiveNotAllowedError, 79, 15); + validateError(result, index++, receiveNotAllowedError, 81, 21); Assert.assertEquals(result.getErrorCount(), index); } @Test public void testMismatchInSendReceivePairing() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-worker-send-receive.bal"); + CompileResult result = BCompileUtil.compile("test-src/workers/send-receive-mismatch.bal"); String invalidSendErrMsg = "invalid worker send, no matching worker receive"; String invalidReceiveErrMsg = "invalid worker receive, no matching worker send"; int index = 0; - validateError(result, index++, invalidSendErrMsg, 3, 9); - validateError(result, index++, invalidSendErrMsg, 7, 9); - validateError(result, index++, invalidReceiveErrMsg, 13, 17); - validateError(result, index++, invalidReceiveErrMsg, 17, 20); - validateError(result, index++, invalidSendErrMsg, 29, 9); - validateError(result, index++, invalidReceiveErrMsg, 44, 21); - validateError(result, index++, invalidReceiveErrMsg, 54, 34); - validateError(result, index++, invalidReceiveErrMsg, 67, 20); - validateError(result, index++, invalidReceiveErrMsg, 67, 27); - validateError(result, index++, invalidReceiveErrMsg, 67, 34); - validateError(result, index++, invalidSendErrMsg, 71, 9); - validateWarning(result, index++, "unused variable 'b'", 79, 13); - validateError(result, index++, invalidReceiveErrMsg, 81, 17); - validateWarning(result, index++, "unused variable 'b'", 85, 13); - validateWarning(result, index++, "unused variable 'a'", 90, 13); - validateWarning(result, index++, "unused variable 'b'", 91, 13); + validateError(result, index++, invalidSendErrMsg, 19, 9); + validateError(result, index++, invalidSendErrMsg, 23, 9); + validateError(result, index++, invalidReceiveErrMsg, 29, 17); + validateError(result, index++, invalidReceiveErrMsg, 33, 20); + validateError(result, index++, invalidSendErrMsg, 45, 9); + validateError(result, index++, invalidReceiveErrMsg, 60, 21); + validateError(result, index++, invalidReceiveErrMsg, 70, 34); + validateError(result, index++, invalidReceiveErrMsg, 83, 20); + validateError(result, index++, invalidReceiveErrMsg, 83, 27); + validateError(result, index++, invalidReceiveErrMsg, 83, 34); + validateError(result, index++, invalidSendErrMsg, 87, 9); + validateWarning(result, index++, "unused variable 'b'", 95, 13); + validateError(result, index++, invalidReceiveErrMsg, 97, 17); + validateWarning(result, index++, "unused variable 'b'", 101, 13); + validateWarning(result, index++, "unused variable 'a'", 106, 13); + validateWarning(result, index++, "unused variable 'b'", 107, 13); Assert.assertEquals(result.getErrorCount(), index - 4); Assert.assertEquals(result.getWarnCount(), 4); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java index 8ee88881368d..060a3d8d9d1d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerTest.java @@ -354,27 +354,27 @@ public void testMultipleReceiveAction() { public void testMultipleWorkerReceiveTypeChecking() { CompileResult negativeResult = BCompileUtil.compile("test-src/workers/multiple-receive-type-checking.bal"); int index = 0; - BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 11, 24); - BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 22, 24); + BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 27, 24); + BAssertUtil.validateError(negativeResult, index++, "invalid multiple receive: duplicate key 'a'", 38, 24); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in " + - "type 'int'", 39, 17); + "type 'int'", 55, 17); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " 'record {| int c; int a; int b; |}'", 41, 45); + " 'record {| int c; int a; int b; |}'", 57, 45); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " 'record {| |} & readonly'", 46, 25); + " 'record {| |} & readonly'", 62, 25); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " 'ABCRecord'", 51, 23); + " 'ABCRecord'", 67, 23); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " '(string|record {| int a; int b; int c; anydata...; |}|int)'", 56, 54); + " '(string|record {| int a; int b; int c; anydata...; |}|int)'", 72, 54); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " '(string|boolean|int)'", 57, 32); + " '(string|boolean|int)'", 73, 32); BAssertUtil.validateError(negativeResult, index++, "ambiguous type '(map|record {| int a; int b; anydata" + - "...; |})'", 58, 45); - BAssertUtil.validateError(negativeResult, index++, "ambiguous type '(map|record {| int...; |})'", 59, 42); + "...; |})'", 74, 45); + BAssertUtil.validateError(negativeResult, index++, "ambiguous type '(map|record {| int...; |})'", 75, 42); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " '(int|record {| int a; int c; anydata...; |})'", 61, 40); + " '(int|record {| int a; int c; anydata...; |})'", 77, 40); BAssertUtil.validateError(negativeResult, index++, "a type compatible with multiple receive not found in type" + - " 'record {| readonly int a; readonly int c; |} & readonly'", 69, 49); + " 'record {| readonly int a; readonly int c; |} & readonly'", 85, 49); Assert.assertEquals(negativeResult.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal index 66be34e4f346..eb65975495a0 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024 WSO2 LLC. +// +// 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 +// +// 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. + function testAltReceiveNoMessageErrorType(boolean b) { worker w1 { // case 1 diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal index 35cd70f4878d..535ae81fbc3e 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024 WSO2 LLC. +// +// 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 +// +// 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. + public function testMultipleReceiveDuplicateKey1() { worker w1 { 50 -> w3; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal similarity index 67% rename from tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal rename to tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal index 7721b789372a..87d1e5a68ef9 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-worker-send-receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024 WSO2 LLC. +// +// 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 +// +// 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. + function case1() { worker w1 { 20 -> w2; From 25c17f35bb9be27dce20371c37374045658c2361 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:11:53 +0530 Subject: [PATCH 75/97] Add test for worker send receive failure type --- .../test/worker/WorkerFailTest.java | 19 +++- .../workers/invalid-send-with-return.bal | 23 ---- .../workers/send-receive-failure-type.bal | 104 ++++++++++++++++++ 3 files changed, 117 insertions(+), 29 deletions(-) delete mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal create mode 100644 tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index fd02b9b0c0de..dfdca7889d50 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -115,12 +115,19 @@ public void invalidSendInLambda() { Assert.assertTrue(message.contains("undefined worker"), message); } - @Test(enabled = false) // TODO: enable - public void invalidSendWithReturnTest() { - CompileResult result = BCompileUtil.compile("test-src/workers/invalid-send-with-return.bal"); - Assert.assertEquals(result.getErrorCount(), 1); - String message = result.getDiagnostics()[0].message(); - Assert.assertTrue(message.contains("can not be used after a non-error return"), message); + @Test + public void testSendReceiveFailureType() { + CompileResult result = BCompileUtil.compile("test-src/workers/send-receive-failure-type.bal"); + int index = 0; + validateError(result, index++, "incompatible types: expected 'int', " + + "found '(int|ballerina/lang.error:0.0.0:NoMessage)'", 50, 15); + validateError(result, index++, "incompatible types: expected 'int', " + + "found '(ErrorA|int|ballerina/lang.error:0.0.0:NoMessage)'", 51, 15); + validateError(result, index++, "incompatible types: expected 'int', " + + "found '(ErrorA|ErrorB|string|ballerina/lang.error:0.0.0:NoMessage)'", 52, 15); + validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 90, 14); + validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 91, 14); + Assert.assertEquals(result.getErrorCount(), 5); } @Test diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal deleted file mode 100644 index 21707110cb97..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/invalid-send-with-return.bal +++ /dev/null @@ -1,23 +0,0 @@ -import ballerina/jballerina.java; - -public function main() { - worker w1 returns boolean|error{ - int i = 2; - if (0 > 1) { - return true; - } - i -> w2; - println("w1"); - return false; - } - - worker w2 { - int j = 25; - j = <- w1; - println(j); - } -} - -public function println(any|error... values) = @java:Method { - 'class: "org.ballerinalang.test.utils.interop.Utils" -} external; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal new file mode 100644 index 000000000000..354807bc639c --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal @@ -0,0 +1,104 @@ +// Copyright (c) 2024 WSO2 LLC. +// +// 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 +// +// 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; + +public type ErrorA distinct error; + +public type ErrorB distinct error; + +public function testSendFailureType(boolean b, boolean c) { + worker w1 returns boolean|ErrorA|ErrorB { + int i = 2; + + i -> w2; + if (0 > 1) { + return true; + } + i = i + 1; + i -> w2; + + if b { + return error ErrorA("error A"); + } + 44 -> w2; + + if c { + return error ErrorB("error B"); + } + "xxx" -> w2; + "yyy" -> w2; + "zzz" -> w2; + + return true; + } + + worker w2 { + int _ = <- w1; // OK + int _ = <- w1; // error: found 'int|error:NoMessage' + int _ = <- w1; // error: found 'int|ErrorA|error:NoMessage' + int _ = <- w1; // error: found 'string|ErrorA|ErrorB|error:NoMessage' + string|ErrorA|ErrorB|error:NoMessage m = <- w1; // OK + string|error n = <- w1; // OK + + println(m); + println(n); + } +} + +public function testReceiveFailureType(boolean b, boolean c) { + worker w1 returns boolean|ErrorA|ErrorB { + int i = 2; + + _ = <- w2; + if (0 > 1) { + return true; + } + i = i + 1; + _ = <- w2; + + if b { + return error ErrorA("error A"); + } + _ = <- w2; + + if c { + return error ErrorB("error B"); + } + _ = <- w2; + _ = <- w2; + _ = <- w2; + + return true; + } + + worker w2 { + () _ = 1 ->> w1; // OK + () _ = 2 ->> w1; // OK + () p = 3 ->> w1; // error: found 'ErrorA?' + () q = 4 ->> w1; // error: found '(ErrorA|ErrorB)?' + ErrorA|ErrorB? r = 5 ->> w1; // OK + error? s = 6 ->> w1; // OK + + println(p); + println(q); + println(r); + println(s); + } +} + +public function println(any|error... values) = @java:Method { + 'class: "org.ballerinalang.test.utils.interop.Utils" +} external; From 5373a08f1daf6302411e8b9e364f21f7a546f465 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:46:10 +0530 Subject: [PATCH 76/97] Add alternate and multiple receive tests for symbol finder --- .../semantic/api/test/SymbolAtCursorTest.java | 6 +++- .../test-src/symbol_at_cursor_basic_test.bal | 30 ++++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/SymbolAtCursorTest.java b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/SymbolAtCursorTest.java index 8dafe220b20a..bbeb41c6a182 100644 --- a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/SymbolAtCursorTest.java +++ b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/SymbolAtCursorTest.java @@ -134,7 +134,11 @@ public Object[][] getPositionsForExactLookup() { {204, 11, "y2"}, {204, 20, "x2"}, {205, 10, "y3"}, - {205, 19, "y1"} + {205, 19, "y1"}, + {229, 20, "w1"}, + {229, 23, "w2"}, + {243, 20, "w1"}, + {243, 27, "w2"} }; } diff --git a/tests/ballerina-compiler-api-test/src/test/resources/test-src/symbol_at_cursor_basic_test.bal b/tests/ballerina-compiler-api-test/src/test/resources/test-src/symbol_at_cursor_basic_test.bal index 007d0223b31f..b2d8ae93bb86 100644 --- a/tests/ballerina-compiler-api-test/src/test/resources/test-src/symbol_at_cursor_basic_test.bal +++ b/tests/ballerina-compiler-api-test/src/test/resources/test-src/symbol_at_cursor_basic_test.bal @@ -215,4 +215,32 @@ public type ReturnValue02 readonly & string; ReturnValue02 stringVar01 = "ballerina"; -public type ReadOnlyPrimitiveUnion readonly & string|int; \ No newline at end of file +public type ReadOnlyPrimitiveUnion readonly & string|int; + +function testAlternateReceive() { + worker w1 { + 3 -> w3; + } + + worker w2 { + 4 -> w3; + } + + worker w2 { + int _ = <- w1|w2; + } +} + +function testMultipleReceive() { + worker w1 { + 5 -> w3; + } + + worker w2 { + 6 -> w3; + } + + worker w2 { + _ = <- {a: w1, b: w2}; + } +} From 26600bd5ff27605dc6f7f64f4c4cdd3412f9a30c Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:32:28 +0530 Subject: [PATCH 77/97] Add alternate and multiple receive tests for reference finder --- .../allreferences/FindRefsInExprsTest.java | 10 +++++++ .../find-all-ref/find_var_ref_in_exprs.bal | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/allreferences/FindRefsInExprsTest.java b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/allreferences/FindRefsInExprsTest.java index f2937f300469..84f855a5a14f 100644 --- a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/allreferences/FindRefsInExprsTest.java +++ b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/allreferences/FindRefsInExprsTest.java @@ -217,6 +217,16 @@ public Object[][] getLookupPositions() { {212, 16, location(223, 22, 24), List.of(location(212, 16, 18), location(223, 22, 24)) + }, + // Alternate receive + {228, 11, location(228, 11, 13), + List.of(location(228, 11, 13), + location(237, 19, 21)) + }, + // Multiple receive + {246, 11, location(246, 11, 13), + List.of(location(246, 11, 13), + location(251, 26, 28)) } }; } diff --git a/tests/ballerina-compiler-api-test/src/test/resources/test-src/find-all-ref/find_var_ref_in_exprs.bal b/tests/ballerina-compiler-api-test/src/test/resources/test-src/find-all-ref/find_var_ref_in_exprs.bal index 29791fcd579e..ca2391ae5e60 100644 --- a/tests/ballerina-compiler-api-test/src/test/resources/test-src/find-all-ref/find_var_ref_in_exprs.bal +++ b/tests/ballerina-compiler-api-test/src/test/resources/test-src/find-all-ref/find_var_ref_in_exprs.bal @@ -224,3 +224,31 @@ function (int) returns int func4 = a => a + a; function func3(string s1) returns function (int) returns int { return func4; } + +function testAlternateReceive() { + worker w1 { + 3 -> w3; + } + + worker w2 { + 4 -> w3; + } + + worker w3 { + int _ = <- w1|w2; + } +} + +function testMultipleReceive() { + worker w1 { + 5 -> w3; + } + + worker w2 { + 6 -> w3; + } + + worker w3 { + _ = <- {a: w1, b: w2}; + } +} From 8dcfb2e864ae9a1d9848455cd030c0b3cffb213d Mon Sep 17 00:00:00 2001 From: hindujaB Date: Thu, 8 Feb 2024 10:30:51 +0530 Subject: [PATCH 78/97] Rename NoMessageError in tests --- .../runtime/internal/ErrorUtils.java | 2 +- .../runtime/internal/errors/ErrorReasons.java | 2 +- .../workers/workers_conditional_send.bal | 64 +++++++++---------- .../workers/workers_multiple_receive.bal | 24 +++---- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java index 59fc618655f3..613af41f7dc7 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/ErrorUtils.java @@ -191,7 +191,7 @@ public static BError createInvalidFractionDigitsError() { public static BError createNoMessageError(String chnlName) { String[] splitWorkers = chnlName.split(":")[0].split("->"); - return createError(BALLERINA_LANG_ERROR_PKG_ID, "NoMessageError", ErrorReasons.NO_MESSAGE_ERROR, + return createError(BALLERINA_LANG_ERROR_PKG_ID, "NoMessage", ErrorReasons.NO_MESSAGE_ERROR, null, ErrorHelper.getErrorDetails(ErrorCodes.NO_MESSAGE_ERROR, StringUtils.fromString(splitWorkers[0]), StringUtils.fromString(splitWorkers[1]))); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java index 9cdfbf5b10ba..ed8e8f0540f5 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/errors/ErrorReasons.java @@ -133,7 +133,7 @@ private ErrorReasons() {} public static final BString REGEXP_OPERATION_ERROR = getModulePrefixedReason(REGEXP_LANG_LIB, "RegularExpressionOperationError"); - public static final BString NO_MESSAGE_ERROR = StringUtils.fromString("NoMessageError"); + public static final BString NO_MESSAGE_ERROR = StringUtils.fromString("NoMessage"); public static BString getModulePrefixedReason(String moduleName, String identifier) { return StringUtils.fromString(BALLERINA_ORG_PREFIX.concat(moduleName) diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index f0b2d6d827fc..62ba1bedb74e 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -28,14 +28,14 @@ function workerConditionalSendTest() { } } - worker w2 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError a = <- w1; + worker w2 returns int|errorLib:NoMessage { + int|errorLib:NoMessage a = <- w1; return a; } worker w3 { - int|errorLib:NoMessageError b = <- w1; - int|errorLib:NoMessageError c = <- w4; + int|errorLib:NoMessage b = <- w1; + int|errorLib:NoMessage c = <- w4; } worker w4 { @@ -46,12 +46,12 @@ function workerConditionalSendTest() { } } - worker w5 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError d = <- w4; + worker w5 returns int|errorLib:NoMessage { + int|errorLib:NoMessage d = <- w4; return d; } - map results = wait {a: w2, b: w5}; + map results = wait {a: w2, b: w5}; test:assertEquals(results["a"], 1, "Invalid int result"); test:assertEquals(results["b"], 2, "Invalid int result"); } @@ -68,12 +68,12 @@ function sameWorkerSendTest() { } worker w2 { - int|errorLib:NoMessageError a = <- w1; - int|errorLib:NoMessageError b = <- w1; + int|errorLib:NoMessage a = <- w1; + int|errorLib:NoMessage b = <- w1; test:assertEquals(a, 10, "Invalid int result"); test:assertTrue(b is error); error e = b; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w2'\"}", "Invalid error detail"); } @@ -92,7 +92,7 @@ function sameWorkerSendEitherOnePath() { } worker w2 { - int|errorLib:NoMessageError a = <- w1 | w1; + int|errorLib:NoMessage a = <- w1 | w1; test:assertEquals(a, 10, "Invalid int result"); } @@ -118,7 +118,7 @@ function sameWorkerSendAltReceiveSendError() { int|error a = <- w1 | w1; test:assertTrue(a is error, "Invalid error result"); error e = a; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no worker message received for channel 'w1->w2'\"}", "Invalid error detail"); } error? unionResult = wait w1; @@ -199,7 +199,7 @@ function sameWorkerSendSenderPanic() { } worker w2 { - int|errorLib:NoMessageError a = <- w1 | w1; + int|errorLib:NoMessage a = <- w1 | w1; } error? unionResult = trap wait w1; @@ -219,12 +219,12 @@ function sameWorkerSendReceiverPanic() { } } - worker w2 returns int|errorLib:NoMessageError { + worker w2 returns int|errorLib:NoMessage { int value = 10; if value == 10 { panic error("Error in worker 2"); } - int|errorLib:NoMessageError a = <- w1 | w1; + int|errorLib:NoMessage a = <- w1 | w1; return a; } @@ -244,12 +244,12 @@ function sameWorkerSendMultiplePath1() { 2 -> w2; } - worker w2 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError a = <- w1 | w1; + worker w2 returns int|errorLib:NoMessage { + int|errorLib:NoMessage a = <- w1 | w1; return a; } - int|errorLib:NoMessageError intResult = wait w2; + int|errorLib:NoMessage intResult = wait w2; test:assertEquals(intResult, 1, "Invalid int result"); } @@ -263,12 +263,12 @@ function sameWorkerSendMultiplePath2() { 2 -> w2; } - worker w2 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError a = <- w1 | w1; + worker w2 returns int|errorLib:NoMessage { + int|errorLib:NoMessage a = <- w1 | w1; return a; } - int|errorLib:NoMessageError intResult = wait w2; + int|errorLib:NoMessage intResult = wait w2; test:assertEquals(intResult, 2, "Invalid int result"); } @@ -391,13 +391,13 @@ function multipleReceiveConditional() { return y; } - worker w2 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError y = <- w1; + worker w2 returns int|errorLib:NoMessage { + int|errorLib:NoMessage y = <- w1; return y; } - worker w3 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError y = <- w1; + worker w3 returns int|errorLib:NoMessage { + int|errorLib:NoMessage y = <- w1; 3 -> w1; return y; } @@ -407,20 +407,20 @@ function multipleReceiveConditional() { test:assertEquals(mapResult["b"], 2, "Invalid int result"); test:assertTrue(mapResult["c"] is error, "Expected error result"); error e = mapResult["c"]; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); } function multipleReceiveWithNonConditionalSend() { boolean foo = true; worker w3 { - int|errorLib:NoMessageError x = <- w1; - int|errorLib:NoMessageError y = <- w1; + int|errorLib:NoMessage x = <- w1; + int|errorLib:NoMessage y = <- w1; int z = <- w1; test:assertEquals(x, 2, "Invalid int result"); test:assertTrue(y is error, "Invalid error result"); error e = y; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); test:assertEquals(z, 4, "Invalid int result"); } @@ -446,13 +446,13 @@ function testNonTopLevelSend() { return false; } - worker w2 returns int|errorLib:NoMessageError { - int|errorLib:NoMessageError j = 25; + worker w2 returns int|errorLib:NoMessage { + int|errorLib:NoMessage j = 25; j = <- w1; return j; } - map mapResult = wait {a: w1, b: w2}; + map mapResult = wait {a: w1, b: w2}; test:assertEquals(mapResult["a"], false, "Invalid boolean result"); test:assertEquals(mapResult["b"], 2, "Invalid int result"); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal index f443e643deb8..88811521cba3 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -263,21 +263,21 @@ function workerMultipleReceiveWithConditionalSend1() { } } - worker w2 returns map { - map m = <- {w1, w3}; + worker w2 returns map { + map m = <- {w1, w3}; return m; } worker w3 { - int|errorLib:NoMessageError a = <- w1; + int|errorLib:NoMessage a = <- w1; test:assertTrue(a is error, "Invalid result"); error e = a; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w3'\"}", "Invalid error detail"); 3 -> w2; } - map mapResult = wait w2; + map mapResult = wait w2; test:assertEquals(mapResult["w1"], 1, "Invalid map result"); test:assertEquals(mapResult["w3"], 3, "Invalid map result"); } @@ -293,22 +293,22 @@ function workerMultipleReceiveWithConditionalSend2() { } } - worker w2 returns map { - map m = <- {w1, w3}; + worker w2 returns map { + map m = <- {w1, w3}; return m; } worker w3 { - int|errorLib:NoMessageError a = <- w1; + int|errorLib:NoMessage a = <- w1; test:assertTrue(a is int, "Invalid result"); test:assertEquals(a, 1, "Invalid int result"); 3 -> w2; } - map mapResult = wait w2; - test:assertTrue(mapResult["w1"] is errorLib:NoMessageError, "Invalid map result"); - errorLib:NoMessageError e = mapResult["w1"]; - test:assertEquals(e.message(), "NoMessageError", "Invalid error message"); + map mapResult = wait w2; + test:assertTrue(mapResult["w1"] is errorLib:NoMessage, "Invalid map result"); + errorLib:NoMessage e = mapResult["w1"]; + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w2'\"}", "Invalid error detail"); test:assertEquals(mapResult["w3"], 3, "Invalid map result"); } From b96cc4f59d04ec66c54ef6d4ad90dbd0d36fce37 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 19 Feb 2024 16:39:56 +0530 Subject: [PATCH 79/97] Change ReceiveField to record --- .../internal/scheduling/ReceiveField.java | 38 ------------------- .../internal/scheduling/WDChannels.java | 10 +++-- .../compiler/bir/codegen/JvmConstants.java | 2 +- .../bir/codegen/JvmTerminatorGen.java | 4 +- .../compiler/bir/model/BIRTerminator.java | 11 +----- .../bir/writer/BIRInstructionWriter.java | 4 +- 6 files changed, 14 insertions(+), 55 deletions(-) delete mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java deleted file mode 100644 index b09c0316ecff..000000000000 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/ReceiveField.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) - * - * 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 - * - * 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 io.ballerina.runtime.internal.scheduling; - -/** - * A worker receive field for multiple receive action. - *

- * e.g., WRK_RECEIVE {w1 , w2}; - * - * @since 2201.9.0 - */ -public class ReceiveField { - - public final String fieldName; - public final String channelName; - - public ReceiveField(String fieldName, String channelName) { - this.fieldName = fieldName; - this.channelName = channelName; - } - -} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 7490974b3f74..331efe4599a3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -43,6 +43,10 @@ public class WDChannels { private Map wDChannels; private final List errors = new ArrayList<>(); + // A worker receive field for multiple receive action. + public record ReceiveField(String fieldName, String channelName) { + } + //TODO try to generalize this to a normal data channel, in that case we won't need these classes. public synchronized WorkerDataChannel getWorkerDataChannel(String name) { @@ -63,13 +67,13 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF strand.workerReceiveMap = ValueCreator.createMapValue(targetType); } for (ReceiveField field : receiveFields) { - WorkerDataChannel channel = getWorkerDataChannel(field.channelName); + WorkerDataChannel channel = getWorkerDataChannel(field.channelName()); if (!channel.isClosed()) { Object result = channel.tryTakeData(strand, true); checkAndPopulateResult(strand, field, result, channel); } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName), channel); + checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName()), channel); } } } @@ -79,7 +83,7 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { if (result != null) { result = getResultValue(result); - strand.workerReceiveMap.populateInitialValue(StringUtils.fromString(field.fieldName), result); + strand.workerReceiveMap.populateInitialValue(StringUtils.fromString(field.fieldName()), result); channel.close(); ++strand.channelCount; } else { 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 1c409e2003d9..4e65ee3fe53c 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 @@ -251,7 +251,7 @@ public class JvmConstants { public static final String SYSTEM = "java/lang/System"; public static final String BIG_DECIMAL = "java/math/BigDecimal"; public static final String STRING_CONCAT_FACTORY = "java/lang/invoke/StringConcatFactory"; - public static final String RECEIVE_FIELD = "io/ballerina/runtime/internal/scheduling/ReceiveField"; + public static final String RECEIVE_FIELD = "io/ballerina/runtime/internal/scheduling/WDChannels$ReceiveField"; // service objects, annotation processing related classes public static final String ANNOTATION_UTILS = "io/ballerina/runtime/internal/AnnotationUtils"; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index f2baa6924ea4..67ae96ffa7d0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -1258,12 +1258,12 @@ private void genWorkerMultipleReceiveIns(BIRTerminator.WorkerMultipleReceive ins this.mv.visitIntInsn(BIPUSH, i); this.mv.visitTypeInsn(NEW, RECEIVE_FIELD); this.mv.visitInsn(DUP); - this.mv.visitLdcInsn(receiveField.key); + this.mv.visitLdcInsn(receiveField.key()); this.mv.visitVarInsn(ILOAD, invocationVarIndex); this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), - receiveField.workerReceive + START_OF_HEADING_WITH_SEMICOLON); + receiveField.workerReceive() + START_OF_HEADING_WITH_SEMICOLON); this.mv.visitMethodInsn(INVOKESPECIAL, RECEIVE_FIELD, JVM_INIT_METHOD, INIT_RECEIVE_FIELD, false); this.mv.visitInsn(AASTORE); i += 1; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java index 47d4fe45821a..1da054301dfd 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java @@ -777,18 +777,11 @@ public BIRBasicBlock[] getNextBasicBlocks() { } /** - * This static inner class represents key-value pair in a multiple worker. + * A worker receive field for multiple receive action. * * @since 2201.9.0 */ - public static class ReceiveField { - public String key; - public String workerReceive; - - public ReceiveField(String key, String workerReceive) { - this.key = key; - this.workerReceive = workerReceive; - } + public record ReceiveField(String key, String workerReceive) { } } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java index 00c3da615c0a..9634ded36f14 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/writer/BIRInstructionWriter.java @@ -244,8 +244,8 @@ public void visit(BIRTerminator.WorkerAlternateReceive entry) { @Override public void visit(BIRTerminator.WorkerMultipleReceive entry) { entry.receiveFields.forEach(key -> { - buf.writeInt(addStringCPEntry(key.key)); - buf.writeInt(addStringCPEntry(key.workerReceive)); + buf.writeInt(addStringCPEntry(key.key())); + buf.writeInt(addStringCPEntry(key.workerReceive())); }); writeType(entry.targetType); entry.lhsOp.accept(this); From b58703d26676116063ccd8c6e148cc2281cb0e44 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Mon, 19 Feb 2024 17:49:25 +0530 Subject: [PATCH 80/97] Fix checkstyle errors --- .../ballerinalang/compiler/bir/model/BIRTerminator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java index 1da054301dfd..0f3181d4e26d 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/model/BIRTerminator.java @@ -777,9 +777,10 @@ public BIRBasicBlock[] getNextBasicBlocks() { } /** - * A worker receive field for multiple receive action. - * - * @since 2201.9.0 + * A worker receive field for multiple receive action. + * @since 2201.9.0 + * @param key the field name of the result + * @param workerReceive the channel name */ public record ReceiveField(String key, String workerReceive) { } From 39503b9ca0046f50cd2c9b535d0a5f590f318fe5 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Tue, 20 Feb 2024 06:43:23 +0530 Subject: [PATCH 81/97] Fix checkstyle errors --- .../io/ballerina/runtime/internal/scheduling/WDChannels.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 331efe4599a3..cdecfa289ff5 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -73,7 +73,8 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF checkAndPopulateResult(strand, field, result, channel); } else { if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName()), channel); + checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName()), + channel); } } } From 91a595272873d483934766976bc7edb4ff43ae36 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Tue, 5 Mar 2024 10:33:48 +0530 Subject: [PATCH 82/97] Remove array stream usage --- .../bir/codegen/JvmTerminatorGen.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java index 67ae96ffa7d0..0e2009af0b47 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/JvmTerminatorGen.java @@ -57,8 +57,10 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static org.objectweb.asm.Opcodes.AASTORE; import static org.objectweb.asm.Opcodes.ACONST_NULL; @@ -1418,21 +1420,24 @@ private void genResourcePathArgs(List pathArgs) { public void genReturnTerm(int returnVarRefIndex, BIRNode.BIRFunction func, int invocationVarIndex, int localVarOffset) { if (func.workerChannels != null) { - Arrays.stream(func.workerChannels).distinct().forEach(channel -> { - this.mv.visitVarInsn(ALOAD, localVarOffset); - if (Symbols.isFlagOn(func.flags, Flags.WORKER)) { - this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); + Set uniqueValues = new HashSet<>(); + for (BIRNode.ChannelDetails channel : func.workerChannels) { + if (uniqueValues.add(channel)) { + this.mv.visitVarInsn(ALOAD, localVarOffset); + if (Symbols.isFlagOn(func.flags, Flags.WORKER)) { + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "parent", GET_STRAND); + } + this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); + this.mv.visitVarInsn(ALOAD, localVarOffset); + this.mv.visitVarInsn(ILOAD, invocationVarIndex); + this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, + new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, + HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), channel.name + + START_OF_HEADING_WITH_SEMICOLON); + this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "removeCompletedChannels", + REMOVE_WORKER_DATA_CHANNEL, false); } - this.mv.visitFieldInsn(GETFIELD, STRAND_CLASS, "wdChannels", GET_WD_CHANNELS); - this.mv.visitVarInsn(ALOAD, localVarOffset); - this.mv.visitVarInsn(ILOAD, invocationVarIndex); - this.mv.visitInvokeDynamicInsn(MAKE_CONCAT_WITH_CONSTANTS, INT_TO_STRING, - new Handle(H_INVOKESTATIC, STRING_CONCAT_FACTORY, MAKE_CONCAT_WITH_CONSTANTS, - HANDLE_DESCRIPTOR_FOR_STRING_CONCAT, false), channel.name - + START_OF_HEADING_WITH_SEMICOLON); - this.mv.visitMethodInsn(INVOKEVIRTUAL, WD_CHANNELS, "removeCompletedChannels", - REMOVE_WORKER_DATA_CHANNEL, false); - }); + } } BType bType = unifier.build(func.type.retType); generateReturnTermFromType(returnVarRefIndex, bType, func, invocationVarIndex, localVarOffset); From eef9971fd38f0f14f7f9dd08440c265247a3fa1b Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:37:12 +0530 Subject: [PATCH 83/97] Revert changes done in 3a75d12 As we are not going to support stream-receive with update 9. --- .../util/diagnostic/DiagnosticErrorCode.java | 1 - .../compiler/parser/BLangNodeBuilder.java | 41 +- .../src/main/resources/compiler.properties | 3 - .../internal/parser/BallerinaParser.java | 126 +- .../parser/BallerinaParserErrorHandler.java | 54 +- .../internal/parser/ParserRuleContext.java | 7 +- ...java => STAlternateReceiveWorkerNode.java} | 20 +- .../internal/parser/tree/STNodeFactory.java | 24 +- .../parser/tree/STNodeTransformer.java | 12 +- .../internal/parser/tree/STNodeVisitor.java | 12 +- .../parser/tree/STSingleReceiveNode.java | 84 -- .../parser/tree/STStreamReceiveNode.java | 114 -- .../internal/parser/tree/STTreeModifier.java | 30 +- ...e.java => AlternateReceiveWorkerNode.java} | 24 +- .../compiler/syntax/tree/NodeFactory.java | 34 +- .../compiler/syntax/tree/NodeTransformer.java | 12 +- .../compiler/syntax/tree/NodeVisitor.java | 12 +- .../syntax/tree/SingleReceiveNode.java | 96 -- .../syntax/tree/StreamReceiveNode.java | 150 --- .../compiler/syntax/tree/SyntaxKind.java | 4 +- .../compiler/syntax/tree/TreeModifier.java | 35 +- .../compiler/parser/test/ParserTestUtils.java | 8 +- .../syntax/actions/ReceiveActionTest.java | 10 - .../receive_action_assert_01.json | 31 +- .../receive_action_assert_02.json | 32 +- .../receive_action_assert_04.json | 14 +- .../receive_action_assert_05.json | 6 +- .../receive_action_assert_06.json | 1074 ----------------- .../receive_action_assert_07.json | 802 ------------ .../receive_action_source_06.bal | 13 - .../receive_action_source_07.bal | 7 - .../misc/completion/completion_assert_08.json | 16 +- .../main/resources/syntax_node_metadata.json | 12 +- .../resources/syntax_tree_descriptor.json | 39 +- .../core/FormattingTreeModifier.java | 29 +- .../formatter/core/ParserTestFormatter.java | 2 +- .../api_gen_syntax_tree_descriptor.json | 39 +- 37 files changed, 141 insertions(+), 2888 deletions(-) rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/{STAlternateReceiveNode.java => STAlternateReceiveWorkerNode.java} (78%) delete mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java delete mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/{AlternateReceiveNode.java => AlternateReceiveWorkerNode.java} (73%) delete mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java delete mode 100644 compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java delete mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json delete mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json delete mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal delete mode 100644 compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index f187da6475b6..26c2b4c5f257 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -816,7 +816,6 @@ public enum DiagnosticErrorCode implements DiagnosticCode { EXPRESSION_OF_FUTURE_TYPE_EXPECTED("BCE4057", "future.expression.expected"), INSTANTIATION_ERROR("BCE4058", "instantiation.error"), INVALID_BINDING_PATTERN_IN_ON_FAIL("BCE4059", "invalid.binding.pattern.in.on.fail"), - STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED("BCE4060", "stream.receive.action.not.yet.supported") ; private String diagnosticId; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index c7d1b52d9f0b..3eacef322e81 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -17,7 +17,7 @@ */ package org.wso2.ballerinalang.compiler.parser; -import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -203,14 +203,12 @@ import io.ballerina.compiler.syntax.tree.SeparatedNodeList; import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.compiler.syntax.tree.SingleReceiveNode; import io.ballerina.compiler.syntax.tree.SingletonTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SpecificFieldNode; import io.ballerina.compiler.syntax.tree.SpreadFieldNode; import io.ballerina.compiler.syntax.tree.SpreadMemberNode; import io.ballerina.compiler.syntax.tree.StartActionNode; import io.ballerina.compiler.syntax.tree.StatementNode; -import io.ballerina.compiler.syntax.tree.StreamReceiveNode; import io.ballerina.compiler.syntax.tree.StreamTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.StreamTypeParamsNode; import io.ballerina.compiler.syntax.tree.SyncSendActionNode; @@ -2529,23 +2527,25 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { Location receiveActionPos = getPosition(receiveActionNode); Node receiveWorkers = receiveActionNode.receiveWorkers(); - if (receiveWorkers.kind() == SyntaxKind.SINGLE_RECEIVE) { - SingleReceiveNode singleReceiveNode = (SingleReceiveNode) receiveWorkers; - BLangWorkerReceive singleWorkerRecv = createSimpleWorkerReceive(singleReceiveNode.worker().name()); + if (receiveWorkers.kind() == SyntaxKind.SIMPLE_NAME_REFERENCE) { + BLangWorkerReceive singleWorkerRecv = + createSimpleWorkerReceive(((SimpleNameReferenceNode) receiveWorkers).name()); singleWorkerRecv.pos = receiveActionPos; return singleWorkerRecv; } - if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE) { + if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE_WORKER) { SeparatedNodeList alternateWorkers = - ((AlternateReceiveNode) receiveWorkers).workers(); - return createAlternateWorkerReceive(alternateWorkers, receiveActionPos); - } + ((AlternateReceiveWorkerNode) receiveWorkers).workers(); + List workerReceives = new ArrayList<>(alternateWorkers.size()); + for (SimpleNameReferenceNode w : alternateWorkers) { + workerReceives.add(createSimpleWorkerReceive(w.name())); + } - if (receiveWorkers.kind() == SyntaxKind.STREAM_RECEIVE) { - dlog.error(receiveActionPos, DiagnosticErrorCode.STREAM_RECEIVE_ACTION_NOT_YET_SUPPORTED); - // mock rest of the flow as an alternative receive - return createAlternateWorkerReceive(((StreamReceiveNode) receiveWorkers).workers(), receiveActionPos); + BLangAlternateWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); + alternateWorkerRecv.setWorkerReceives(workerReceives); + alternateWorkerRecv.pos = receiveActionPos; + return alternateWorkerRecv; } ReceiveFieldsNode receiveFieldsNode = (ReceiveFieldsNode) receiveWorkers; @@ -2571,19 +2571,6 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { return multipleWorkerRv; } - private BLangAlternateWorkerReceive createAlternateWorkerReceive( - SeparatedNodeList alternateWorkers, Location receiveActionPos) { - List workerReceives = new ArrayList<>(alternateWorkers.size()); - for (SimpleNameReferenceNode w : alternateWorkers) { - workerReceives.add(createSimpleWorkerReceive(w.name())); - } - - BLangAlternateWorkerReceive alternateWorkerRecv = TreeBuilder.createAlternateWorkerReceiveNode(); - alternateWorkerRecv.setWorkerReceives(workerReceives); - alternateWorkerRecv.pos = receiveActionPos; - return alternateWorkerRecv; - } - private BLangWorkerReceive createSimpleWorkerReceive(Token workerRef) { BLangWorkerReceive workerReceiveExpr = (BLangWorkerReceive) TreeBuilder.createWorkerReceiveNode(); workerReceiveExpr.setWorkerName(createIdentifier(workerRef)); diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index acd4b097ceca..3a8e6f0af546 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -2027,6 +2027,3 @@ error.inferred.query.construct.type.as.stream=\ error.invalid.binding.pattern.in.on.fail=\ invalid binding pattern in ''on fail'' clause: only a capture binding pattern or an error binding pattern is allowed - -error.stream.receive.action.not.yet.supported=\ - stream receive action not yet supported diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index b9c4e94fa205..4c06f11a3c28 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13076,147 +13076,63 @@ private STNode parseSyncSendToken() { * multiple-receive-action := <- { receive-field (, receive-field)* } *

* alternate-receive-action := <- peer-worker (| peer-worker)* - *

- * stream-receive-action := <- stream `(` peer-worker (| peer-worker)* `)` * * * @return Receive action */ private STNode parseReceiveAction() { STNode leftArrow = parseLeftArrowToken(); - STNode receiveRhs = parseReceiveActionRhs(); - return STNodeFactory.createReceiveActionNode(leftArrow, receiveRhs); + STNode receiveWorkers = parseReceiveWorkers(); + return STNodeFactory.createReceiveActionNode(leftArrow, receiveWorkers); } - private STNode parseReceiveActionRhs() { + private STNode parseReceiveWorkers() { switch (peek().kind) { case FUNCTION_KEYWORD: case IDENTIFIER_TOKEN: - return parseSingleOrAlternateReceiveRhs(); + return parseSingleOrAlternateReceiveWorkers(); case OPEN_BRACE_TOKEN: - return parseMultipleReceiveRhs(); - case STREAM_KEYWORD: - return parseStreamReceiveRhs(); + return parseMultipleReceiveWorkers(); default: - recover(peek(), ParserRuleContext.RECEIVE_ACTION_RHS); - return parseReceiveActionRhs(); + recover(peek(), ParserRuleContext.RECEIVE_WORKERS); + return parseReceiveWorkers(); } } - /** - * Parse single or alternate receive action rhs. - *

- *

- * single-receive-rhs := peer-worker - *

- * alternate-receive-rhs := peer-worker (| peer-worker)* - *
- * - * @return Receive action - */ - private STNode parseSingleOrAlternateReceiveRhs() { - startContext(ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS); - STNode firstPeerWorker = parsePeerWorkerName(); + private STNode parseSingleOrAlternateReceiveWorkers() { + startContext(ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER); + List workers = new ArrayList<>(); + // Parse first peer worker name, that has no leading comma + STNode peerWorker = parsePeerWorkerName(); + workers.add(peerWorker); + STToken nextToken = peek(); if (nextToken.kind != SyntaxKind.PIPE_TOKEN) { endContext(); - return STNodeFactory.createSingleReceiveNode(firstPeerWorker); + return peerWorker; } - STNode peerWorkers = parsePeerWorkers(firstPeerWorker); - endContext(); - return STNodeFactory.createAlternateReceiveNode(peerWorkers); - } - - /** - * Parse peer worker list separated by `|`. - * - * @param firstPeerWorker first peer worker node - * @return Parsed node - */ - private STNode parsePeerWorkers(STNode firstPeerWorker) { - List workers = new ArrayList<>(); - workers.add(firstPeerWorker); - // Parse the remaining peer worker names - STToken nextToken = peek(); while (nextToken.kind == SyntaxKind.PIPE_TOKEN) { STNode pipeToken = consume(); workers.add(pipeToken); - STNode peerWorker = parsePeerWorkerName(); + peerWorker = parsePeerWorkerName(); workers.add(peerWorker); nextToken = peek(); } - return STNodeFactory.createNodeList(workers); - } - - /** - * Parse stream receive action rhs. - *

- * - * stream-receive-rhs := stream `(` peer-worker (| peer-worker)* `)` - * - * - * @return Parsed node - */ - private STNode parseStreamReceiveRhs() { - startContext(ParserRuleContext.STREAM_RECEIVE_RHS); - STNode streamKeyword = parseStreamKeyword(); - STNode openParen = parseOpenParenthesis(); - STNode workers = parseStreamPeerWorkers(); - STNode closeParen = parseCloseParenthesis(); endContext(); - return STNodeFactory.createStreamReceiveNode(streamKeyword, openParen, workers, closeParen); - } - - /** - * Parse stream-keyword. - * - * @return Parsed node - */ - private STNode parseStreamKeyword() { - STToken token = peek(); - if (token.kind == SyntaxKind.STREAM_KEYWORD) { - return consume(); - } else { - recover(token, ParserRuleContext.STREAM_KEYWORD); - return parseStreamKeyword(); - } + return STNodeFactory.createAlternateReceiveWorkerNode(STNodeFactory.createNodeList(workers)); } /** - * Parse stream receive peer worker list. + * Parse multiple worker receivers. *

- * - * stream-receive-peer-workers := peer-worker (| peer-worker)* - * + * { receive-field (, receive-field)* } * - * @return Parsed node - */ - private STNode parseStreamPeerWorkers() { - STNode firstPeerWorker = parsePeerWorkerName(); - - STToken nextToken = peek(); - if (nextToken.kind != SyntaxKind.PIPE_TOKEN) { - return STNodeFactory.createNodeList(new ArrayList<>(Collections.singletonList(firstPeerWorker))); - } - - return parsePeerWorkers(firstPeerWorker); - } - - /** - * Parse multiple receive action rhs. - *

- * - * multiple-receive-rhs := { receive-field (, receive-field)* } - *

- * receive-field := peer-worker | field-name : peer-worker - *
- * - * @return Parsed node + * @return Multiple worker receiver node */ - private STNode parseMultipleReceiveRhs() { + private STNode parseMultipleReceiveWorkers() { startContext(ParserRuleContext.MULTI_RECEIVE_WORKERS); STNode openBrace = parseOpenBrace(); STNode receiveFields = parseReceiveFields(); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java index 258c9c62cfc4..20b922cfe6bf 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParserErrorHandler.java @@ -521,16 +521,12 @@ public class BallerinaParserErrorHandler extends AbstractParserErrorHandler { private static final ParserRuleContext[] REMOTE_CALL_OR_ASYNC_SEND_END = { ParserRuleContext.ARG_LIST_OPEN_PAREN, ParserRuleContext.SEMICOLON }; - private static final ParserRuleContext[] RECEIVE_ACTION_RHS = - { ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS, ParserRuleContext.STREAM_RECEIVE_RHS, - ParserRuleContext.MULTI_RECEIVE_WORKERS }; + private static final ParserRuleContext[] RECEIVE_WORKERS = + { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER, ParserRuleContext.MULTI_RECEIVE_WORKERS }; private static final ParserRuleContext[] SINGLE_OR_ALTERNATE_WORKER_SEPARATOR = { ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END, ParserRuleContext.PIPE }; - private static final ParserRuleContext[] STREAM_WORKER_SEPARATOR = - { ParserRuleContext.STREAM_WORKER_END, ParserRuleContext.PIPE }; - private static final ParserRuleContext[] RECEIVE_FIELD = { ParserRuleContext.PEER_WORKER_NAME, ParserRuleContext.RECEIVE_FIELD_NAME }; @@ -1482,7 +1478,7 @@ protected boolean hasAlternativePaths(ParserRuleContext currentCtx) { case NIL_OR_PARENTHESISED_TYPE_DESC_RHS: case REMOTE_OR_RESOURCE_CALL_OR_ASYNC_SEND_RHS: case REMOTE_CALL_OR_ASYNC_SEND_END: - case RECEIVE_ACTION_RHS: + case RECEIVE_WORKERS: case RECEIVE_FIELD: case RECEIVE_FIELD_END: case WAIT_KEYWORD_RHS: @@ -1615,7 +1611,6 @@ protected boolean hasAlternativePaths(ParserRuleContext currentCtx) { case GROUPING_KEY_LIST_ELEMENT_END: case RESULT_CLAUSE: case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: - case STREAM_WORKER_SEPARATOR: return true; default: return false; @@ -1842,7 +1837,7 @@ protected ParserRuleContext getShortestAlternative(ParserRuleContext currentCtx) return ParserRuleContext.PEER_WORKER_NAME; case REMOTE_CALL_OR_ASYNC_SEND_END: return ParserRuleContext.SEMICOLON; - case RECEIVE_ACTION_RHS: + case RECEIVE_WORKERS: case RECEIVE_FIELD: return ParserRuleContext.PEER_WORKER_NAME; case RECEIVE_FIELD_END: @@ -2086,8 +2081,6 @@ protected ParserRuleContext getShortestAlternative(ParserRuleContext currentCtx) return ParserRuleContext.SELECT_CLAUSE; case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_END; - case STREAM_WORKER_SEPARATOR: - return ParserRuleContext.STREAM_WORKER_END; default: throw new IllegalStateException("Alternative path entry not found"); } @@ -2578,8 +2571,8 @@ private Result seekMatchInStmtRelatedAlternativePaths(ParserRuleContext currentC case OPTIONAL_RESOURCE_ACCESS_ACTION_ARG_LIST: alternativeRules = OPTIONAL_RESOURCE_ACCESS_ACTION_ARG_LIST; break; - case RECEIVE_ACTION_RHS: - alternativeRules = RECEIVE_ACTION_RHS; + case RECEIVE_WORKERS: + alternativeRules = RECEIVE_WORKERS; break; case RECEIVE_FIELD: alternativeRules = RECEIVE_FIELD; @@ -2861,9 +2854,6 @@ private Result seekMatchInExprRelatedAlternativePaths(ParserRuleContext currentC case SINGLE_OR_ALTERNATE_WORKER_SEPARATOR: alternativeRules = SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; break; - case STREAM_WORKER_SEPARATOR: - alternativeRules = STREAM_WORKER_SEPARATOR; - break; default: throw new IllegalStateException("seekMatchInExprRelatedAlternativePaths found: " + currentCtx); } @@ -3500,15 +3490,11 @@ protected ParserRuleContext getNextRule(ParserRuleContext currentCtx, int nextLo return getNextRuleForBindingPattern(); case TUPLE_MEMBERS: return ParserRuleContext.TUPLE_MEMBER; - case SINGLE_OR_ALTERNATE_RECEIVE_RHS: + case SINGLE_OR_ALTERNATE_WORKER: return ParserRuleContext.PEER_WORKER_NAME; case SINGLE_OR_ALTERNATE_WORKER_END: endContext(); // end single-or-alternate-worker return ParserRuleContext.EXPRESSION_RHS; - case STREAM_RECEIVE_RHS: - return ParserRuleContext.STREAM_KEYWORD; - case STREAM_WORKER_END: - return ParserRuleContext.CLOSE_PARENTHESIS; default: return getNextRuleInternal(currentCtx, nextLookahead); } @@ -3532,8 +3518,7 @@ private ParserRuleContext getNextRuleInternal(ParserRuleContext currentCtx, int return ParserRuleContext.XML_ATOMIC_NAME_PATTERN; } else if (parentCtx == ParserRuleContext.MATCH_PATTERN) { return ParserRuleContext.MATCH_PATTERN_START; - } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS || - parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { return ParserRuleContext.PEER_WORKER_NAME; } return ParserRuleContext.TYPE_DESCRIPTOR; @@ -3742,7 +3727,7 @@ private ParserRuleContext getNextRuleInternal(ParserRuleContext currentCtx, int case SYNC_SEND_TOKEN: return ParserRuleContext.PEER_WORKER_NAME; case LEFT_ARROW_TOKEN: - return ParserRuleContext.RECEIVE_ACTION_RHS; + return ParserRuleContext.RECEIVE_WORKERS; case MULTI_RECEIVE_WORKERS: return ParserRuleContext.OPEN_BRACE; case RECEIVE_FIELD_NAME: @@ -4079,8 +4064,6 @@ private ParserRuleContext getNextRuleForKeywords(ParserRuleContext currentCtx, i parentCtx = getParentContext(); if (parentCtx == ParserRuleContext.TABLE_CONSTRUCTOR_OR_QUERY_EXPRESSION) { return ParserRuleContext.QUERY_EXPRESSION; - } else if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { - return ParserRuleContext.OPEN_PARENTHESIS; } return ParserRuleContext.STREAM_TYPE_PARAM_START_TOKEN; case NEW_KEYWORD: @@ -4127,10 +4110,8 @@ private ParserRuleContext getNextRuleForKeywords(ParserRuleContext currentCtx, i parentCtx = getParentContext(); if (parentCtx == ParserRuleContext.MULTI_RECEIVE_WORKERS) { return ParserRuleContext.RECEIVE_FIELD_END; - } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_RECEIVE_RHS) { + } else if (parentCtx == ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER) { return ParserRuleContext.SINGLE_OR_ALTERNATE_WORKER_SEPARATOR; - } else if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { - return ParserRuleContext.STREAM_WORKER_SEPARATOR; } return ParserRuleContext.EXPRESSION_RHS; case WAIT_KEYWORD: @@ -4307,8 +4288,7 @@ private void startContextIfRequired(ParserRuleContext currentCtx) { case BRACED_EXPRESSION: case CLIENT_RESOURCE_ACCESS_ACTION: case TUPLE_MEMBERS: - case SINGLE_OR_ALTERNATE_RECEIVE_RHS: - case STREAM_RECEIVE_RHS: + case SINGLE_OR_ALTERNATE_WORKER: // Contexts that expect a type case TYPE_DESC_IN_ANNOTATION_DECL: @@ -4345,11 +4325,9 @@ private void startContextIfRequired(ParserRuleContext currentCtx) { } private ParserRuleContext getNextRuleForCloseParenthesis() { - ParserRuleContext parentCtx = getParentContext(); - if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { - endContext(); // end stream-receive-rhs - return ParserRuleContext.EXPRESSION_RHS; - } else if (parentCtx == ParserRuleContext.PARAM_LIST) { + ParserRuleContext parentCtx; + parentCtx = getParentContext(); + if (parentCtx == ParserRuleContext.PARAM_LIST) { endContext(); // end parameters return ParserRuleContext.FUNC_OPTIONAL_RETURNS; } else if (isParameter(parentCtx)) { @@ -4396,9 +4374,7 @@ private ParserRuleContext getNextRuleForCloseParenthesis() { private ParserRuleContext getNextRuleForOpenParenthesis() { ParserRuleContext parentCtx = getParentContext(); - if (parentCtx == ParserRuleContext.STREAM_RECEIVE_RHS) { - return ParserRuleContext.PEER_WORKER_NAME; - } else if (parentCtx == ParserRuleContext.EXPRESSION_STATEMENT) { + if (parentCtx == ParserRuleContext.EXPRESSION_STATEMENT) { return ParserRuleContext.EXPRESSION_STATEMENT_START; } else if (isStatement(parentCtx) || isExpressionContext(parentCtx) || parentCtx == ParserRuleContext.ARRAY_TYPE_DESCRIPTOR || diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java index 4ad9fe6eb5b6..7463f0a3281b 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/ParserRuleContext.java @@ -223,7 +223,7 @@ public enum ParserRuleContext { REMOTE_OR_RESOURCE_CALL_OR_ASYNC_SEND_RHS("remote-or-resource-call-or-async-send-rhs"), REMOTE_CALL_OR_ASYNC_SEND_END("remote-call-or-async-send-end"), DEFAULT_WORKER_NAME_IN_ASYNC_SEND("default-worker-name-in-async-send"), - RECEIVE_ACTION_RHS("receive-action-rhs"), + RECEIVE_WORKERS("receive-workers"), MULTI_RECEIVE_WORKERS("multi-receive-workers"), RECEIVE_FIELD_END("receive-field-end"), RECEIVE_FIELD("receive-field"), @@ -733,12 +733,9 @@ public enum ParserRuleContext { OPTIONAL_TOP_LEVEL_SEMICOLON("optional-top-level-semicolon"), TUPLE_MEMBERS("tuple-members"), TUPLE_MEMBER("tuple-member"), - SINGLE_OR_ALTERNATE_RECEIVE_RHS("single-or-alternate-receive-rhs"), + SINGLE_OR_ALTERNATE_WORKER("single-or-alternate-worker"), SINGLE_OR_ALTERNATE_WORKER_SEPARATOR("single-or-alternate-worker-separator"), SINGLE_OR_ALTERNATE_WORKER_END("single-or-alternate-worker-end"), - STREAM_RECEIVE_RHS("stream-receive-rhs"), - STREAM_WORKER_SEPARATOR("stream-worker-separator"), - STREAM_WORKER_END("stream-worker-end"), ; private String value; diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java similarity index 78% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java index 63f3f4c92977..cdf5bbd00e4b 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -17,7 +17,7 @@ */ package io.ballerina.compiler.internal.parser.tree; -import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NonTerminalNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; @@ -30,20 +30,20 @@ * * @since 2201.9.0 */ -public class STAlternateReceiveNode extends STNode { +public class STAlternateReceiveWorkerNode extends STNode { public final STNode workers; - STAlternateReceiveNode( + STAlternateReceiveWorkerNode( STNode workers) { this( workers, Collections.emptyList()); } - STAlternateReceiveNode( + STAlternateReceiveWorkerNode( STNode workers, Collection diagnostics) { - super(SyntaxKind.ALTERNATE_RECEIVE, diagnostics); + super(SyntaxKind.ALTERNATE_RECEIVE_WORKER, diagnostics); this.workers = workers; addChildren( @@ -51,25 +51,25 @@ public class STAlternateReceiveNode extends STNode { } public STNode modifyWith(Collection diagnostics) { - return new STAlternateReceiveNode( + return new STAlternateReceiveWorkerNode( this.workers, diagnostics); } - public STAlternateReceiveNode modify( + public STAlternateReceiveWorkerNode modify( STNode workers) { if (checkForReferenceEquality( workers)) { return this; } - return new STAlternateReceiveNode( + return new STAlternateReceiveWorkerNode( workers, diagnostics); } public Node createFacade(int position, NonTerminalNode parent) { - return new AlternateReceiveNode(this, position, parent); + return new AlternateReceiveWorkerNode(this, position, parent); } @Override diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index 3e758e91c0a1..9dd731622273 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -1826,10 +1826,10 @@ public static STNode createReceiveFieldsNode( closeBrace); } - public static STNode createAlternateReceiveNode( + public static STNode createAlternateReceiveWorkerNode( STNode workers) { - return new STAlternateReceiveNode( + return new STAlternateReceiveWorkerNode( workers); } @@ -2730,25 +2730,5 @@ public static STNode createReceiveFieldNode( colon, peerWorker); } - - public static STNode createStreamReceiveNode( - STNode streamKeyword, - STNode openParenthesis, - STNode workers, - STNode closeParenthesis) { - - return new STStreamReceiveNode( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - - public static STNode createSingleReceiveNode( - STNode worker) { - - return new STSingleReceiveNode( - worker); - } } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java index 28394b8054e1..295e3c84c5c2 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java @@ -621,8 +621,8 @@ public T transform(STReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(STAlternateReceiveNode alternateReceiveNode) { - return transformSyntaxNode(alternateReceiveNode); + public T transform(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + return transformSyntaxNode(alternateReceiveWorkerNode); } public T transform(STRestDescriptorNode restDescriptorNode) { @@ -945,14 +945,6 @@ public T transform(STReceiveFieldNode receiveFieldNode) { return transformSyntaxNode(receiveFieldNode); } - public T transform(STStreamReceiveNode streamReceiveNode) { - return transformSyntaxNode(streamReceiveNode); - } - - public T transform(STSingleReceiveNode singleReceiveNode) { - return transformSyntaxNode(singleReceiveNode); - } - // Tokens public T transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java index fb00f619afaf..1fd5c558a1f7 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java @@ -621,8 +621,8 @@ public void visit(STReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(STAlternateReceiveNode alternateReceiveNode) { - visitSyntaxNode(alternateReceiveNode); + public void visit(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + visitSyntaxNode(alternateReceiveWorkerNode); } public void visit(STRestDescriptorNode restDescriptorNode) { @@ -945,14 +945,6 @@ public void visit(STReceiveFieldNode receiveFieldNode) { visitSyntaxNode(receiveFieldNode); } - public void visit(STStreamReceiveNode streamReceiveNode) { - visitSyntaxNode(streamReceiveNode); - } - - public void visit(STSingleReceiveNode singleReceiveNode) { - visitSyntaxNode(singleReceiveNode); - } - // STNodeList public void visit(STNodeList nodeList) { visitChildren(nodeList); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java deleted file mode 100644 index 32e4b3259509..000000000000 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STSingleReceiveNode.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * 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 - * - * 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 io.ballerina.compiler.internal.parser.tree; - -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NonTerminalNode; -import io.ballerina.compiler.syntax.tree.SingleReceiveNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; - -import java.util.Collection; -import java.util.Collections; - -/** - * This is a generated internal syntax tree node. - * - * @since 2201.9.0 - */ -public class STSingleReceiveNode extends STNode { - public final STNode worker; - - STSingleReceiveNode( - STNode worker) { - this( - worker, - Collections.emptyList()); - } - - STSingleReceiveNode( - STNode worker, - Collection diagnostics) { - super(SyntaxKind.SINGLE_RECEIVE, diagnostics); - this.worker = worker; - - addChildren( - worker); - } - - public STNode modifyWith(Collection diagnostics) { - return new STSingleReceiveNode( - this.worker, - diagnostics); - } - - public STSingleReceiveNode modify( - STNode worker) { - if (checkForReferenceEquality( - worker)) { - return this; - } - - return new STSingleReceiveNode( - worker, - diagnostics); - } - - public Node createFacade(int position, NonTerminalNode parent) { - return new SingleReceiveNode(this, position, parent); - } - - @Override - public void accept(STNodeVisitor visitor) { - visitor.visit(this); - } - - @Override - public T apply(STNodeTransformer transformer) { - return transformer.transform(this); - } -} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java deleted file mode 100644 index e7f2385d4392..000000000000 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STStreamReceiveNode.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * 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 - * - * 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 io.ballerina.compiler.internal.parser.tree; - -import io.ballerina.compiler.syntax.tree.Node; -import io.ballerina.compiler.syntax.tree.NonTerminalNode; -import io.ballerina.compiler.syntax.tree.StreamReceiveNode; -import io.ballerina.compiler.syntax.tree.SyntaxKind; - -import java.util.Collection; -import java.util.Collections; - -/** - * This is a generated internal syntax tree node. - * - * @since 2201.9.0 - */ -public class STStreamReceiveNode extends STNode { - public final STNode streamKeyword; - public final STNode openParenthesis; - public final STNode workers; - public final STNode closeParenthesis; - - STStreamReceiveNode( - STNode streamKeyword, - STNode openParenthesis, - STNode workers, - STNode closeParenthesis) { - this( - streamKeyword, - openParenthesis, - workers, - closeParenthesis, - Collections.emptyList()); - } - - STStreamReceiveNode( - STNode streamKeyword, - STNode openParenthesis, - STNode workers, - STNode closeParenthesis, - Collection diagnostics) { - super(SyntaxKind.STREAM_RECEIVE, diagnostics); - this.streamKeyword = streamKeyword; - this.openParenthesis = openParenthesis; - this.workers = workers; - this.closeParenthesis = closeParenthesis; - - addChildren( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - - public STNode modifyWith(Collection diagnostics) { - return new STStreamReceiveNode( - this.streamKeyword, - this.openParenthesis, - this.workers, - this.closeParenthesis, - diagnostics); - } - - public STStreamReceiveNode modify( - STNode streamKeyword, - STNode openParenthesis, - STNode workers, - STNode closeParenthesis) { - if (checkForReferenceEquality( - streamKeyword, - openParenthesis, - workers, - closeParenthesis)) { - return this; - } - - return new STStreamReceiveNode( - streamKeyword, - openParenthesis, - workers, - closeParenthesis, - diagnostics); - } - - public Node createFacade(int position, NonTerminalNode parent) { - return new StreamReceiveNode(this, position, parent); - } - - @Override - public void accept(STNodeVisitor visitor) { - visitor.visit(this); - } - - @Override - public T apply(STNodeTransformer transformer) { - return transformer.transform(this); - } -} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index 88ac4ad28f95..be89fe8f2121 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -1956,10 +1956,10 @@ public STReceiveFieldsNode transform( } @Override - public STAlternateReceiveNode transform( - STAlternateReceiveNode alternateReceiveNode) { - STNode workers = modifyNode(alternateReceiveNode.workers); - return alternateReceiveNode.modify( + public STAlternateReceiveWorkerNode transform( + STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { + STNode workers = modifyNode(alternateReceiveWorkerNode.workers); + return alternateReceiveWorkerNode.modify( workers); } @@ -2937,28 +2937,6 @@ public STReceiveFieldNode transform( peerWorker); } - @Override - public STStreamReceiveNode transform( - STStreamReceiveNode streamReceiveNode) { - STNode streamKeyword = modifyNode(streamReceiveNode.streamKeyword); - STNode openParenthesis = modifyNode(streamReceiveNode.openParenthesis); - STNode workers = modifyNode(streamReceiveNode.workers); - STNode closeParenthesis = modifyNode(streamReceiveNode.closeParenthesis); - return streamReceiveNode.modify( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - - @Override - public STSingleReceiveNode transform( - STSingleReceiveNode singleReceiveNode) { - STNode worker = modifyNode(singleReceiveNode.worker); - return singleReceiveNode.modify( - worker); - } - // Tokens public STToken transform(STToken token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java similarity index 73% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java index c8f94dad42cd..9faf603d867d 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -26,9 +26,9 @@ * * @since 2201.9.0 */ -public class AlternateReceiveNode extends NonTerminalNode { +public class AlternateReceiveWorkerNode extends NonTerminalNode { - public AlternateReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { + public AlternateReceiveWorkerNode(STNode internalNode, int position, NonTerminalNode parent) { super(internalNode, position, parent); } @@ -52,19 +52,19 @@ protected String[] childNames() { "workers"}; } - public AlternateReceiveNode modify( + public AlternateReceiveWorkerNode modify( SeparatedNodeList workers) { if (checkForReferenceEquality( workers.underlyingListNode())) { return this; } - return NodeFactory.createAlternateReceiveNode( + return NodeFactory.createAlternateReceiveWorkerNode( workers); } - public AlternateReceiveNodeModifier modify() { - return new AlternateReceiveNodeModifier(this); + public AlternateReceiveWorkerNodeModifier modify() { + return new AlternateReceiveWorkerNodeModifier(this); } /** @@ -72,23 +72,23 @@ public AlternateReceiveNodeModifier modify() { * * @since 2201.9.0 */ - public static class AlternateReceiveNodeModifier { - private final AlternateReceiveNode oldNode; + public static class AlternateReceiveWorkerNodeModifier { + private final AlternateReceiveWorkerNode oldNode; private SeparatedNodeList workers; - public AlternateReceiveNodeModifier(AlternateReceiveNode oldNode) { + public AlternateReceiveWorkerNodeModifier(AlternateReceiveWorkerNode oldNode) { this.oldNode = oldNode; this.workers = oldNode.workers(); } - public AlternateReceiveNodeModifier withWorkers( + public AlternateReceiveWorkerNodeModifier withWorkers( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); this.workers = workers; return this; } - public AlternateReceiveNode apply() { + public AlternateReceiveWorkerNode apply() { return oldNode.modify( workers); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index a49fcbad3117..b11a56354eaf 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -2430,13 +2430,13 @@ public static ReceiveFieldsNode createReceiveFieldsNode( return stReceiveFieldsNode.createUnlinkedFacade(); } - public static AlternateReceiveNode createAlternateReceiveNode( + public static AlternateReceiveWorkerNode createAlternateReceiveWorkerNode( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); - STNode stAlternateReceiveNode = STNodeFactory.createAlternateReceiveNode( + STNode stAlternateReceiveWorkerNode = STNodeFactory.createAlternateReceiveWorkerNode( workers.underlyingListNode().internalNode()); - return stAlternateReceiveNode.createUnlinkedFacade(); + return stAlternateReceiveWorkerNode.createUnlinkedFacade(); } public static RestDescriptorNode createRestDescriptorNode( @@ -3637,31 +3637,5 @@ public static ReceiveFieldNode createReceiveFieldNode( peerWorker.internalNode()); return stReceiveFieldNode.createUnlinkedFacade(); } - - public static StreamReceiveNode createStreamReceiveNode( - Token streamKeyword, - Token openParenthesis, - SeparatedNodeList workers, - Token closeParenthesis) { - Objects.requireNonNull(streamKeyword, "streamKeyword must not be null"); - Objects.requireNonNull(openParenthesis, "openParenthesis must not be null"); - Objects.requireNonNull(workers, "workers must not be null"); - Objects.requireNonNull(closeParenthesis, "closeParenthesis must not be null"); - - STNode stStreamReceiveNode = STNodeFactory.createStreamReceiveNode( - streamKeyword.internalNode(), - openParenthesis.internalNode(), - workers.underlyingListNode().internalNode(), - closeParenthesis.internalNode()); - return stStreamReceiveNode.createUnlinkedFacade(); - } - - public static SingleReceiveNode createSingleReceiveNode( - SimpleNameReferenceNode worker) { - Objects.requireNonNull(worker, "worker must not be null"); - - STNode stSingleReceiveNode = STNodeFactory.createSingleReceiveNode( - worker.internalNode()); - return stSingleReceiveNode.createUnlinkedFacade(); - } } + diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java index 726778d6ddd5..d0557866aaf9 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java @@ -632,8 +632,8 @@ public T transform(ReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(AlternateReceiveNode alternateReceiveNode) { - return transformSyntaxNode(alternateReceiveNode); + public T transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + return transformSyntaxNode(alternateReceiveWorkerNode); } public T transform(RestDescriptorNode restDescriptorNode) { @@ -956,14 +956,6 @@ public T transform(ReceiveFieldNode receiveFieldNode) { return transformSyntaxNode(receiveFieldNode); } - public T transform(StreamReceiveNode streamReceiveNode) { - return transformSyntaxNode(streamReceiveNode); - } - - public T transform(SingleReceiveNode singleReceiveNode) { - return transformSyntaxNode(singleReceiveNode); - } - // Tokens public T transform(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java index ec48cdfd9ce3..7b41a3d8d075 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java @@ -631,8 +631,8 @@ public void visit(ReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(AlternateReceiveNode alternateReceiveNode) { - visitSyntaxNode(alternateReceiveNode); + public void visit(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + visitSyntaxNode(alternateReceiveWorkerNode); } public void visit(RestDescriptorNode restDescriptorNode) { @@ -955,14 +955,6 @@ public void visit(ReceiveFieldNode receiveFieldNode) { visitSyntaxNode(receiveFieldNode); } - public void visit(StreamReceiveNode streamReceiveNode) { - visitSyntaxNode(streamReceiveNode); - } - - public void visit(SingleReceiveNode singleReceiveNode) { - visitSyntaxNode(singleReceiveNode); - } - // Tokens public void visit(Token token) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java deleted file mode 100644 index 2f53f65a3e2c..000000000000 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SingleReceiveNode.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * 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 - * - * 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 io.ballerina.compiler.syntax.tree; - -import io.ballerina.compiler.internal.parser.tree.STNode; - -import java.util.Objects; - -/** - * This is a generated syntax tree node. - * - * @since 2201.9.0 - */ -public class SingleReceiveNode extends NonTerminalNode { - - public SingleReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { - super(internalNode, position, parent); - } - - public SimpleNameReferenceNode worker() { - return childInBucket(0); - } - - @Override - public void accept(NodeVisitor visitor) { - visitor.visit(this); - } - - @Override - public T apply(NodeTransformer visitor) { - return visitor.transform(this); - } - - @Override - protected String[] childNames() { - return new String[]{ - "worker"}; - } - - public SingleReceiveNode modify( - SimpleNameReferenceNode worker) { - if (checkForReferenceEquality( - worker)) { - return this; - } - - return NodeFactory.createSingleReceiveNode( - worker); - } - - public SingleReceiveNodeModifier modify() { - return new SingleReceiveNodeModifier(this); - } - - /** - * This is a generated tree node modifier utility. - * - * @since 2201.9.0 - */ - public static class SingleReceiveNodeModifier { - private final SingleReceiveNode oldNode; - private SimpleNameReferenceNode worker; - - public SingleReceiveNodeModifier(SingleReceiveNode oldNode) { - this.oldNode = oldNode; - this.worker = oldNode.worker(); - } - - public SingleReceiveNodeModifier withWorker( - SimpleNameReferenceNode worker) { - Objects.requireNonNull(worker, "worker must not be null"); - this.worker = worker; - return this; - } - - public SingleReceiveNode apply() { - return oldNode.modify( - worker); - } - } -} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java deleted file mode 100644 index c476b6d8f56b..000000000000 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/StreamReceiveNode.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). - * - * 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 - * - * 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 io.ballerina.compiler.syntax.tree; - -import io.ballerina.compiler.internal.parser.tree.STNode; - -import java.util.Objects; - -/** - * This is a generated syntax tree node. - * - * @since 2201.9.0 - */ -public class StreamReceiveNode extends NonTerminalNode { - - public StreamReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { - super(internalNode, position, parent); - } - - public Token streamKeyword() { - return childInBucket(0); - } - - public Token openParenthesis() { - return childInBucket(1); - } - - public SeparatedNodeList workers() { - return new SeparatedNodeList<>(childInBucket(2)); - } - - public Token closeParenthesis() { - return childInBucket(3); - } - - @Override - public void accept(NodeVisitor visitor) { - visitor.visit(this); - } - - @Override - public T apply(NodeTransformer visitor) { - return visitor.transform(this); - } - - @Override - protected String[] childNames() { - return new String[]{ - "streamKeyword", - "openParenthesis", - "workers", - "closeParenthesis"}; - } - - public StreamReceiveNode modify( - Token streamKeyword, - Token openParenthesis, - SeparatedNodeList workers, - Token closeParenthesis) { - if (checkForReferenceEquality( - streamKeyword, - openParenthesis, - workers.underlyingListNode(), - closeParenthesis)) { - return this; - } - - return NodeFactory.createStreamReceiveNode( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - - public StreamReceiveNodeModifier modify() { - return new StreamReceiveNodeModifier(this); - } - - /** - * This is a generated tree node modifier utility. - * - * @since 2201.9.0 - */ - public static class StreamReceiveNodeModifier { - private final StreamReceiveNode oldNode; - private Token streamKeyword; - private Token openParenthesis; - private SeparatedNodeList workers; - private Token closeParenthesis; - - public StreamReceiveNodeModifier(StreamReceiveNode oldNode) { - this.oldNode = oldNode; - this.streamKeyword = oldNode.streamKeyword(); - this.openParenthesis = oldNode.openParenthesis(); - this.workers = oldNode.workers(); - this.closeParenthesis = oldNode.closeParenthesis(); - } - - public StreamReceiveNodeModifier withStreamKeyword( - Token streamKeyword) { - Objects.requireNonNull(streamKeyword, "streamKeyword must not be null"); - this.streamKeyword = streamKeyword; - return this; - } - - public StreamReceiveNodeModifier withOpenParenthesis( - Token openParenthesis) { - Objects.requireNonNull(openParenthesis, "openParenthesis must not be null"); - this.openParenthesis = openParenthesis; - return this; - } - - public StreamReceiveNodeModifier withWorkers( - SeparatedNodeList workers) { - Objects.requireNonNull(workers, "workers must not be null"); - this.workers = workers; - return this; - } - - public StreamReceiveNodeModifier withCloseParenthesis( - Token closeParenthesis) { - Objects.requireNonNull(closeParenthesis, "closeParenthesis must not be null"); - this.closeParenthesis = closeParenthesis; - return this; - } - - public StreamReceiveNode apply() { - return oldNode.modify( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - } -} diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java index c03b1a64044f..84edbf974023 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java @@ -484,10 +484,8 @@ public enum SyntaxKind { GROUPING_KEY_VAR_NAME(3092), GROUP_BY_CLAUSE(3093), COLLECT_CLAUSE(3094), - ALTERNATE_RECEIVE(3095), + ALTERNATE_RECEIVE_WORKER(3095), RECEIVE_FIELD(3096), - STREAM_RECEIVE(3097), - SINGLE_RECEIVE(3098), // XML XML_ELEMENT(4000), diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index a2e782f98e7e..ad1fab524d3d 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -2475,11 +2475,11 @@ public ReceiveFieldsNode transform( } @Override - public AlternateReceiveNode transform( - AlternateReceiveNode alternateReceiveNode) { + public AlternateReceiveWorkerNode transform( + AlternateReceiveWorkerNode alternateReceiveWorkerNode) { SeparatedNodeList workers = - modifySeparatedNodeList(alternateReceiveNode.workers()); - return alternateReceiveNode.modify( + modifySeparatedNodeList(alternateReceiveWorkerNode.workers()); + return alternateReceiveWorkerNode.modify( workers); } @@ -3702,33 +3702,6 @@ public ReceiveFieldNode transform( peerWorker); } - @Override - public StreamReceiveNode transform( - StreamReceiveNode streamReceiveNode) { - Token streamKeyword = - modifyToken(streamReceiveNode.streamKeyword()); - Token openParenthesis = - modifyToken(streamReceiveNode.openParenthesis()); - SeparatedNodeList workers = - modifySeparatedNodeList(streamReceiveNode.workers()); - Token closeParenthesis = - modifyToken(streamReceiveNode.closeParenthesis()); - return streamReceiveNode.modify( - streamKeyword, - openParenthesis, - workers, - closeParenthesis); - } - - @Override - public SingleReceiveNode transform( - SingleReceiveNode singleReceiveNode) { - SimpleNameReferenceNode worker = - modifyNode(singleReceiveNode.worker()); - return singleReceiveNode.modify( - worker); - } - // Tokens @Override diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java index 9c1b032b10dc..e318d246cda2 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java @@ -633,12 +633,8 @@ private static SyntaxKind getNodeKind(String kind) { return SyntaxKind.COMPUTED_RESOURCE_ACCESS_SEGMENT; case "RESOURCE_ACCESS_REST_SEGMENT": return SyntaxKind.RESOURCE_ACCESS_REST_SEGMENT; - case "ALTERNATE_RECEIVE": - return SyntaxKind.ALTERNATE_RECEIVE; - case "STREAM_RECEIVE": - return SyntaxKind.STREAM_RECEIVE; - case "SINGLE_RECEIVE": - return SyntaxKind.SINGLE_RECEIVE; + case "ALTERNATE_RECEIVE_WORKER": + return SyntaxKind.ALTERNATE_RECEIVE_WORKER; case "RECEIVE_FIELD": return SyntaxKind.RECEIVE_FIELD; diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java index f9b0d921a774..446896beb7c9 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/actions/ReceiveActionTest.java @@ -38,11 +38,6 @@ public void testAlternateReceiveAction() { testFile("receive-action/receive_action_source_04.bal", "receive-action/receive_action_assert_04.json"); } - @Test - public void testStreamReceiveAction() { - testFile("receive-action/receive_action_source_06.bal", "receive-action/receive_action_assert_06.json"); - } - // Recover tests @Test @@ -59,9 +54,4 @@ public void testInvalidNodeInReceiveAction() { public void testAlternateReceiveActionRecovery() { testFile("receive-action/receive_action_source_05.bal", "receive-action/receive_action_assert_05.json"); } - - @Test - public void testStreamReceiveActionRecovery() { - testFile("receive-action/receive_action_source_07.bal", "receive-action/receive_action_assert_07.json"); - } } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json index 87a1ed4e266f..0614217f73ce 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_01.json @@ -80,15 +80,10 @@ ] }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD" - } - ] + "kind": "FUNCTION_KEYWORD" } ] } @@ -127,16 +122,11 @@ ] }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "b" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "b" } ] } @@ -199,16 +189,11 @@ ] }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "b" - } - ] + "kind": "IDENTIFIER_TOKEN", + "value": "b" } ] } diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json index fdcc7307c187..d3fa057f8f2f 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_02.json @@ -79,21 +79,15 @@ ] }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - } + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" ] } ] @@ -153,21 +147,15 @@ "kind": "LEFT_ARROW_TOKEN" }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - } + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" ] } ] diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 9743ea8f002f..19961f156696 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -186,7 +186,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -325,7 +325,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -400,7 +400,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -525,7 +525,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -672,7 +672,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -772,7 +772,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", @@ -920,7 +920,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "children": [ { "kind": "LIST", diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json index 4f7122368510..4ae969c3f442 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json @@ -85,7 +85,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "hasDiagnostics": true, "children": [ { @@ -260,7 +260,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "hasDiagnostics": true, "children": [ { @@ -430,7 +430,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "hasDiagnostics": true, "children": [ { diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json deleted file mode 100644 index 87d5f15449fd..000000000000 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_06.json +++ /dev/null @@ -1,1074 +0,0 @@ -{ - "kind": "FUNCTION_DEFINITION", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "foo" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "NAMED_WORKER_DECLARATOR", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "NAMED_WORKER_DECLARATION", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "WORKER_KEYWORD", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "E", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "BLOCK_STATEMENT", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "FOREACH_STATEMENT", - "children": [ - { - "kind": "FOREACH_KEYWORD", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "VAR_TYPE_DESC", - "children": [ - { - "kind": "VAR_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "err", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "IN_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "BLOCK_STATEMENT", - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_BRACE_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "leadingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - }, - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "C", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "D" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ACTION_STATEMENT", - "children": [ - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "D" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "C" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "INT_TYPE_DESC", - "children": [ - { - "kind": "INT_KEYWORD", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "b", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "C" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] -} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json deleted file mode 100644 index 819947e4ce86..000000000000 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_07.json +++ /dev/null @@ -1,802 +0,0 @@ -{ - "kind": "FUNCTION_DEFINITION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "IDENTIFIER_TOKEN", - "value": "bar" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "FUNCTION_SIGNATURE", - "children": [ - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "FUNCTION_BODY_BLOCK", - "hasDiagnostics": true, - "children": [ - { - "kind": "OPEN_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - }, - { - "kind": "LIST", - "hasDiagnostics": true, - "children": [ - { - "kind": "ACTION_STATEMENT", - "hasDiagnostics": true, - "children": [ - { - "kind": "RECEIVE_ACTION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "hasDiagnostics": true, - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "hasDiagnostics": true, - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ], - "leadingMinutiae": [ - { - "kind": "INVALID_NODE_MINUTIAE", - "invalidNode": { - "kind": "INVALID_TOKEN_MINUTIAE_NODE", - "hasDiagnostics": true, - "children": [ - { - "kind": "IMPORT_KEYWORD", - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_INVALID_TOKEN" - ] - } - ] - } - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "C", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "D" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "hasDiagnostics": true, - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "hasDiagnostics": true, - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "hasDiagnostics": true, - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ], - "leadingMinutiae": [ - { - "kind": "INVALID_NODE_MINUTIAE", - "invalidNode": { - "kind": "INVALID_TOKEN_MINUTIAE_NODE", - "hasDiagnostics": true, - "children": [ - { - "kind": "IMPORT_KEYWORD", - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_INVALID_TOKEN" - ] - } - ] - } - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "D" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN" - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "hasDiagnostics": true, - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "hasDiagnostics": true, - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_OPEN_PAREN_TOKEN" - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_CLOSE_PAREN_TOKEN" - ] - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "ASSIGNMENT_STATEMENT", - "hasDiagnostics": true, - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "hasDiagnostics": true, - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_OPEN_PAREN_TOKEN" - ] - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "PIPE_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "B" - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_CLOSE_PAREN_TOKEN" - ] - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - }, - { - "kind": "LOCAL_VAR_DECL", - "hasDiagnostics": true, - "children": [ - { - "kind": "LIST", - "children": [] - }, - { - "kind": "TYPED_BINDING_PATTERN", - "children": [ - { - "kind": "INT_TYPE_DESC", - "children": [ - { - "kind": "INT_KEYWORD", - "leadingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ], - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - }, - { - "kind": "CAPTURE_BINDING_PATTERN", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "a", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "EQUAL_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "RECEIVE_ACTION", - "hasDiagnostics": true, - "children": [ - { - "kind": "LEFT_ARROW_TOKEN", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "STREAM_RECEIVE", - "hasDiagnostics": true, - "children": [ - { - "kind": "STREAM_KEYWORD", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - }, - { - "kind": "OPEN_PAREN_TOKEN" - }, - { - "kind": "LIST", - "children": [ - { - "kind": "SIMPLE_NAME_REFERENCE", - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "value": "A", - "trailingMinutiae": [ - { - "kind": "WHITESPACE_MINUTIAE", - "value": " " - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_PAREN_TOKEN", - "hasDiagnostics": true, - "leadingMinutiae": [ - { - "kind": "INVALID_NODE_MINUTIAE", - "invalidNode": { - "kind": "INVALID_TOKEN_MINUTIAE_NODE", - "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_INVALID_TOKEN" - ], - "value": "B" - } - ] - } - } - ] - } - ] - } - ] - }, - { - "kind": "SEMICOLON_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] - }, - { - "kind": "CLOSE_BRACE_TOKEN", - "trailingMinutiae": [ - { - "kind": "END_OF_LINE_MINUTIAE", - "value": "\n" - } - ] - } - ] - } - ] -} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal deleted file mode 100644 index 73bccf465337..000000000000 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_06.bal +++ /dev/null @@ -1,13 +0,0 @@ -function foo() { - worker E { - foreach var err in <- stream (A | B) { - } - } - - <- stream (function | function); - <- stream (A | B | C | D); - <- stream (A | function | D); - a = <- stream (function | A); - a = <- stream (A | B | C); - int b = <- stream (B | C); -} diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal deleted file mode 100644 index ec0bc71423a1..000000000000 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_source_07.bal +++ /dev/null @@ -1,7 +0,0 @@ -function bar() { - <- stream (A | import| C | D); - a = <- stream (A | B | import| D); - a = <- stream A; - a = <- stream A | B; - int a = <- stream (A B); -} diff --git a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json index 16a3f949203c..d92545238d4f 100644 --- a/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json +++ b/compiler/ballerina-parser/src/test/resources/misc/completion/completion_assert_08.json @@ -1039,21 +1039,15 @@ ] }, { - "kind": "SINGLE_RECEIVE", + "kind": "SIMPLE_NAME_REFERENCE", "hasDiagnostics": true, "children": [ { - "kind": "SIMPLE_NAME_REFERENCE", + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, "hasDiagnostics": true, - "children": [ - { - "kind": "IDENTIFIER_TOKEN", - "isMissing": true, - "hasDiagnostics": true, - "diagnostics": [ - "ERROR_MISSING_IDENTIFIER" - ] - } + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" ] } ] diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index 88e548f67246..ea69efacd564 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -1,14 +1,6 @@ { - "SingleReceiveNode": { - "createdYear": "2024", - "since": "2201.9.0" - }, - "StreamReceiveNode": { - "createdYear": "2024", - "since": "2201.9.0" - }, - "AlternateReceiveNode": { - "createdYear": "2024", + "AlternateReceiveWorkerNode": { + "createdYear": "2023", "since": "2201.9.0" }, "ClientResourceActionNode": { diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 53a0b59ecb8d..97d843298269 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveNode", + "name": "AlternateReceiveWorkerNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "attributes": [ { "name": "workers", @@ -4976,41 +4976,6 @@ "type": "SimpleNameReferenceNode" } ] - }, - { - "name": "StreamReceiveNode", - "base": "Node", - "kind": "STREAM_RECEIVE", - "attributes": [ - { - "name": "streamKeyword", - "type": "Token" - }, - { - "name": "openParenthesis", - "type": "Token" - }, - { - "name": "workers", - "type": "SimpleNameReferenceNode", - "occurrences": "MULTIPLE_SEPARATED" - }, - { - "name": "closeParenthesis", - "type": "Token" - } - ] - }, - { - "name": "SingleReceiveNode", - "base": "Node", - "kind": "SINGLE_RECEIVE", - "attributes": [ - { - "name": "worker", - "type": "SimpleNameReferenceNode" - } - ] } ] } diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 27a4af5d12d4..6636979456fd 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -17,7 +17,7 @@ */ package org.ballerinalang.formatter.core; -import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -189,14 +189,12 @@ import io.ballerina.compiler.syntax.tree.SeparatedNodeList; import io.ballerina.compiler.syntax.tree.ServiceDeclarationNode; import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode; -import io.ballerina.compiler.syntax.tree.SingleReceiveNode; import io.ballerina.compiler.syntax.tree.SingletonTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.SpecificFieldNode; import io.ballerina.compiler.syntax.tree.SpreadFieldNode; import io.ballerina.compiler.syntax.tree.SpreadMemberNode; import io.ballerina.compiler.syntax.tree.StartActionNode; import io.ballerina.compiler.syntax.tree.StatementNode; -import io.ballerina.compiler.syntax.tree.StreamReceiveNode; import io.ballerina.compiler.syntax.tree.StreamTypeDescriptorNode; import io.ballerina.compiler.syntax.tree.StreamTypeParamsNode; import io.ballerina.compiler.syntax.tree.SyncSendActionNode; @@ -3031,7 +3029,7 @@ public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { } @Override - public AlternateReceiveNode transform(AlternateReceiveNode alternateReceiveWorkerNode) { + public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { SeparatedNodeList workers = formatSeparatedNodeList(alternateReceiveWorkerNode.workers(), 1, 0, env.trailingWS, env.trailingNL); return alternateReceiveWorkerNode.modify() @@ -3039,29 +3037,6 @@ public AlternateReceiveNode transform(AlternateReceiveNode alternateReceiveWorke .apply(); } - @Override - public SingleReceiveNode transform(SingleReceiveNode singleReceiveNode) { - SimpleNameReferenceNode worker = formatNode(singleReceiveNode.worker(), env.trailingWS, env.trailingNL); - return singleReceiveNode.modify() - .withWorker(worker) - .apply(); - } - - @Override - public StreamReceiveNode transform(StreamReceiveNode streamReceiveNode) { - Token streamKeyword = formatToken(streamReceiveNode.streamKeyword(), 1, 0); - Token openParenthesis = formatToken(streamReceiveNode.openParenthesis(), 0, 0); - SeparatedNodeList workers = - formatSeparatedNodeList(streamReceiveNode.workers(), 1, 0, 0, 0); - Token closeParenthesis = formatToken(streamReceiveNode.closeParenthesis(), env.trailingWS, env.trailingNL); - return streamReceiveNode.modify() - .withStreamKeyword(streamKeyword) - .withOpenParenthesis(openParenthesis) - .withWorkers(workers) - .withCloseParenthesis(closeParenthesis) - .apply(); - } - @Override public ReceiveFieldNode transform(ReceiveFieldNode receiveFieldNode) { SimpleNameReferenceNode fieldName = formatNode(receiveFieldNode.fieldName(), 0, 0); diff --git a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java index 0efb89b92c5b..6f06b62f41dd 100644 --- a/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java +++ b/misc/formatter/modules/formatter-core/src/test/java/org/ballerinalang/formatter/core/ParserTestFormatter.java @@ -92,7 +92,7 @@ public List skipList() { // The following tests are disabled due to tokens merging together after formatting. issue #35240 "query_expr_source_121.bal", "query_expr_source_123.bal", "query_expr_source_124.bal", "query_expr_source_126.bal", "match_stmt_source_21.bal", - "func_params_source_27.bal", "receive_action_source_07.bal", + "func_params_source_27.bal", "separated_node_list_import_decl.bal", "node_location_test_03.bal", diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index e0e4c20ae861..72f8496140b0 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveNode", + "name": "AlternateReceiveWorkerNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE", + "kind": "ALTERNATE_RECEIVE_WORKER", "attributes": [ { "name": "workers", @@ -4976,41 +4976,6 @@ "type": "SimpleNameReferenceNode" } ] - }, - { - "name": "StreamReceiveNode", - "base": "Node", - "kind": "STREAM_RECEIVE", - "attributes": [ - { - "name": "streamKeyword", - "type": "Token" - }, - { - "name": "openParenthesis", - "type": "Token" - }, - { - "name": "workers", - "type": "SimpleNameReferenceNode", - "occurrences": "MULTIPLE_SEPARATED" - }, - { - "name": "closeParenthesis", - "type": "Token" - } - ] - }, - { - "name": "SingleReceiveNode", - "base": "Node", - "kind": "SINGLE_RECEIVE", - "attributes": [ - { - "name": "worker", - "type": "SimpleNameReferenceNode" - } - ] } ] } From 225f2f09e907bcb07da70cd5707b5c28984eb728 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:28:29 +0530 Subject: [PATCH 84/97] Rename AlternateWorkerReceiveNode to AlternateReceiveNode --- .../compiler/parser/BLangNodeBuilder.java | 6 ++--- .../internal/parser/BallerinaParser.java | 2 +- ...rNode.java => STAlternateReceiveNode.java} | 20 ++++++++-------- .../internal/parser/tree/STNodeFactory.java | 4 ++-- .../parser/tree/STNodeTransformer.java | 4 ++-- .../internal/parser/tree/STNodeVisitor.java | 4 ++-- .../internal/parser/tree/STTreeModifier.java | 8 +++---- ...kerNode.java => AlternateReceiveNode.java} | 24 +++++++++---------- .../compiler/syntax/tree/NodeFactory.java | 6 ++--- .../compiler/syntax/tree/NodeTransformer.java | 4 ++-- .../compiler/syntax/tree/NodeVisitor.java | 4 ++-- .../compiler/syntax/tree/SyntaxKind.java | 2 +- .../compiler/syntax/tree/TreeModifier.java | 8 +++---- .../compiler/parser/test/ParserTestUtils.java | 4 ++-- .../receive_action_assert_04.json | 14 +++++------ .../receive_action_assert_05.json | 6 ++--- .../main/resources/syntax_node_metadata.json | 4 ++-- .../resources/syntax_tree_descriptor.json | 4 ++-- .../core/FormattingTreeModifier.java | 8 +++---- .../api_gen_syntax_tree_descriptor.json | 4 ++-- 20 files changed, 70 insertions(+), 70 deletions(-) rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/{STAlternateReceiveWorkerNode.java => STAlternateReceiveNode.java} (78%) rename compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/{AlternateReceiveWorkerNode.java => AlternateReceiveNode.java} (73%) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java index 3eacef322e81..c62d64eaddb8 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/parser/BLangNodeBuilder.java @@ -17,7 +17,7 @@ */ package org.wso2.ballerinalang.compiler.parser; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -2534,9 +2534,9 @@ public BLangNode transform(ReceiveActionNode receiveActionNode) { return singleWorkerRecv; } - if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE_WORKER) { + if (receiveWorkers.kind() == SyntaxKind.ALTERNATE_RECEIVE) { SeparatedNodeList alternateWorkers = - ((AlternateReceiveWorkerNode) receiveWorkers).workers(); + ((AlternateReceiveNode) receiveWorkers).workers(); List workerReceives = new ArrayList<>(alternateWorkers.size()); for (SimpleNameReferenceNode w : alternateWorkers) { workerReceives.add(createSimpleWorkerReceive(w.name())); diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 4c06f11a3c28..facb4a98ca56 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -13122,7 +13122,7 @@ private STNode parseSingleOrAlternateReceiveWorkers() { } endContext(); - return STNodeFactory.createAlternateReceiveWorkerNode(STNodeFactory.createNodeList(workers)); + return STNodeFactory.createAlternateReceiveNode(STNodeFactory.createNodeList(workers)); } /** diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java similarity index 78% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java index cdf5bbd00e4b..63f3f4c92977 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveWorkerNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STAlternateReceiveNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -17,7 +17,7 @@ */ package io.ballerina.compiler.internal.parser.tree; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.Node; import io.ballerina.compiler.syntax.tree.NonTerminalNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; @@ -30,20 +30,20 @@ * * @since 2201.9.0 */ -public class STAlternateReceiveWorkerNode extends STNode { +public class STAlternateReceiveNode extends STNode { public final STNode workers; - STAlternateReceiveWorkerNode( + STAlternateReceiveNode( STNode workers) { this( workers, Collections.emptyList()); } - STAlternateReceiveWorkerNode( + STAlternateReceiveNode( STNode workers, Collection diagnostics) { - super(SyntaxKind.ALTERNATE_RECEIVE_WORKER, diagnostics); + super(SyntaxKind.ALTERNATE_RECEIVE, diagnostics); this.workers = workers; addChildren( @@ -51,25 +51,25 @@ public class STAlternateReceiveWorkerNode extends STNode { } public STNode modifyWith(Collection diagnostics) { - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( this.workers, diagnostics); } - public STAlternateReceiveWorkerNode modify( + public STAlternateReceiveNode modify( STNode workers) { if (checkForReferenceEquality( workers)) { return this; } - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( workers, diagnostics); } public Node createFacade(int position, NonTerminalNode parent) { - return new AlternateReceiveWorkerNode(this, position, parent); + return new AlternateReceiveNode(this, position, parent); } @Override diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java index 9dd731622273..8c058ad27a02 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeFactory.java @@ -1826,10 +1826,10 @@ public static STNode createReceiveFieldsNode( closeBrace); } - public static STNode createAlternateReceiveWorkerNode( + public static STNode createAlternateReceiveNode( STNode workers) { - return new STAlternateReceiveWorkerNode( + return new STAlternateReceiveNode( workers); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java index 295e3c84c5c2..47e6111e1b2e 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeTransformer.java @@ -621,8 +621,8 @@ public T transform(STReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - return transformSyntaxNode(alternateReceiveWorkerNode); + public T transform(STAlternateReceiveNode alternateReceiveNode) { + return transformSyntaxNode(alternateReceiveNode); } public T transform(STRestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java index 1fd5c558a1f7..9f9794d78313 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STNodeVisitor.java @@ -621,8 +621,8 @@ public void visit(STReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - visitSyntaxNode(alternateReceiveWorkerNode); + public void visit(STAlternateReceiveNode alternateReceiveNode) { + visitSyntaxNode(alternateReceiveNode); } public void visit(STRestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java index be89fe8f2121..b64f2180dd81 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STTreeModifier.java @@ -1956,10 +1956,10 @@ public STReceiveFieldsNode transform( } @Override - public STAlternateReceiveWorkerNode transform( - STAlternateReceiveWorkerNode alternateReceiveWorkerNode) { - STNode workers = modifyNode(alternateReceiveWorkerNode.workers); - return alternateReceiveWorkerNode.modify( + public STAlternateReceiveNode transform( + STAlternateReceiveNode alternateReceiveNode) { + STNode workers = modifyNode(alternateReceiveNode.workers); + return alternateReceiveNode.modify( workers); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java similarity index 73% rename from compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java rename to compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java index 9faf603d867d..c8f94dad42cd 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveWorkerNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/AlternateReceiveNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -26,9 +26,9 @@ * * @since 2201.9.0 */ -public class AlternateReceiveWorkerNode extends NonTerminalNode { +public class AlternateReceiveNode extends NonTerminalNode { - public AlternateReceiveWorkerNode(STNode internalNode, int position, NonTerminalNode parent) { + public AlternateReceiveNode(STNode internalNode, int position, NonTerminalNode parent) { super(internalNode, position, parent); } @@ -52,19 +52,19 @@ protected String[] childNames() { "workers"}; } - public AlternateReceiveWorkerNode modify( + public AlternateReceiveNode modify( SeparatedNodeList workers) { if (checkForReferenceEquality( workers.underlyingListNode())) { return this; } - return NodeFactory.createAlternateReceiveWorkerNode( + return NodeFactory.createAlternateReceiveNode( workers); } - public AlternateReceiveWorkerNodeModifier modify() { - return new AlternateReceiveWorkerNodeModifier(this); + public AlternateReceiveNodeModifier modify() { + return new AlternateReceiveNodeModifier(this); } /** @@ -72,23 +72,23 @@ public AlternateReceiveWorkerNodeModifier modify() { * * @since 2201.9.0 */ - public static class AlternateReceiveWorkerNodeModifier { - private final AlternateReceiveWorkerNode oldNode; + public static class AlternateReceiveNodeModifier { + private final AlternateReceiveNode oldNode; private SeparatedNodeList workers; - public AlternateReceiveWorkerNodeModifier(AlternateReceiveWorkerNode oldNode) { + public AlternateReceiveNodeModifier(AlternateReceiveNode oldNode) { this.oldNode = oldNode; this.workers = oldNode.workers(); } - public AlternateReceiveWorkerNodeModifier withWorkers( + public AlternateReceiveNodeModifier withWorkers( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); this.workers = workers; return this; } - public AlternateReceiveWorkerNode apply() { + public AlternateReceiveNode apply() { return oldNode.modify( workers); } diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java index b11a56354eaf..33db78359e09 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeFactory.java @@ -2430,13 +2430,13 @@ public static ReceiveFieldsNode createReceiveFieldsNode( return stReceiveFieldsNode.createUnlinkedFacade(); } - public static AlternateReceiveWorkerNode createAlternateReceiveWorkerNode( + public static AlternateReceiveNode createAlternateReceiveNode( SeparatedNodeList workers) { Objects.requireNonNull(workers, "workers must not be null"); - STNode stAlternateReceiveWorkerNode = STNodeFactory.createAlternateReceiveWorkerNode( + STNode stAlternateReceiveNode = STNodeFactory.createAlternateReceiveNode( workers.underlyingListNode().internalNode()); - return stAlternateReceiveWorkerNode.createUnlinkedFacade(); + return stAlternateReceiveNode.createUnlinkedFacade(); } public static RestDescriptorNode createRestDescriptorNode( diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java index d0557866aaf9..6a07516d87e8 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeTransformer.java @@ -632,8 +632,8 @@ public T transform(ReceiveFieldsNode receiveFieldsNode) { return transformSyntaxNode(receiveFieldsNode); } - public T transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { - return transformSyntaxNode(alternateReceiveWorkerNode); + public T transform(AlternateReceiveNode alternateReceiveNode) { + return transformSyntaxNode(alternateReceiveNode); } public T transform(RestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java index 7b41a3d8d075..1fe6ddfa596e 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/NodeVisitor.java @@ -631,8 +631,8 @@ public void visit(ReceiveFieldsNode receiveFieldsNode) { visitSyntaxNode(receiveFieldsNode); } - public void visit(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { - visitSyntaxNode(alternateReceiveWorkerNode); + public void visit(AlternateReceiveNode alternateReceiveNode) { + visitSyntaxNode(alternateReceiveNode); } public void visit(RestDescriptorNode restDescriptorNode) { diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java index 84edbf974023..f74b79a91bb3 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/SyntaxKind.java @@ -484,7 +484,7 @@ public enum SyntaxKind { GROUPING_KEY_VAR_NAME(3092), GROUP_BY_CLAUSE(3093), COLLECT_CLAUSE(3094), - ALTERNATE_RECEIVE_WORKER(3095), + ALTERNATE_RECEIVE(3095), RECEIVE_FIELD(3096), // XML diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java index ad1fab524d3d..865d3bdb6aea 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/TreeModifier.java @@ -2475,11 +2475,11 @@ public ReceiveFieldsNode transform( } @Override - public AlternateReceiveWorkerNode transform( - AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + public AlternateReceiveNode transform( + AlternateReceiveNode alternateReceiveNode) { SeparatedNodeList workers = - modifySeparatedNodeList(alternateReceiveWorkerNode.workers()); - return alternateReceiveWorkerNode.modify( + modifySeparatedNodeList(alternateReceiveNode.workers()); + return alternateReceiveNode.modify( workers); } diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java index e318d246cda2..6dc3df46bfd5 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/ParserTestUtils.java @@ -633,8 +633,8 @@ private static SyntaxKind getNodeKind(String kind) { return SyntaxKind.COMPUTED_RESOURCE_ACCESS_SEGMENT; case "RESOURCE_ACCESS_REST_SEGMENT": return SyntaxKind.RESOURCE_ACCESS_REST_SEGMENT; - case "ALTERNATE_RECEIVE_WORKER": - return SyntaxKind.ALTERNATE_RECEIVE_WORKER; + case "ALTERNATE_RECEIVE": + return SyntaxKind.ALTERNATE_RECEIVE; case "RECEIVE_FIELD": return SyntaxKind.RECEIVE_FIELD; diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json index 19961f156696..9743ea8f002f 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_04.json @@ -186,7 +186,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -325,7 +325,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -400,7 +400,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -525,7 +525,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -672,7 +672,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -772,7 +772,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", @@ -920,7 +920,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "children": [ { "kind": "LIST", diff --git a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json index 4ae969c3f442..4f7122368510 100644 --- a/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json +++ b/compiler/ballerina-parser/src/test/resources/actions/receive-action/receive_action_assert_05.json @@ -85,7 +85,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { @@ -260,7 +260,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { @@ -430,7 +430,7 @@ ] }, { - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "hasDiagnostics": true, "children": [ { diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index ea69efacd564..ec2ca5bb501e 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -1,6 +1,6 @@ { - "AlternateReceiveWorkerNode": { - "createdYear": "2023", + "AlternateReceiveNode": { + "createdYear": "2024", "since": "2201.9.0" }, "ClientResourceActionNode": { diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json index 97d843298269..69079a74ca75 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveWorkerNode", + "name": "AlternateReceiveNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "attributes": [ { "name": "workers", diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java index 6636979456fd..85c760415322 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingTreeModifier.java @@ -17,7 +17,7 @@ */ package org.ballerinalang.formatter.core; -import io.ballerina.compiler.syntax.tree.AlternateReceiveWorkerNode; +import io.ballerina.compiler.syntax.tree.AlternateReceiveNode; import io.ballerina.compiler.syntax.tree.AnnotAccessExpressionNode; import io.ballerina.compiler.syntax.tree.AnnotationAttachPointNode; import io.ballerina.compiler.syntax.tree.AnnotationDeclarationNode; @@ -3029,10 +3029,10 @@ public ReceiveFieldsNode transform(ReceiveFieldsNode receiveFieldsNode) { } @Override - public AlternateReceiveWorkerNode transform(AlternateReceiveWorkerNode alternateReceiveWorkerNode) { + public AlternateReceiveNode transform(AlternateReceiveNode alternateReceiveNode) { SeparatedNodeList workers = - formatSeparatedNodeList(alternateReceiveWorkerNode.workers(), 1, 0, env.trailingWS, env.trailingNL); - return alternateReceiveWorkerNode.modify() + formatSeparatedNodeList(alternateReceiveNode.workers(), 1, 0, env.trailingWS, env.trailingNL); + return alternateReceiveNode.modify() .withWorkers(workers) .apply(); } diff --git a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json index 72f8496140b0..c2eeb0024b7e 100644 --- a/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json +++ b/misc/syntax-api-calls-gen/src/main/resources/api_gen_syntax_tree_descriptor.json @@ -3342,9 +3342,9 @@ ] }, { - "name": "AlternateReceiveWorkerNode", + "name": "AlternateReceiveNode", "base": "Node", - "kind": "ALTERNATE_RECEIVE_WORKER", + "kind": "ALTERNATE_RECEIVE", "attributes": [ { "name": "workers", From 4e9f2f6dc4b1e8d6937158168f0bae95550b9b5e Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 7 Mar 2024 14:37:46 +0530 Subject: [PATCH 85/97] Enable full build for worker_change branch --- .github/workflows/pull_request_full_build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull_request_full_build.yml b/.github/workflows/pull_request_full_build.yml index cdc5746c7353..db1ab8e5128d 100644 --- a/.github/workflows/pull_request_full_build.yml +++ b/.github/workflows/pull_request_full_build.yml @@ -4,6 +4,7 @@ on: pull_request: branches: - master + - worker_change jobs: build-lang: From dd63236d253be73f470d290372885c68006046fb Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:56:51 +0530 Subject: [PATCH 86/97] Remove worker_change branch build --- .github/workflows/publish_timestamped_release.yml | 1 - .github/workflows/pull_request_full_build.yml | 1 - .github/workflows/pull_request_ubuntu_build.yml | 1 - .github/workflows/pull_request_windows_build.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/.github/workflows/publish_timestamped_release.yml b/.github/workflows/publish_timestamped_release.yml index 34276582b158..bd39a4f4add9 100644 --- a/.github/workflows/publish_timestamped_release.yml +++ b/.github/workflows/publish_timestamped_release.yml @@ -4,7 +4,6 @@ on: push: branches: - query-grouping-aggregation - - worker_change workflow_dispatch: jobs: diff --git a/.github/workflows/pull_request_full_build.yml b/.github/workflows/pull_request_full_build.yml index db1ab8e5128d..cdc5746c7353 100644 --- a/.github/workflows/pull_request_full_build.yml +++ b/.github/workflows/pull_request_full_build.yml @@ -4,7 +4,6 @@ on: pull_request: branches: - master - - worker_change jobs: build-lang: diff --git a/.github/workflows/pull_request_ubuntu_build.yml b/.github/workflows/pull_request_ubuntu_build.yml index 214233f284bd..5bdf8e1e7fee 100644 --- a/.github/workflows/pull_request_ubuntu_build.yml +++ b/.github/workflows/pull_request_ubuntu_build.yml @@ -15,7 +15,6 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation - - worker_change jobs: ubuntu_build: diff --git a/.github/workflows/pull_request_windows_build.yml b/.github/workflows/pull_request_windows_build.yml index cadfb9ef3c42..4f42987df8a5 100644 --- a/.github/workflows/pull_request_windows_build.yml +++ b/.github/workflows/pull_request_windows_build.yml @@ -15,7 +15,6 @@ on: - native-build - revert-client-decl-master - query-grouping-aggregation - - worker_change jobs: windows_build: name: Build with some tests on Windows From ecd62f31dce62e05b435ce33e62421177f9b420d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:02:34 +0530 Subject: [PATCH 87/97] Update license headers --- .../runtime/internal/scheduling/WorkerDataChannel.java | 3 +-- .../tree/expressions/BLangAlternateWorkerReceive.java | 2 +- .../tree/expressions/BLangMultipleWorkerReceive.java | 2 +- .../tree/expressions/BLangWorkerSendReceiveExpr.java | 2 +- .../compiler/internal/parser/tree/STReceiveFieldNode.java | 2 +- .../ballerina/compiler/syntax/tree/ReceiveFieldNode.java | 2 +- .../src/main/resources/syntax_node_metadata.json | 8 ++++---- 7 files changed, 10 insertions(+), 11 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index ed74b5650577..3a2357d1fd8d 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -1,6 +1,5 @@ /* -/* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java index 889dad3a2305..1281fae42aa9 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangAlternateWorkerReceive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java index 49c40b37d777..76696b204fd0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangMultipleWorkerReceive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java index 23ec0f31a717..aae3c1acd329 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/tree/expressions/BLangWorkerSendReceiveExpr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java index 48312813338d..5413a31dc8df 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/tree/STReceiveFieldNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java index 068285da324b..88b77bf999dd 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/syntax/tree/ReceiveFieldNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except diff --git a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json index ec2ca5bb501e..ef3b01f225aa 100644 --- a/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json +++ b/compiler/ballerina-treegen/src/main/resources/syntax_node_metadata.json @@ -3,6 +3,10 @@ "createdYear": "2024", "since": "2201.9.0" }, + "ReceiveFieldNode": { + "createdYear": "2024", + "since": "2201.9.0" + }, "ClientResourceActionNode": { "createdYear": "2022", "since": "2201.2.0" @@ -138,9 +142,5 @@ "SpreadMemberNode": { "createdYear": "2022", "since": "2201.1.0" - }, - "ReceiveFieldNode": { - "createdYear": "2023", - "since": "2201.9.0" } } From 718556633914c53ef9a3d62ec032f03a44809d1b Mon Sep 17 00:00:00 2001 From: Hinduja Balasubramaniyam <28644893+HindujaB@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:36:19 +0530 Subject: [PATCH 88/97] Update bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java Co-authored-by: Sasindu Alahakoon <47134066+SasinduDilshara@users.noreply.github.com> --- .../io/ballerina/runtime/internal/scheduling/WDChannels.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index cdecfa289ff5..709fc03f8781 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -48,7 +48,6 @@ public record ReceiveField(String fieldName, String channelName) { } //TODO try to generalize this to a normal data channel, in that case we won't need these classes. - public synchronized WorkerDataChannel getWorkerDataChannel(String name) { if (this.wDChannels == null) { this.wDChannels = new HashMap<>(); From e94d7dc4d7318c532a8dd3973843245df413df05 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Wed, 20 Mar 2024 07:21:34 +0530 Subject: [PATCH 89/97] Increment BIR version --- .../ballerinalang/programfile/ProgramFileConstants.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java index 5131bd521144..a8e81b4d5fde 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/programfile/ProgramFileConstants.java @@ -25,9 +25,9 @@ public class ProgramFileConstants { public static final int MAGIC_NUMBER = 0xBA1DA4CE; public static final short VERSION_NUMBER = 50; - public static final int BIR_VERSION_NUMBER = 71; - public static final short MIN_SUPPORTED_VERSION = 71; - public static final short MAX_SUPPORTED_VERSION = 71; + public static final int BIR_VERSION_NUMBER = 72; + public static final short MIN_SUPPORTED_VERSION = 72; + public static final short MAX_SUPPORTED_VERSION = 72; // todo move this to a proper place public static final String[] SUPPORTED_PLATFORMS = {"java17", "java11"}; From 57e8c6a109e211c7d7b030b72222329517fa7b69 Mon Sep 17 00:00:00 2001 From: hindujaB Date: Wed, 20 Mar 2024 10:05:48 +0530 Subject: [PATCH 90/97] Refactor message result handling --- .../internal/scheduling/WDChannels.java | 76 ++++++++++--------- .../scheduling/WorkerDataChannel.java | 5 -- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 709fc03f8781..27d9e12596c4 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -67,39 +67,43 @@ public Object receiveDataMultipleChannels(Strand strand, ReceiveField[] receiveF } for (ReceiveField field : receiveFields) { WorkerDataChannel channel = getWorkerDataChannel(field.channelName()); - if (!channel.isClosed()) { - Object result = channel.tryTakeData(strand, true); - checkAndPopulateResult(strand, field, result, channel); - } else { - if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - checkAndPopulateResult(strand, field, ErrorUtils.createNoMessageError(field.channelName()), - channel); - } + WorkerDataChannel.State state = channel.getState(); + Object result = null; + switch (state) { + case OPEN: + result = channel.tryTakeData(strand, true); + break; + case AUTO_CLOSED: + result = ErrorUtils.createNoMessageError(field.channelName()); + break; + case CLOSED: + continue; } + checkAndPopulateResult(strand, field, result, channel); } return clearResultCache(strand, receiveFields); } private void checkAndPopulateResult(Strand strand, ReceiveField field, Object result, WorkerDataChannel channel) { - if (result != null) { - result = getResultValue(result); - strand.workerReceiveMap.populateInitialValue(StringUtils.fromString(field.fieldName()), result); - channel.close(); - ++strand.channelCount; - } else { + if (result == null) { strand.setState(BLOCK_AND_YIELD); + return; } + result = getResultValue(result); + strand.workerReceiveMap.populateInitialValue(StringUtils.fromString(field.fieldName()), result); + channel.close(); + ++strand.channelCount; } private Object clearResultCache(Strand strand, ReceiveField[] receiveFields) { - if (strand.channelCount == receiveFields.length) { - BMap map = strand.workerReceiveMap; - strand.workerReceiveMap = null; - strand.channelCount = 0; - strand.setState(State.RUNNABLE); - return map; + if (strand.channelCount != receiveFields.length) { + return null; } - return null; + BMap map = strand.workerReceiveMap; + strand.workerReceiveMap = null; + strand.channelCount = 0; + strand.setState(State.RUNNABLE); + return map; } public Object receiveDataAlternateChannels(Strand strand, String[] channels) throws Throwable { @@ -107,30 +111,30 @@ public Object receiveDataAlternateChannels(Strand strand, String[] channels) thr boolean allChannelsClosed = true; for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); - if (!channel.isClosed()) { + WorkerDataChannel.State state = channel.getState(); + if (state == WorkerDataChannel.State.OPEN) { allChannelsClosed = false; - result = channel.tryTakeData(strand, true); - if (result != null) { - result = handleNonNullResult(channels, result, channel); - } - } else { - if (channel.getState() == WorkerDataChannel.State.AUTO_CLOSED) { - errors.add((ErrorValue) ErrorUtils.createNoMessageError(channelName)); - } + result = handleResultForOpenChannel(strand, channels, channel); + } else if (state == WorkerDataChannel.State.AUTO_CLOSED) { + errors.add((ErrorValue) ErrorUtils.createNoMessageError(channelName)); } } return processResulAndError(strand, channels, result, allChannelsClosed); } - private Object handleNonNullResult(String[] channels, Object result, WorkerDataChannel channel) { + private Object handleResultForOpenChannel(Strand strand, String[] channels, WorkerDataChannel channel) + throws Throwable { + Object result = channel.tryTakeData(strand, true); + if (result == null) { + return null; + } Object resultValue = getResultValue(result); if (resultValue instanceof ErrorValue errorValue) { errors.add(errorValue); channel.close(); - result = null; - } else { - closeChannels(channels); + return null; } + closeChannels(channels); return result; } @@ -158,14 +162,14 @@ private void closeChannels(String[] channels) { for (String channelName : channels) { WorkerDataChannel channel = getWorkerDataChannel(channelName); channel.close(); - channel.setRemovable(); + channel.callCount = 2; } } public synchronized void removeCompletedChannels(Strand strand, String channelName) { if (this.wDChannels != null) { WorkerDataChannel channel = this.wDChannels.get(channelName); - if (channel != null && (channel.callCount == 2 || channel.isRemovable)) { + if (channel != null && (channel.callCount == 2)) { this.wDChannels.remove(channelName); strand.channelDetails.remove(new ChannelDetails(channelName, true, false)); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java index 3a2357d1fd8d..c4ada8ee3efa 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WorkerDataChannel.java @@ -48,7 +48,6 @@ public class WorkerDataChannel { protected String chnlName; protected int callCount = 0; - protected boolean isRemovable; @SuppressWarnings("rawtypes") private final Queue channel = new LinkedList<>(); @@ -95,10 +94,6 @@ public State getState() { return this.state; } - public void setRemovable() { - this.isRemovable = true; - } - public enum State { OPEN, AUTO_CLOSED, CLOSED } From 0780848f6a91f6ee0631a9ad432c4b55e240ce1d Mon Sep 17 00:00:00 2001 From: hindujaB Date: Wed, 20 Mar 2024 10:17:27 +0530 Subject: [PATCH 91/97] Add comment about callCount --- .../io/ballerina/runtime/internal/scheduling/WDChannels.java | 1 + 1 file changed, 1 insertion(+) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 27d9e12596c4..46861902fd87 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -169,6 +169,7 @@ private void closeChannels(String[] channels) { public synchronized void removeCompletedChannels(Strand strand, String channelName) { if (this.wDChannels != null) { WorkerDataChannel channel = this.wDChannels.get(channelName); + // callCount is incremented to 2 when the message passing is completed. if (channel != null && (channel.callCount == 2)) { this.wDChannels.remove(channelName); strand.channelDetails.remove(new ChannelDetails(channelName, true, false)); From cc01a894bc75980b10519329a25813eeaa5c4d9d Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:25:42 +0530 Subject: [PATCH 92/97] Refactor code --- .../io/ballerina/runtime/internal/scheduling/WDChannels.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java index 46861902fd87..f00a5c9a40b3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/WDChannels.java @@ -170,7 +170,7 @@ public synchronized void removeCompletedChannels(Strand strand, String channelNa if (this.wDChannels != null) { WorkerDataChannel channel = this.wDChannels.get(channelName); // callCount is incremented to 2 when the message passing is completed. - if (channel != null && (channel.callCount == 2)) { + if (channel != null && channel.callCount == 2) { this.wDChannels.remove(channelName); strand.channelDetails.remove(new ChannelDetails(channelName, true, false)); } From 1ec750e1943246373939cb8c63143bf1d36a4da6 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:51:49 +0530 Subject: [PATCH 93/97] Improve error message for multiple-receive with 'var' --- .../util/diagnostic/DiagnosticErrorCode.java | 2 +- .../compiler/semantics/analyzer/TypeChecker.java | 9 +++++++-- .../src/main/resources/compiler.properties | 4 ++-- .../io/ballerina/semantic/api/test/DiagnosticsTest.java | 2 +- .../ballerinalang/test/query/QueryActionOrExprTest.java | 8 +++----- .../test/worker/BasicWorkerActionsNegativeTest.java | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java index 846317a344d8..fe38cc07eb08 100644 --- a/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java +++ b/compiler/ballerina-lang/src/main/java/org/ballerinalang/util/diagnostic/DiagnosticErrorCode.java @@ -587,7 +587,7 @@ public enum DiagnosticErrorCode implements DiagnosticCode { // Worker receive and send related error codes INVALID_TYPE_FOR_RECEIVE("BCE3840", "invalid.type.for.receive"), INVALID_TYPE_FOR_SEND("BCE3841", "invalid.type.for.send"), - INVALID_USAGE_OF_RECEIVE_EXPRESSION("BCE3842", "invalid.usage.of.receive.expression"), + RECEIVE_ACTION_NOT_SUPPORTED_WITH_VAR("BCE3842", "receive.action.not.supported.with.var.type"), INVALID_USE_OF_EXPERIMENTAL_FEATURE("BCE3843", "invalid.use.of.experimental.feature"), MULTIPLE_RECEIVE_COMPATIBLE_TYPE_NOT_FOUND("BCE3844", "multiple.receive.compatible.type.not.found"), DUPLICATE_KEY_IN_MULTIPLE_RECEIVE("BCE3845", "duplicate.key.in.multiple.receive"), diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 35af2475134e..a4fdf47cfbf0 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -3022,6 +3022,11 @@ private BType validateAndGetMultipleReceiveCompatibleType(BType bType, } BType impliedType = Types.getImpliedType(bType); + if (impliedType.tag == TypeTags.NONE) { + dlog.error(multipleWorkerReceive.pos, DiagnosticErrorCode.RECEIVE_ACTION_NOT_SUPPORTED_WITH_VAR); + return symTable.semanticError; + } + if (impliedType.tag != TypeTags.UNION) { BType compatibleType = getMappingConstructorCompatibleNonUnionType(impliedType, data); if (symTable.semanticError.tag == compatibleType.tag || (TypeTags.RECORD == compatibleType.tag && @@ -3099,9 +3104,9 @@ public void visit(BLangWorkerReceive workerReceiveExpr, AnalyzerData data) { workerReceiveExpr.workerType = symbol.type; workerReceiveExpr.workerSymbol = symbol; } - // The receive expression cannot be assigned to var, since we cannot infer the type. + // The receive-action cannot be assigned to var, since we cannot infer the type. if (symTable.noType == data.expType) { - this.dlog.error(workerReceiveExpr.pos, DiagnosticErrorCode.INVALID_USAGE_OF_RECEIVE_EXPRESSION); + this.dlog.error(workerReceiveExpr.pos, DiagnosticErrorCode.RECEIVE_ACTION_NOT_SUPPORTED_WITH_VAR); } // We cannot predict the type of the receive expression as it depends on the type of the data sent by the other // worker/channel. Since receive is an expression now we infer the type of it from the lhs of the statement. diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 6e2887c68aea..91ac709fa142 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -438,8 +438,8 @@ error.invalid.type.for.receive=\ error.invalid.type.for.send=\ invalid type for worker send ''{0}'', expected value:Cloneable -error.invalid.usage.of.receive.expression=\ - invalid usage of receive expression, var not allowed +error.receive.action.not.supported.with.var.type=\ + receive action not supported wth ''var'' type error.multiple.receive.compatible.type.not.found=\ a type compatible with multiple receive not found in type ''{0}'' diff --git a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/DiagnosticsTest.java b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/DiagnosticsTest.java index 81cbc55dc6ac..af01102fbe23 100644 --- a/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/DiagnosticsTest.java +++ b/tests/ballerina-compiler-api-test/src/test/java/io/ballerina/semantic/api/test/DiagnosticsTest.java @@ -104,7 +104,7 @@ private Object[][] getExpectedErrors() { {"too many arguments in call to 'map()'", 27, 18}, {"missing close parenthesis token", 27, 39}, - {"invalid usage of receive expression, var not allowed", 37, 8}, + {"receive action not supported wth 'var' type", 37, 8}, {"variable assignment is required", 37, 8}, {"missing identifier", 38, 0}, {"missing semicolon token", 38, 0}, diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java index 5a3543d25931..fe8ed238035a 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryActionOrExprTest.java @@ -90,7 +90,7 @@ public void testQueryingEmptyTuple() { BRunUtil.invoke(compileResult, "testQueryingEmptyTuple"); } - @Test(enabled = false) // TODO: enable + @Test public void testQueryActionOrExprSemanticsNegative() { CompileResult negativeResult = BCompileUtil.compile( "test-src/query/query_action_or_expr_semantic_negative.bal"); @@ -113,10 +113,8 @@ public void testQueryActionOrExprSemanticsNegative() { validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 93, 27); validateError(negativeResult, i++, "incompatible types: '()' is not an iterable collection", 133, 27); validateError(negativeResult, i++, "incompatible types: 'other' is not an iterable collection", 151, 27); - validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 151, 27); - validateError(negativeResult, i++, "incompatible types: 'other' is not an iterable collection", 168, 27); - validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 168, 31); - validateError(negativeResult, i++, "invalid usage of receive expression, var not allowed", 168, 35); + validateError(negativeResult, i++, "receive action not supported wth 'var' type", 151, 27); + validateError(negativeResult, i++, "receive action not supported wth 'var' type", 168, 27); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 279, 15); validateError(negativeResult, i++, "action invocation as an expression not allowed here", 291, 18); validateError(negativeResult, i++, "order by not supported for complex type fields, order key should " + diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java index 70023f72aebf..0684adfc0508 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/BasicWorkerActionsNegativeTest.java @@ -43,7 +43,7 @@ public void testWorkerActionsSemanticsNegative() { BAssertUtil.validateError(resultSemanticsNegative, index++, "action invocation as an expression not allowed here", 78, 15); BAssertUtil.validateError(resultSemanticsNegative, index++, - "invalid usage of receive expression, var not allowed", 112, 21); + "receive action not supported wth 'var' type", 112, 21); BAssertUtil.validateError(resultSemanticsNegative, index++, "missing identifier", 139, 13); BAssertUtil.validateError(resultSemanticsNegative, index++, From f2e6cd804ec0736aa2802c260f4a852ec84629a2 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:50:44 +0530 Subject: [PATCH 94/97] Add tests with if-else ladder to fix desugar coverage --- .../worker/WorkerAlternateReceiveTest.java | 3 +- .../worker/WorkerMultipleReceiveTest.java | 1 + .../test-src/workers/workers_alt_receive.bal | 23 ++++++++++++- .../workers/workers_multiple_receive.bal | 32 ++++++++++++++++++- 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index 1bf4e2124446..bf677abada1b 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -62,7 +62,8 @@ public static String[] functionProvider() { "alternateReceiveWithSameWorkerSendError2", "alternateReceiveWithSameWorkerSendPanic", "multilpleAlternateReceive1", - "multilpleAlternateReceive2" + "multilpleAlternateReceive2", + "workerAlternateReceiveWithConditionalSend" }; } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java index 0ffad6ffe538..e568f9e6a445 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java @@ -59,6 +59,7 @@ public static String[] functionProvider() { "workerMultipleReceiveWithErrorReturnRec", "workerMultipleReceiveWithConditionalSend1", "workerMultipleReceiveWithConditionalSend2", + "workerMultipleReceiveWithConditionalSend3" }; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal index 7f25b63dfb95..41afac26944a 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_alt_receive.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023 WSO2 LLC. +// Copyright (c) 2024 WSO2 Inc. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -378,3 +378,24 @@ function alternateReceiveWithSameWorkerSendPanic() { test:assertEquals(x, 3, "Invalid int result"); test:assertEquals(y, 2, "Invalid int result"); } + +function workerAlternateReceiveWithConditionalSend() returns error? { + worker w1 { + boolean b1 = true; + boolean b2 = true; + boolean b3 = false; + + if b1 { + 1 -> function; + } else if b2 { + 2 -> function; + } else if b3 { + 3 -> function; + } else { + 4 -> function; + } + } + + int n = check <- w1|w1|w1|w1; + test:assertEquals(n, 1); +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal index 88811521cba3..b882eda09607 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_multiple_receive.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023 WSO2 LLC. +// Copyright (c) 2024 WSO2 Inc. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -312,3 +312,33 @@ function workerMultipleReceiveWithConditionalSend2() { test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'w2'\"}", "Invalid error detail"); test:assertEquals(mapResult["w3"], 3, "Invalid map result"); } + +function workerMultipleReceiveWithConditionalSend3() { + worker w1 { + boolean b1 = true; + boolean b2 = true; + boolean b3 = false; + + if b1 { + 1 -> function; + } else if b2 { + 2 -> function; + } else if b3 { + 3 -> function; + } else { + 4 -> function; + } + } + + map mapResult = <- {a:w1, b:w1, c:w1, d:w1}; + test:assertEquals(mapResult["a"], 1); + + int|errorLib:NoMessage? bResult = mapResult["b"]; + test:assertTrue(bResult is errorLib:NoMessage); + errorLib:NoMessage e = bResult; + test:assertEquals(e.message(), "NoMessage", "Invalid error message"); + test:assertEquals(e.detail().toString(), "{\"message\":\"no message received from worker 'w1' to worker 'function'\"}", "Invalid error detail"); + + test:assertTrue(mapResult["c"] is errorLib:NoMessage); + test:assertTrue(mapResult["d"] is errorLib:NoMessage); +} From a733e1e5af7cfdfecd28b837d00776f563998baa Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:09:30 +0530 Subject: [PATCH 95/97] Update license headers where applicable --- .../src/main/ballerina/auto-close-channels.bal | 2 +- .../langlib/internal/WorkerChannels.java | 4 ++-- .../test/worker/WorkerAlternateReceiveTest.java | 6 ++++-- .../test/worker/WorkerConditionalSendTest.java | 6 ++++-- .../test/worker/WorkerMultipleReceiveTest.java | 6 ++++-- .../test/worker/WorkerOnFailTest.java | 4 +++- .../workers/alternate_receive_type_checking.bal | 2 +- .../workers/multiple-receive-type-checking.bal | 2 +- .../workers/send-receive-allowed-positions.bal | 2 +- .../workers/send-receive-failure-type.bal | 3 ++- .../test-src/workers/send-receive-mismatch.bal | 2 +- .../test-src/workers/worker-on-fail.bal | 16 ++++++++++++++++ .../workers/workers_conditional_send.bal | 3 +-- 13 files changed, 41 insertions(+), 17 deletions(-) diff --git a/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal index 244e9d722927..9d7beafd4489 100644 --- a/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal +++ b/langlib/lang.__internal/src/main/ballerina/auto-close-channels.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java index a8fedfb505c3..f42dced134ac 100644 --- a/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java +++ b/langlib/lang.__internal/src/main/java/org/ballerinalang/langlib/internal/WorkerChannels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -23,7 +23,7 @@ import io.ballerina.runtime.internal.scheduling.WorkerDataChannel; /** - * Native implementation of lang.internal:AutoCloseChannels. + * Native implementation of lang.internal:WorkerChannels. * * @since 2201.9.0 */ diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java index bf677abada1b..67738badcdc0 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerAlternateReceiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com) * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -28,7 +28,9 @@ import org.testng.annotations.Test; /** - * worker alternative receive related tests. + * Worker alternative receive related tests. + * + * @since 2201.9.0 */ public class WorkerAlternateReceiveTest { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java index 2d2279c4ed7e..720441d1454d 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerConditionalSendTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com) * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -28,7 +28,9 @@ import org.testng.annotations.Test; /** - * worker conditional send related tests. + * Worker conditional send related tests. + * + * @since 2201.9.0 */ public class WorkerConditionalSendTest { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java index e568f9e6a445..04374251d96c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerMultipleReceiveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com) + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com) * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -28,7 +28,9 @@ import org.testng.annotations.Test; /** - * worker alternative receive related tests. + * Worker alternative receive related tests. + * + * @since 2201.9.0 */ public class WorkerMultipleReceiveTest { diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java index 883be193b203..487c2272ab99 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerOnFailTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -29,6 +29,8 @@ /** * Tests the worker on fail clause. + * + * @since 2021.9.0 */ public class WorkerOnFailTest { diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal index eb65975495a0..beadd1836343 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/alternate_receive_type_checking.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2024 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal index 535ae81fbc3e..856692e77a15 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/multiple-receive-type-checking.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2024 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal index 29104222c54e..c7806fe03161 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-allowed-positions.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2024 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal index 354807bc639c..f374ad10e350 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2024 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -13,6 +13,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + import ballerina/jballerina.java; public type ErrorA distinct error; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal index 87d1e5a68ef9..fd7f379f3c56 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-mismatch.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2024 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal index 4fbf781f33fa..6029a48eda52 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/worker-on-fail.bal @@ -1,3 +1,19 @@ +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). +// +// 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 +// +// 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. + function testOnFailInWorker() returns int { int[] vals = returnIntArr(); int key = returnOne(); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal index 62ba1bedb74e..08051b73b216 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/workers_conditional_send.bal @@ -1,4 +1,4 @@ -// Copyright (c) 2023 WSO2 LLC. +// Copyright (c) 2024 WSO2 LLC. (http://www.wso2.com). // // WSO2 LLC. licenses this file to you under the Apache License, // Version 2.0 (the "License"); you may not use this file except @@ -477,4 +477,3 @@ function testSendWithEarlyReturnError() { test:assertEquals(mapResult["a"], false, "Invalid boolean result"); test:assertEquals(mapResult["b"], 2, "Invalid int result"); } - From 72b015dbd8fec334c4bc16efc027504a39512b70 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Thu, 21 Mar 2024 13:28:00 +0530 Subject: [PATCH 96/97] Fix test failure due to test file newline addition --- .../ballerinalang/test/worker/WorkerFailTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index dfdca7889d50..e06884288938 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -120,14 +120,14 @@ public void testSendReceiveFailureType() { CompileResult result = BCompileUtil.compile("test-src/workers/send-receive-failure-type.bal"); int index = 0; validateError(result, index++, "incompatible types: expected 'int', " + - "found '(int|ballerina/lang.error:0.0.0:NoMessage)'", 50, 15); + "found '(int|ballerina/lang.error:0.0.0:NoMessage)'", 51, 15); validateError(result, index++, "incompatible types: expected 'int', " + - "found '(ErrorA|int|ballerina/lang.error:0.0.0:NoMessage)'", 51, 15); + "found '(ErrorA|int|ballerina/lang.error:0.0.0:NoMessage)'", 52, 15); validateError(result, index++, "incompatible types: expected 'int', " + - "found '(ErrorA|ErrorB|string|ballerina/lang.error:0.0.0:NoMessage)'", 52, 15); - validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 90, 14); - validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 91, 14); - Assert.assertEquals(result.getErrorCount(), 5); + "found '(ErrorA|ErrorB|string|ballerina/lang.error:0.0.0:NoMessage)'", 53, 15); + validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 91, 14); + validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 92, 14); + Assert.assertEquals(result.getErrorCount(), index); } @Test From e6ef91cb1bd49ef9b053b16f7c9766ac68711c60 Mon Sep 17 00:00:00 2001 From: lochana-chathura <39232462+lochana-chathura@users.noreply.github.com> Date: Tue, 26 Mar 2024 10:56:29 +0530 Subject: [PATCH 97/97] Improve coverage failure type --- .../test/worker/WorkerFailTest.java | 13 +++--- .../workers/send-receive-failure-type.bal | 40 ++++++++++++++++--- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java index e06884288938..990243a46c7f 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/worker/WorkerFailTest.java @@ -120,13 +120,16 @@ public void testSendReceiveFailureType() { CompileResult result = BCompileUtil.compile("test-src/workers/send-receive-failure-type.bal"); int index = 0; validateError(result, index++, "incompatible types: expected 'int', " + - "found '(int|ballerina/lang.error:0.0.0:NoMessage)'", 51, 15); + "found '(int|ballerina/lang.error:0.0.0:NoMessage)'", 49, 15); validateError(result, index++, "incompatible types: expected 'int', " + - "found '(ErrorA|int|ballerina/lang.error:0.0.0:NoMessage)'", 52, 15); + "found '(ErrorA|int|ballerina/lang.error:0.0.0:NoMessage)'", 50, 15); validateError(result, index++, "incompatible types: expected 'int', " + - "found '(ErrorA|ErrorB|string|ballerina/lang.error:0.0.0:NoMessage)'", 53, 15); - validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 91, 14); - validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 92, 14); + "found '(ErrorA|ErrorB|string|ballerina/lang.error:0.0.0:NoMessage)'", 51, 15); + validateError(result, index++, "incompatible types: expected 'int', found '(ErrorA|ErrorB|int)'", 71, 15); + validateError(result, index++, "incompatible types: expected 'int', " + + "found '(ErrorA|ErrorB|int|ballerina/lang.error:0.0.0:NoMessage)'", 86, 15); + validateError(result, index++, "incompatible types: expected '()', found 'ErrorA?'", 119, 14); + validateError(result, index++, "incompatible types: expected '()', found '(ErrorA|ErrorB)?'", 120, 14); Assert.assertEquals(result.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal index f374ad10e350..8ad304087044 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/workers/send-receive-failure-type.bal @@ -14,13 +14,11 @@ // specific language governing permissions and limitations // under the License. -import ballerina/jballerina.java; - public type ErrorA distinct error; public type ErrorB distinct error; -public function testSendFailureType(boolean b, boolean c) { +public function testSendFailureType1(boolean b, boolean c) { worker w1 returns boolean|ErrorA|ErrorB { int i = 2; @@ -59,6 +57,36 @@ public function testSendFailureType(boolean b, boolean c) { } } +public function testSendFailureType2(boolean b) { + worker w1 returns boolean|ErrorA|ErrorB { + ErrorA|ErrorB e = error ErrorA("error A"); + if b { + return e; + } + 11 -> w2; + return true; + } + + worker w2 { + int _ = <- w1; // error: found '(ErrorA|ErrorB|int)' + } +} + +public function testSendFailureType3(boolean b) { + worker w1 returns boolean|ErrorA|ErrorB { + ErrorA|ErrorB|boolean e = error ErrorA("error A"); + if b { + return e; + } + 22 -> w2; + return true; + } + + worker w2 { + int _ = <- w1; // error: found '(ErrorA|ErrorB|int|error:NoMessage) + } +} + public function testReceiveFailureType(boolean b, boolean c) { worker w1 returns boolean|ErrorA|ErrorB { int i = 2; @@ -100,6 +128,6 @@ public function testReceiveFailureType(boolean b, boolean c) { } } -public function println(any|error... values) = @java:Method { - 'class: "org.ballerinalang.test.utils.interop.Utils" -} external; +public function println(any|error value) { + return; +}