Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
import org.wso2.ballerinalang.compiler.tree.expressions.BLangMarkdownReturnParameterDocumentation;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangMatchGuard;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNamedArgsExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
Expand Down Expand Up @@ -1111,4 +1112,8 @@
@Override
public void visit(BLangReCapturingGroups reCapturingGroups) {
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
}

Check warning on line 1118 in compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BaseVisitor.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/BaseVisitor.java#L1118

Added line #L1118 was not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr;
Expand Down Expand Up @@ -1578,6 +1579,13 @@
lookupNode(invocation.invocation);
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
lookupNodes(naturalExpression.arguments);
lookupNodes(naturalExpression.strings);
lookupNodes(naturalExpression.insertions);
}

Check warning on line 1587 in compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/NodeFinder.java#L1584-L1587

Added lines #L1584 - L1587 were not covered by tests

private boolean setEnclosingNode(BLangNode node, Location pos) {
if (PositionUtil.isRangeWithinNode(this.range, pos)
&& (this.enclosingNode == null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr;
Expand Down Expand Up @@ -1480,6 +1481,13 @@
find(reFlagExpression.colon);
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
find(naturalExpression.arguments);
find(naturalExpression.insertions);
find(naturalExpression.strings);
}

Check warning on line 1489 in compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/ReferenceFinder.java#L1486-L1489

Added lines #L1486 - L1489 were not covered by tests

// Private methods

private void findRefsInResourceAccessPathSegments(BLangInvocation.BLangResourceAccessInvocation invocation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr;
Expand Down Expand Up @@ -1795,6 +1796,13 @@
lookupNode(reFlagExpression.colon);
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
lookupNodes(naturalExpression.arguments);
lookupNodes(naturalExpression.strings);
lookupNodes(naturalExpression.insertions);
}

Check warning on line 1804 in compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/io/ballerina/compiler/api/impl/SymbolFinder.java#L1801-L1804

Added lines #L1801 - L1804 were not covered by tests

private void lookupResourceAccessPathSegments(BLangInvocation.BLangResourceAccessInvocation resourceInvocation) {
if (resourceInvocation.targetResourceFunc == null) {
// Return if target-function is not set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.ballerina.compiler.syntax.tree.SeparatedNodeList;
import io.ballerina.compiler.syntax.tree.SyntaxTree;
import io.ballerina.projects.environment.ModuleLoadRequest;
import io.ballerina.projects.internal.NaturalProgrammingImportAnalyzer;
import io.ballerina.projects.internal.TransactionImportValidator;
import io.ballerina.tools.diagnostics.Diagnostic;
import io.ballerina.tools.text.TextDocument;
Expand Down Expand Up @@ -139,19 +140,45 @@ private Set<ModuleLoadRequest> getModuleLoadRequests(ModuleDescriptor currentMod
moduleLoadRequestSet.add(getModuleLoadRequest(importDcl, scope));
}

addTransactionModuleImportIfRequired(currentModuleDesc, scope, modulePartNode, moduleLoadRequestSet);
addNaturalProgrammingModuleImportIfRequired(currentModuleDesc, scope, modulePartNode, moduleLoadRequestSet);
return moduleLoadRequestSet;
}

private static void addTransactionModuleImportIfRequired(ModuleDescriptor currentModuleDesc,
PackageDependencyScope scope,
ModulePartNode modulePartNode,
Set<ModuleLoadRequest> moduleLoadRequestSet) {
// TODO This is a temporary solution for SLP6 release
// TODO Traverse the syntax tree to see whether to import the ballerinai/transaction package or not
TransactionImportValidator trxImportValidator = new TransactionImportValidator();
if (!trxImportValidator.shouldImportTransactionPackage(modulePartNode)) {
return;
}
addModuleLoadRequest(currentModuleDesc, scope, moduleLoadRequestSet, Names.BALLERINA_INTERNAL_ORG.value,
Names.TRANSACTION.value, DependencyResolutionType.PLATFORM_PROVIDED);
}

if (trxImportValidator.shouldImportTransactionPackage(modulePartNode) &&
!currentModuleDesc.name().toString().equals(Names.TRANSACTION.value)) {
String moduleName = Names.TRANSACTION.value;
ModuleLoadRequest ballerinaiLoadReq = new ModuleLoadRequest(
PackageOrg.from(Names.BALLERINA_INTERNAL_ORG.value),
moduleName, scope, DependencyResolutionType.PLATFORM_PROVIDED);
moduleLoadRequestSet.add(ballerinaiLoadReq);
private static void addNaturalProgrammingModuleImportIfRequired(ModuleDescriptor currentModuleDesc,
PackageDependencyScope scope,
ModulePartNode modulePartNode,
Set<ModuleLoadRequest> moduleLoadRequestSet) {
NaturalProgrammingImportAnalyzer naturalProgrammingImportAnalyzer = new NaturalProgrammingImportAnalyzer();
if (!naturalProgrammingImportAnalyzer.shouldImportNaturalProgrammingModule(modulePartNode)) {
return;
}
addModuleLoadRequest(currentModuleDesc, scope, moduleLoadRequestSet, Names.BALLERINA_ORG.value,
Names.NATURAL_PROGRAMMING.value, DependencyResolutionType.PLATFORM_PROVIDED);
}

private static void addModuleLoadRequest(ModuleDescriptor currentModuleDesc, PackageDependencyScope scope,
Set<ModuleLoadRequest> moduleLoadRequestSet, String orgName,
String moduleName, DependencyResolutionType dependencyResolutionType) {
if (!currentModuleDesc.name().toString().equals(moduleName)) {
ModuleLoadRequest moduleLoadRequest = new ModuleLoadRequest(
PackageOrg.from(orgName), moduleName, scope, dependencyResolutionType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In here Don't we need to consider about the language version
As an example np module can have different versions for U12 and U13

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's resolved by the project API? Which is why we shouldn't specify a version here?

moduleLoadRequestSet.add(moduleLoadRequest);
}
return moduleLoadRequestSet;
}

private ModuleLoadRequest getModuleLoadRequest(ImportDeclarationNode importDcl, PackageDependencyScope scope) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org).
*
* 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.projects.internal;

import io.ballerina.compiler.syntax.tree.ExternalFunctionBodyNode;
import io.ballerina.compiler.syntax.tree.FunctionDefinitionNode;
import io.ballerina.compiler.syntax.tree.ModulePartNode;
import io.ballerina.compiler.syntax.tree.NaturalExpressionNode;
import io.ballerina.compiler.syntax.tree.Node;
import io.ballerina.compiler.syntax.tree.NodeVisitor;
import io.ballerina.compiler.syntax.tree.SimpleNameReferenceNode;

/**
* Check and add an import for the natural programming module if there is a natural expression.
*
* @since 2201.13.0
*/
public class NaturalProgrammingImportAnalyzer extends NodeVisitor {

private boolean shouldImportNaturalProgrammingModule;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private boolean shouldImportNaturalProgrammingModule;
private boolean shouldImportNaturalProgrammingModule = false;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in #44013.

private static final String CODE_ANNOTATION = "code";

public boolean shouldImportNaturalProgrammingModule(ModulePartNode modulePartNode) {
modulePartNode.accept(this);
return this.shouldImportNaturalProgrammingModule;
}

@Override
public void visit(NaturalExpressionNode naturalExpressionNode) {
this.shouldImportNaturalProgrammingModule = true;
}

@Override
public void visit(FunctionDefinitionNode functionDefinitionNode) {
if (this.shouldImportNaturalProgrammingModule) {
return;
}

if (isExternalFunctionWithCodeAnnotation(functionDefinitionNode)) {
this.shouldImportNaturalProgrammingModule = true;
return;
}

super.visit(functionDefinitionNode);
}

private boolean isExternalFunctionWithCodeAnnotation(FunctionDefinitionNode functionDefinitionNode) {
if (!(functionDefinitionNode.functionBody() instanceof ExternalFunctionBodyNode externalFunctionBodyNode)) {
return false;
}

return externalFunctionBodyNode.annotations().stream()
.anyMatch(annotation ->
annotation.annotReference() instanceof SimpleNameReferenceNode annotReference &&
CODE_ANNOTATION.equals(annotReference.name().text()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since code is a common name, shall we check the prompt field also?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll have the module prefix then.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we don't give a redeclared symbol error for code in the current module. Will fix this for m2.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is when there is a code annotation in the current module.

}

@Override
protected void visitSyntaxNode(Node node) {
if (this.shouldImportNaturalProgrammingModule) {
return;
}
super.visitSyntaxNode(node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
import org.ballerinalang.model.tree.expressions.MarkdownDocumentationReturnParameterAttributeNode;
import org.ballerinalang.model.tree.expressions.MarkdownDocumentationTextAttributeNode;
import org.ballerinalang.model.tree.expressions.NamedArgNode;
import org.ballerinalang.model.tree.expressions.NaturalExpressionNode;
import org.ballerinalang.model.tree.expressions.QueryExpressionNode;
import org.ballerinalang.model.tree.expressions.RawTemplateLiteralNode;
import org.ballerinalang.model.tree.expressions.ReAssertionNode;
Expand Down Expand Up @@ -275,6 +276,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
Expand Down Expand Up @@ -1191,4 +1193,8 @@ public static InferredTypedescDefaultNode createInferTypedescExpressionNode() {
public static BLangInvocation.BLangResourceAccessInvocation createResourceAccessInvocation() {
return new BLangInvocation.BLangResourceAccessInvocation();
}

public static NaturalExpressionNode createNaturalExpressionNode() {
return new BLangNaturalExpression();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public enum NodeKind {
REG_EXP_CAPTURING_GROUP,
REG_EXP_FLAG_EXPR,
REG_EXP_FLAGS_ON_OFF,
NATURAL_EXPR,

/* Statements */
ABORT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org).
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.ballerinalang.model.tree.expressions;

import java.util.List;

/**
* Represents a natural expression node.
*
* @since 2201.13.0
*/
public interface NaturalExpressionNode extends ExpressionNode {

List<? extends ExpressionNode> getInsertions();

void addInsertion(ExpressionNode expression);

List<? extends ExpressionNode> getStrings();

void addString(ExpressionNode stringLiteral);
}
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,17 @@ 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"),
INVALID_USAGE_OF_CHECK_IN_PARAMETER_DEFAULT("BCE4060", "invalid.usage.of.check.in.parameter.default")
INVALID_USAGE_OF_CHECK_IN_PARAMETER_DEFAULT("BCE4060", "invalid.usage.of.check.in.parameter.default"),

EXPECTED_TYPE_FOR_NATURAL_EXPR_MUST_CONTAIN_ERROR("BCE4070", "expected.type.for.natural.expr.must.contain.error"),
EXPECTED_TYPE_FOR_NATURAL_EXPR_MUST_CONTAIN_A_UNION_OF_NON_ERROR_AND_ERROR(
"BCE4071", "expected.type.for.natural.expr.must.contain.a.union.of.non.error.and.error"),
EXPECTED_TYPE_FOR_NATURAL_EXPR_MUST_BE_A_SUBTYPE_OF_ANYDATA_OR_ERROR(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont we need to avoid the regexp in here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why though?

"BCE4072", "expected.type.for.natural.expr.must.be.a.subtype.of.anydata.or.error"),
CONST_NATURAL_EXPR_CAN_HAVE_ONLY_CONST_EXPR_INSERTION(
"BCE4073", "const.natural.expr.can.have.only.const.expr.insertion"),
EXPECTED_TYPE_FOR_CONST_NATURAL_EXPR_MUST_BE_A_SUBTYPE_OF_ANYDATA(
"BCE4074", "expected.type.for.const.natural.expr.must.be.a.subtype.of.anydata")
;

private final String diagnosticId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
Expand Down Expand Up @@ -1792,6 +1793,14 @@
/* Ignore */
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
rewriteExprs(naturalExpression.arguments);
rewriteExprs(naturalExpression.strings);
rewriteExprs(naturalExpression.insertions);
result = naturalExpression;
}

Check warning on line 1802 in compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ClosureGenerator.java#L1798-L1802

Added lines #L1798 - L1802 were not covered by tests

// Rewrite methods

@SuppressWarnings("unchecked")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangObjectConstructorExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
Expand Down Expand Up @@ -1274,6 +1275,14 @@
result = reFlagExpression;
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
rewrite(naturalExpression.arguments);
rewrite(naturalExpression.strings);
rewrite(naturalExpression.insertions);
result = naturalExpression;
}

Check warning on line 1284 in compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/ConstantPropagation.java#L1280-L1284

Added lines #L1280 - L1284 were not covered by tests

@SuppressWarnings("unchecked")
<E extends BLangNode> E rewrite(E node) {
if (node == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
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.BLangNaturalExpression;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangNumericLiteral;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryAction;
import org.wso2.ballerinalang.compiler.tree.expressions.BLangQueryExpr;
Expand Down Expand Up @@ -2801,6 +2802,14 @@
result = regExpTemplateLiteral;
}

@Override
public void visit(BLangNaturalExpression naturalExpression) {
rewrite(naturalExpression.arguments);
rewrite(naturalExpression.strings);
rewrite(naturalExpression.insertions);
result = naturalExpression;
}

Check warning on line 2811 in compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java

View check run for this annotation

Codecov / codecov/patch

compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/QueryDesugar.java#L2807-L2811

Added lines #L2807 - L2811 were not covered by tests

private void acceptNode(BLangNode node) {
if (node == null) {
return;
Expand Down
Loading
Loading