diff --git a/README.md b/README.md index f3c11d242898..2277447e3aa0 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,7 @@ # The Ballerina programming language -[Ballerina](https://ballerina.io/) is a statically typed, open-source cloud-native programming language developed -and supported by [WSO2](https://wso2.com/). +[Ballerina](https://ballerina.io/) is an open-source cloud-native programming language optimized for integration. It is developed and supported by [WSO2](https://wso2.com/). With Ballerina, you could easily develop microservices, API endpoints and integrations, and any other application for the cloud. Additionally, Ballerina has all the general-purpose @@ -34,18 +33,6 @@ Extensible metadata enables easy integration of Ballerina programs with cloud pl You could directly generate Docker and Kubernetes artifacts straight away from the source code. -## Get started - -You can use one of the following options to try out Ballerina. - -* [Set up Ballerina](https://ballerina.io/learn/get-started/) -* [Ballerina Playground](https://play.ballerina.io/) - -You can use the following resources to learn Ballerina. - -* [Ballerina by Example](https://ballerina.io/learn/by-example/) -* [Ballerina learn pages and guides](https://ballerina.io/learn/) - ## Download and install For instructions on downloading and installing, see [Ballerina Downloads](https://ballerina.io/downloads/). @@ -58,13 +45,20 @@ For more installation options, see [Installation options](https://ballerina.io/d Try out Ballerina's development capabilities using the [Ballerina extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=WSO2.ballerina). +## Get started + +You can use the following resources to learn Ballerina. + +* [Ballerina by Example](https://ballerina.io/learn/by-example/) +* [Ballerina learn pages and guides](https://ballerina.io/learn/) + ## Report issues and security flaws >**Tip:** If you are unsure whether you have found a bug, search the existing issues in the GitHub repo and raise it in the [Ballerina Discord](https://discord.com/invite/wAJYFbMrG2) or [Stack Overflow](https://stackoverflow.com/questions/tagged/ballerina). - - Language, Tooling, Ballerina library, Website: ballerina-lang repo - - Extended library: ballerina-extended-library repo - - Security flaw: send an email to security@ballerina.io. For details, see the security policy. + - Language, Tooling, Website: ballerina-lang repo + - Ballerina library: ballerina-lang repo + - Security flaw: send an email to security@ballerina.io. For details, see the security policy. ## Contribute to Ballerina @@ -79,7 +73,6 @@ Ballerina code is distributed under [Apache license 2.0](https://github.com/ball ## Useful links -* Join [Ballerina-Dev](https://groups.google.com/g/ballerina-dev) group for technical discussions related to the Ballerina project. * Chat live with us on our [Discord community](https://discord.com/invite/wAJYFbMrG2). * Post technical questions on the Stack Overflow with the [#ballerina](https://stackoverflow.com/questions/tagged/ballerina) tag. * For more details on how to engage with the community, see [Community](https://ballerina.io/community/). diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/RuntimeRegistry.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/RuntimeRegistry.java index 1a3ec5d602ca..9ce89176033f 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/RuntimeRegistry.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/scheduling/RuntimeRegistry.java @@ -17,6 +17,7 @@ package io.ballerina.runtime.internal.scheduling; import io.ballerina.runtime.api.async.Callback; +import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BFunctionPointer; import io.ballerina.runtime.api.values.BObject; @@ -91,7 +92,8 @@ private synchronized void invokeStopHandlerFunction(Strand strand, Scheduler sch BFunctionPointer bFunctionPointer = stopHandlerStack.pop(); StopHandlerCallback callback = new StopHandlerCallback(strand, scheduler); final FutureValue future = scheduler.createFuture(strand, callback, null, - ((BFunctionType) bFunctionPointer.getType()).retType, null, strand.getMetadata()); + ((BFunctionType) TypeUtils.getImpliedType(bFunctionPointer.getType())).retType, null, + strand.getMetadata()); scheduler.scheduleLocal(new Object[]{strand}, bFunctionPointer, strand, future); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java index 08c6734549fa..80c1ac6512f0 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/AbstractArrayValue.java @@ -151,7 +151,7 @@ public void setLength(long length) { int newLength = (int) length; checkFixedLength(length); rangeCheck(length, size); - fillerValueCheck(newLength, size); + fillerValueCheck(newLength, size, newLength); resizeInternalArray(newLength); fillValues(newLength); size = newLength; @@ -193,9 +193,9 @@ public Type getIteratorNextReturnType() { * helper methods that are visible to the implementation classes. */ - protected abstract void fillValues(int newLength); + protected abstract void fillValues(int index); - protected abstract void fillerValueCheck(int newLength, int size2); + protected abstract void fillerValueCheck(int index, int size, int expectedLength); protected abstract void resizeInternalArray(int newLength); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java index a241fdede542..59543d47ce2b 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/ArrayValueImpl.java @@ -1105,7 +1105,7 @@ protected void rangeCheck(long index, int size) { } @Override - protected void fillerValueCheck(int index, int size) { + protected void fillerValueCheck(int index, int size, int expectedLength) { // if the elementType doesn't have an implicit initial value & if the insertion is not a consecutive append // to the array, then an exception will be thrown. if (arrayType.hasFillerValue()) { @@ -1113,7 +1113,7 @@ protected void fillerValueCheck(int index, int size) { } if (index > size) { throw ErrorHelper.getRuntimeException(ErrorReasons.ILLEGAL_LIST_INSERTION_ERROR, - ErrorCodes.ILLEGAL_ARRAY_INSERTION, size, index + 1); + ErrorCodes.ILLEGAL_ARRAY_INSERTION, size, expectedLength); } } @@ -1172,7 +1172,7 @@ private void prepareForAdd(long index, Object value, Type sourceType, int curren int intIndex = (int) index; rangeCheck(index, size); - fillerValueCheck(intIndex, size); + fillerValueCheck(intIndex, size, intIndex + 1); ensureCapacity(intIndex + 1, currentArraySize); fillValues(intIndex); resetSize(intIndex); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java index a16a44309c8a..1283cf5a11cc 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/values/TupleValueImpl.java @@ -671,9 +671,9 @@ protected void rangeCheck(long index, int size) { } @Override - protected void fillerValueCheck(int index, int size) { + protected void fillerValueCheck(int index, int size, int expectedLength) { // if there has been values added beyond the current index, that means filler values - // has already been checked. Therefore no need to check again. + // has already been checked. Therefore, no need to check again. if (this.size >= index) { return; } @@ -682,7 +682,7 @@ protected void fillerValueCheck(int index, int size) { // to the array, then an exception will be thrown. if (!TypeChecker.hasFillerValue(this.tupleType.getRestType()) && (index > size)) { throw ErrorHelper.getRuntimeException(ErrorReasons.ILLEGAL_LIST_INSERTION_ERROR, - ErrorCodes.ILLEGAL_TUPLE_INSERTION, size, index + 1); + ErrorCodes.ILLEGAL_TUPLE_INSERTION, size, expectedLength); } } @@ -759,7 +759,7 @@ private void prepareForAdd(long index, Object value, int currentArraySize) { TypeChecker.getType(value))); } - fillerValueCheck(intIndex, size); + fillerValueCheck(intIndex, size, intIndex + 1); ensureCapacity(intIndex + 1, currentArraySize); fillValues(intIndex); resetSize(intIndex); diff --git a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunNativeImageTestTask.java b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunNativeImageTestTask.java index be9e151fc2fb..8ea430c39458 100644 --- a/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunNativeImageTestTask.java +++ b/cli/ballerina-cli/src/main/java/io/ballerina/cli/task/RunNativeImageTestTask.java @@ -471,15 +471,15 @@ private int runTestSuiteWithNativeImage(Package currentPackage, Target target, if (nativeImageCommand == null) { throw new ProjectException("GraalVM installation directory not found. Set GRAALVM_HOME as an " + "environment variable\nHINT: To install GraalVM, follow the link: " + - "https://ballerina.io/learn/build-a-native-executable/#configure-graalvm"); + "https://ballerina.io/learn/build-the-executable-locally/#configure-graalvm"); } nativeImageCommand += File.separator + BIN_DIR_NAME + File.separator + (OS.contains("win") ? "native-image.cmd" : "native-image"); File commandExecutable = Paths.get(nativeImageCommand).toFile(); if (!commandExecutable.exists()) { - throw new ProjectException("Cannot find '" + commandExecutable.getName() + "' in the GRAALVM_HOME. " + - "Install it using: gu install native-image"); + throw new ProjectException("Cannot find '" + commandExecutable.getName() + "' in the GRAALVM_HOME/bin " + + "directory. Install it using: gu install native-image"); } } catch (ProjectException e) { throw createLauncherException(e.getMessage()); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/DocumentContext.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/DocumentContext.java index 5616ad48e8fe..c4a7ef1b98f5 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/DocumentContext.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/DocumentContext.java @@ -58,7 +58,7 @@ class DocumentContext { private NodeCloner nodeCloner; private final DocumentId documentId; private final String name; - private final String content; + private String content; private boolean disableSyntaxTree = false; private DocumentContext(DocumentId documentId, String name, String content, boolean disableSyntaxTree) { @@ -187,4 +187,11 @@ private void reportSyntaxDiagnostics(PackageID pkgID, SyntaxTree tree, BLangDiag DocumentContext duplicate() { return new DocumentContext(this.documentId, this.name, syntaxTree().toSourceCode(), false); } + + void shrink() { + if (this.compilationUnit != null) { + this.compilationUnit.topLevelNodes.clear(); + } + this.content = null; + } } diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/JBallerinaBackend.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/JBallerinaBackend.java index a974c477f490..ec1fdadad1bf 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/JBallerinaBackend.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/JBallerinaBackend.java @@ -176,6 +176,9 @@ private void performCodeGen() { moduleDiagnostics.add( new PackageDiagnostic(diagnostic, moduleContext.descriptor(), moduleContext.project())); } + + //TODO: remove this once ballerina-lang#41407 is fixed + ModuleContext.shrinkDocuments(moduleContext); } // add compilation diagnostics diagnostics.addAll(moduleDiagnostics); @@ -553,15 +556,15 @@ private Path emitGraalExecutable(Path executableFilePath) { if (nativeImageCommand == null) { throw new ProjectException("GraalVM installation directory not found. Set GRAALVM_HOME as an " + "environment variable\nHINT: To install GraalVM, follow the link: " + - "https://ballerina.io/learn/build-a-native-executable/#configure-graalvm"); + "https://ballerina.io/learn/build-the-executable-locally/#configure-graalvm"); } nativeImageCommand += File.separator + BIN_DIR_NAME + File.separator + (OS.contains("win") ? "native-image.cmd" : "native-image"); File commandExecutable = Paths.get(nativeImageCommand).toFile(); if (!commandExecutable.exists()) { - throw new ProjectException("cannot find '" + commandExecutable.getName() + "' in the GRAALVM_HOME. " + - "Install it using: gu install native-image"); + throw new ProjectException("cannot find '" + commandExecutable.getName() + "' in the GRAALVM_HOME/bin " + + "directory. Install it using: gu install native-image"); } String graalVMBuildOptions = project.buildOptions().graalVMBuildOptions(); diff --git a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java index 2ce415bc1db6..6578b424fdc8 100644 --- a/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java +++ b/compiler/ballerina-lang/src/main/java/io/ballerina/projects/ModuleContext.java @@ -560,6 +560,11 @@ static void loadPlatformSpecificCodeInternal(ModuleContext moduleContext, Compil // TODO implement } + //TODO: should be removed once we properly fix ballerina-lang#41407 + static void shrinkDocuments(ModuleContext moduleContext) { + moduleContext.srcDocContextMap.values().forEach(DocumentContext::shrink); + } + Optional moduleMdContext() { return Optional.ofNullable(this.moduleMdContext); } 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 bc0fcf61bcbf..19fa61f3a08d 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 @@ -814,7 +814,8 @@ public enum DiagnosticErrorCode implements DiagnosticCode { INVALID_QUERY_CONSTRUCT_TYPE("BCE4055", "invalid.error.query.construct.type"), CANNOT_USE_ALTERNATE_WAIT_ACTION_WITHIN_MULTIPLE_WAIT_ACTION("BCE4056", "cannot.use.alternate.wait.action.within.multiple.wait.action"), - EXPRESSION_OF_FUTURE_TYPE_EXPECTED("BCE4057", "future.expression.expected") + EXPRESSION_OF_FUTURE_TYPE_EXPECTED("BCE4057", "future.expression.expected"), + INSTANTIATION_ERROR("BCE4058", "instantiation.error") ; private String diagnosticId; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/CodeGenerator.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/CodeGenerator.java index a3cd78e0a0db..40b9848ef08b 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/CodeGenerator.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/CodeGenerator.java @@ -98,11 +98,11 @@ private CompiledJarFile generate(BPackageSymbol packageSymbol) { HashMap originalIdentifierMap = JvmDesugarPhase.encodeModuleIdentifiers(packageSymbol.bir); // TODO Get-rid of the following assignment - packageSymbol.compiledJarFile = jvmPackageGen.generate(packageSymbol.bir, true); + CompiledJarFile compiledJarFile = jvmPackageGen.generate(packageSymbol.bir, true); //Revert encoding identifier names JvmDesugarPhase.replaceEncodedModuleIdentifiers(packageSymbol.bir, originalIdentifierMap); - return packageSymbol.compiledJarFile; + return compiledJarFile; } private void populateExternalMap(JvmPackageGen jvmPackageGen) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java index 3fb27f038d47..a7496256d9e3 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/codegen/interop/JMethodResolver.java @@ -47,6 +47,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; @@ -897,6 +898,10 @@ private Executable resolveMethod(Class clazz, String name, Class... paramT private List getExecutables(Class clazz, String methodName, JMethodKind kind) { if (kind == JMethodKind.CONSTRUCTOR) { + if (Modifier.isAbstract(clazz.getModifiers())) { + throw new JInteropException(DiagnosticErrorCode.INSTANTIATION_ERROR, + "'" + clazz.getName() + "' is abstract, and cannot be instantiated"); + } return Arrays.asList(getConstructors(clazz)); } else { List list = new ArrayList<>(); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java index 6fe4551aa68d..076565007e74 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/desugar/AnnotationDesugar.java @@ -840,7 +840,7 @@ private BLangLambdaFunction addReturnAndDefineLambda(BLangFunction function, BLa BInvokableSymbol lambdaFunctionSymbol = createInvokableSymbol(function, pkgID, owner); BLangLambdaFunction lambdaFunction = desugar.createLambdaFunction(function, lambdaFunctionSymbol, env); - lambdaFunction.capturedClosureEnv = env.createClone(); + lambdaFunction.capturedClosureEnv = env; pkgNode.functions.add(function); pkgNode.topLevelNodes.add(function); 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 b2585c126b53..edf0e7add015 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 @@ -1415,6 +1415,7 @@ public void visit(BLangLambdaFunction bLangLambdaFunction) { boolean isWorker = bLangLambdaFunction.function.flagSet.contains(Flag.WORKER); bLangLambdaFunction.enclMapSymbols = collectClosureMapSymbols(symbolEnv, enclInvokable, isWorker); } + bLangLambdaFunction.capturedClosureEnv = null; result = bLangLambdaFunction; } 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 38a81d2fd0f7..cb167d786dd7 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 @@ -551,7 +551,7 @@ private BLangExpression createClosureForDefaultValue(String closureName, String BLangReturn returnStmt = ASTBuilderUtil.createReturnStmt(function.pos, (BLangBlockFunctionBody) function.body); returnStmt.expr = varNode.expr; BLangLambdaFunction lambdaFunction = createLambdaFunction(function); - lambdaFunction.capturedClosureEnv = env.createClone(); + lambdaFunction.capturedClosureEnv = env; BInvokableSymbol varSymbol = createSimpleVariable(function, lambdaFunction, false); env.enclPkg.symbol.scope.define(function.symbol.name, function.symbol); env.enclPkg.functions.add(function); 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 ede19f45b6d4..20deedc98a6f 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 @@ -6222,7 +6222,7 @@ private BLangNode rewriteObjectMemberAccessAsField(BLangFieldBasedAccess fieldAc BLangLambdaFunction lambdaFunction = (BLangLambdaFunction) TreeBuilder.createLambdaFunctionNode(); lambdaFunction.function = func; - lambdaFunction.capturedClosureEnv = env.createClone(); + lambdaFunction.capturedClosureEnv = env; env.enclPkg.functions.add(func); env.enclPkg.topLevelNodes.add(func); //env.enclPkg.lambdaFunctions.add(lambdaFunction); @@ -7809,6 +7809,7 @@ public void visit(BLangLambdaFunction bLangLambdaFunction) { funcSymbol.addAnnotation(this.strandAnnotAttachement.annotationAttachmentSymbol); funcSymbol.schedulerPolicy = SchedulerPolicy.ANY; } + bLangLambdaFunction.capturedClosureEnv = null; result = bLangLambdaFunction; } diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BPackageSymbol.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BPackageSymbol.java index ed1b8b5dc725..19ac138d2fb4 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BPackageSymbol.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/symbols/BPackageSymbol.java @@ -23,7 +23,6 @@ import org.ballerinalang.model.symbols.SymbolKind; import org.ballerinalang.model.symbols.SymbolOrigin; import org.ballerinalang.repository.CompiledPackage; -import org.wso2.ballerinalang.compiler.CompiledJarFile; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; import org.wso2.ballerinalang.compiler.semantics.model.types.BPackageType; import org.wso2.ballerinalang.compiler.util.Name; @@ -56,9 +55,6 @@ public class BPackageSymbol extends BTypeSymbol { public BIRNode.BIRPackage bir; // TODO try to remove this public BIRPackageFile birPackageFile; - // kep code generated jar binary content in memory - public CompiledJarFile compiledJarFile; - // TODO Refactor following two flags public boolean entryPointExists = false; diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index 000855ebbddb..738ca3841df4 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -1575,6 +1575,9 @@ error.unsupported.primitive.type.reason=\ error.method.signature.not.match=\ '{ballerina/jballerina.java}'METHOD_SIGNATURE_DOES_NOT_MATCH ''{0}'' +error.instantiation.error=\ + '{ballerina/jballerina.java}'INSTANTIATION_ERROR ''{0}'' + error.invalid.attribute.reference=\ invalid attribute reference diff --git a/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_assert_10.json b/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_assert_10.json index c68a2c7d374b..987ebde619d8 100644 --- a/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_assert_10.json +++ b/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_assert_10.json @@ -145,7 +145,7 @@ "leadingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", - "value": " " + "value": " " } ], "trailingMinutiae": [ @@ -203,7 +203,7 @@ "leadingMinutiae": [ { "kind": "WHITESPACE_MINUTIAE", - "value": " " + "value": " " } ] } diff --git a/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_source_10.bal b/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_source_10.bal index f5f93c0c3adc..139b64d604cd 100644 --- a/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_source_10.bal +++ b/compiler/ballerina-parser/src/test/resources/expressions/object-constructor/object_constructor_source_10.bal @@ -1,5 +1,5 @@ public function main() { foo(object { - int i = 1; - }); + int i = 1; + }); } diff --git a/distribution/zip/jballerina/bin/bal.bat b/distribution/zip/jballerina/bin/bal.bat index c87ace5a0322..4108114a6540 100644 --- a/distribution/zip/jballerina/bin/bal.bat +++ b/distribution/zip/jballerina/bin/bal.bat @@ -34,7 +34,7 @@ rem ----- if JAVA_HOME is not set we're not happy ------------------------------ :checkJava set BALLERINA_HOME=%~sdp0.. -if exist %BALLERINA_HOME%\..\..\dependencies\jdk-17.0.7+7-jree ( +if exist %BALLERINA_HOME%\..\..\dependencies\jdk-17.0.7+7-jre ( set "JAVA_HOME=%BALLERINA_HOME%\..\..\dependencies\jdk-17.0.7+7-jre" ) diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Pop.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Pop.java index 84a25ee23bc9..df573d7c0e6b 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Pop.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/Pop.java @@ -18,10 +18,13 @@ package org.ballerinalang.langlib.array; +import io.ballerina.runtime.api.types.ArrayType; +import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.utils.TypeUtils; import io.ballerina.runtime.api.values.BArray; import static org.ballerinalang.langlib.array.utils.ArrayUtils.checkIsArrayOnlyOperation; +import static org.ballerinalang.langlib.array.utils.ArrayUtils.checkIsClosedArray; /** * Native implementation of lang.array:pop((any|error)[]). @@ -39,7 +42,11 @@ public class Pop { private static final String FUNCTION_SIGNATURE = "pop()"; public static Object pop(BArray arr) { - checkIsArrayOnlyOperation(TypeUtils.getImpliedType(arr.getType()), FUNCTION_SIGNATURE); + Type type = TypeUtils.getImpliedType(arr.getType()); + checkIsArrayOnlyOperation(type, FUNCTION_SIGNATURE); + checkIsClosedArray((ArrayType) type, FUNCTION_SIGNATURE); return arr.shift(arr.size() - 1); } + + private Pop() {} } diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/SetLength.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/SetLength.java index cb67ee5006c5..d85908a7f2b8 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/SetLength.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/SetLength.java @@ -35,4 +35,6 @@ public class SetLength { public static void setLength(BArray arr, long i) { arr.setLength(i); } + + private SetLength() {} } diff --git a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/ArrayUtils.java b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/ArrayUtils.java index 3b77683ca726..6f5c627b64b0 100644 --- a/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/ArrayUtils.java +++ b/langlib/lang.array/src/main/java/org/ballerinalang/langlib/array/utils/ArrayUtils.java @@ -86,6 +86,12 @@ public static void checkIsArrayOnlyOperation(Type arrType, String op) { } } + public static void checkIsClosedArray(ArrayType arrType, String op) { + if (arrType.getState() == ArrayType.ArrayState.CLOSED) { + throw createOpNotSupportedError(arrType, op); + } + } + public static BError createOpNotSupportedError(Type type, String op) { return ErrorCreator.createError(getModulePrefixedReason(ARRAY_LANG_LIB, OPERATION_NOT_SUPPORTED_IDENTIFIER), diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java index 9566cf30e95f..f07bd8627f67 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/LangLibArrayTest.java @@ -600,7 +600,9 @@ public Object[] testFunctions() { "testModificationWithinEvery", "testArrSortWithNamedArgs1", "testArrSortWithNamedArgs2", - "testArrSortWithNamedArgs3" + "testArrSortWithNamedArgs3", + "testArrayPop", + "testSetLengthNegative" }; } } diff --git a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal index fc775c52bf20..e1810ae806b5 100644 --- a/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal +++ b/langlib/langlib-test/src/test/resources/test-src/arraylib_test.bal @@ -1788,3 +1788,47 @@ function testPushWithErrorConstructorExpr() { assertTrue(e is Error); assertValueEquality("e2", e.message()); } + +function testArrayPop() { + int[] arr1 = [1, 2]; + assertValueEquality(arr1.pop(), 2); + assertValueEquality(arr1, [1]); + + int[2] arr2 = [1, 2]; + int|error result = trap array:pop(arr2); + assertTrue(result is error); + if (result is error) { + assertValueEquality("{ballerina/lang.array}OperationNotSupported", result.message()); + assertValueEquality("pop() not supported on type 'int[2]'", + checkpanic result.detail()["message"]); + } + + int[] arr = arr2; + result = trap arr.pop(); + assertTrue(result is error); + if (result is error) { + assertValueEquality("{ballerina/lang.array}OperationNotSupported", result.message()); + assertValueEquality("pop() not supported on type 'int[2]'", + checkpanic result.detail()["message"]); + } +} + +function testSetLengthNegative() { + string:Char[] arr = ["a","b"]; + error? result = trap arr.setLength(5); + assertTrue(result is error); + if (result is error) { + assertValueEquality("{ballerina/lang.array}IllegalListInsertion", result.message()); + assertValueEquality("array of length 2 cannot be expanded into array of length 5 without filler values", + checkpanic result.detail()["message"]); + } + + [string:Char...] tup = ["a","b"]; + result = trap tup.setLength(10); + assertTrue(result is error); + if (result is error) { + assertValueEquality("{ballerina/lang.array}IllegalListInsertion", result.message()); + assertValueEquality("tuple of length 2 cannot be expanded into tuple of length 10 without filler values", + checkpanic result.detail()["message"]); + } +} diff --git a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java index 622d0601548d..5e64c7abe5a6 100644 --- a/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java +++ b/language-server/modules/langserver-core/src/main/java/org/ballerinalang/langserver/references/ReferencesUtil.java @@ -17,6 +17,7 @@ import io.ballerina.compiler.api.SemanticModel; import io.ballerina.compiler.api.symbols.Symbol; +import io.ballerina.compiler.syntax.tree.ModulePartNode; import io.ballerina.compiler.syntax.tree.NonTerminalNode; import io.ballerina.compiler.syntax.tree.SyntaxKind; import io.ballerina.projects.Document; @@ -24,6 +25,7 @@ import io.ballerina.projects.Project; import io.ballerina.tools.diagnostics.Location; import io.ballerina.tools.text.LinePosition; +import io.ballerina.tools.text.TextRange; import org.ballerinalang.langserver.common.utils.CommonUtil; import org.ballerinalang.langserver.common.utils.PathUtil; import org.ballerinalang.langserver.common.utils.PositionUtil; @@ -120,7 +122,22 @@ public static Optional getSymbolAtCursor(PositionedOperationContext cont return Optional.empty(); } + Document document = srcFile.get(); Position position = context.getCursorPosition(); + TextRange range = TextRange.from( + document.textDocument().textPositionFrom(PositionUtil.getLinePosition(position)), 0); + NonTerminalNode nonTerminalNode = ((ModulePartNode) document.syntaxTree().rootNode()).findNode(range); + SyntaxKind parentKind = nonTerminalNode.parent().kind(); + + if (parentKind == SyntaxKind.TYPE_PARAMETER || parentKind == SyntaxKind.STREAM_TYPE_PARAMS) { + if (nonTerminalNode.lineRange().endLine().offset() == position.getCharacter()) { + // When there is a type parameter and cursor is at the end of the type parameter, semantic API does not + // provide the correct symbol. Therefore, here we search for the symbol at (col - 1). + return semanticModel.get().symbol(document, + LinePosition.from(position.getLine(), position.getCharacter() - 1)); + } + } + Optional symbolAtCursor = semanticModel.get().symbol(srcFile.get(), LinePosition.from(position.getLine(), position.getCharacter())); diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java index 08c7780bbfee..892cafafd8af 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/definition/DefinitionTest.java @@ -151,7 +151,8 @@ protected Object[][] testDataProvider() throws IOException { {"def_annotation_on_obj_func_config1.json", "project"}, {"def_typereference.json", "project"}, {"def_typereference2.json", "project"}, - {"def_typereference3.json", "project"} + {"def_typereference3.json", "project"}, + {"defProject15.json", "project"}, }; } diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java index 12c0e2b5d647..cf490722901b 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/ProjectRenameTest.java @@ -54,6 +54,7 @@ private Object[][] testDataProvider() { // Negative/invalid cases {"rename_keyword_result1.json", "kw"}, {"rename_invalid_token_result1.json", "token"}, + {"rename_table_row_type_and_stream_type.json", "Student"}, }; } diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java index ddbe2bb71462..11923e7911f8 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/rename/RenameTest.java @@ -77,6 +77,12 @@ public Object[][] testDataProvider() { {"rename_self.json", "this"}, {"rename_invalid_qname_ref.json", "io"}, // {"rename_resource_method_path_segment.json", "path1"} //TODO: Fix #41041 + + {"rename_table_row_type_parameter1.json", "Student"}, + {"rename_table_row_type_parameter2.json", "Student"}, + {"rename_table_row_type_parameter3.json", "Student"}, + {"rename_stream_type_parameter.json", "Student"}, + {"rename_map_type_parameter.json", "Student"}, }; } } diff --git a/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json b/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json new file mode 100644 index 000000000000..abe51a94884d --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/definition/expected/project/defProject15.json @@ -0,0 +1,24 @@ +{ + "source": { + "file": "projectls/defmodsource6.bal" + }, + "position": { + "line": 3, + "character": 19 + }, + "result": [ + { + "range": { + "start": { + "line": 9, + "character": 12 + }, + "end": { + "line": 9, + "character": 17 + } + }, + "uri": "projectls/modules/lsmod3/lsmod3.bal" + } + ] +} diff --git a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal new file mode 100644 index 000000000000..c002065b5d3c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/defmodsource6.bal @@ -0,0 +1,6 @@ +import projectls.lsmod3; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +} + diff --git a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal index 81f65bb8da58..e210999d68fb 100644 --- a/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal +++ b/language-server/modules/langserver-core/src/test/resources/definition/sources/projectls/modules/lsmod3/lsmod3.bal @@ -6,3 +6,8 @@ public function mod3Function1() { public type MyType lsmod1:MyType; public type MyType2 MyType; + +public type Human record {| + readonly int id; + string name; +|}; diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json new file mode 100644 index 000000000000..85b26cc4f006 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/project/rename_table_row_type_and_stream_type.json @@ -0,0 +1,54 @@ +{ + "source": { + "file": "main.bal" + }, + "position": { + "line": 19, + "character": 23 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "modules/module2/types.bal": [{ + "range": { + "start": { + "line": 2, + "character": 12 + }, + "end": { + "line": 2, + "character": 17 + } + }, + "newText": "Student" + }], + "main.bal": [{ + "range": { + "start": { + "line": 18, + "character": 19 + }, + "end": { + "line": 18, + "character": 24 + } + }, + "newText": "Student" + }, { + "range": { + "start": { + "line": 19, + "character": 18 + }, + "end": { + "line": 19, + "character": 23 + } + }, + "newText": "Student" + }] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json new file mode 100644 index 000000000000..7d2f8265f1c3 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_map_type_parameter.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_map_type_parameter.bal" + }, + "position": { + "line": 6, + "character": 14 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_map_type_parameter.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 8 + }, + "end": { + "line": 6, + "character": 14 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json new file mode 100644 index 000000000000..f08f38ba0b68 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_stream_type_parameter.json @@ -0,0 +1,57 @@ +{ + "source": { + "file": "rename_stream_type_parameter.bal" + }, + "position": { + "line": 7, + "character": 17 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_stream_type_parameter.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 10 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 7, + "character": 11 + }, + "end": { + "line": 7, + "character": 17 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json new file mode 100644 index 000000000000..33a03123149c --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter1.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_table_row_type_parameter1.bal" + }, + "position": { + "line": 6, + "character": 16 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter1.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 10 + }, + "end": { + "line": 6, + "character": 16 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json new file mode 100644 index 000000000000..e0c14a558e61 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter2.json @@ -0,0 +1,70 @@ +{ + "source": { + "file": "rename_table_row_type_parameter2.bal" + }, + "position": { + "line": 7, + "character": 16 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter2.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 10 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 7, + "character": 10 + }, + "end": { + "line": 7, + "character": 16 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 8, + "character": 11 + }, + "end": { + "line": 8, + "character": 17 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json new file mode 100644 index 000000000000..70ebeacb467a --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/expected/single/rename_table_row_type_parameter3.json @@ -0,0 +1,44 @@ +{ + "source": { + "file": "rename_table_row_type_parameter1.bal" + }, + "position": { + "line": 6, + "character": 13 + }, + "prepareRename": { + "valid": true + }, + "result": { + "changes": { + "rename_table_row_type_parameter1.bal": [ + { + "range": { + "start": { + "line": 0, + "character": 5 + }, + "end": { + "line": 0, + "character": 11 + } + }, + "newText": "Student" + }, + { + "range": { + "start": { + "line": 6, + "character": 10 + }, + "end": { + "line": 6, + "character": 16 + } + }, + "newText": "Student" + } + ] + } + } +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal index 4c143350cad3..816fd0bcd572 100644 --- a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/main.bal @@ -15,4 +15,7 @@ public function main() { int localInt = module1:gInt; module2:setName(fname = "John", lname = "Doe"); + + stream s = new; + table tHuman = table [{id: 1, name: "Jane"}]; } diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal index e267324e7d5f..c03e271fb9e7 100644 --- a/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/project/modules/module2/types.bal @@ -1 +1,6 @@ public type Mod1Error error; + +public type Human record {| + readonly int id; + string name; +|}; diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal new file mode 100644 index 000000000000..04dace1d2832 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_map_type_parameter.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + map m = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal new file mode 100644 index 000000000000..8bd2017f31d4 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_stream_type_parameter.bal @@ -0,0 +1,9 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + Person p = { id: 1, name: "foo" }; + stream s = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal new file mode 100644 index 000000000000..2c2d75d578ef --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter1.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal new file mode 100644 index 000000000000..14931acdb3b9 --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter2.bal @@ -0,0 +1,10 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + Person p = { id: 1, name: "foo" }; + table tHuman = table [{id: 1, name: "Jane"}]; + stream s = new; +} diff --git a/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal new file mode 100644 index 000000000000..2c2d75d578ef --- /dev/null +++ b/language-server/modules/langserver-core/src/test/resources/rename/sources/single/rename_table_row_type_parameter3.bal @@ -0,0 +1,8 @@ +type Person record {| + readonly int id; + string name; +|}; + +function foo() { + table tHuman = table [{id: 1, name: "Jane"}]; +} diff --git a/misc/ballerina-bindgen/src/main/java/org/ballerinalang/bindgen/model/JClass.java b/misc/ballerina-bindgen/src/main/java/org/ballerinalang/bindgen/model/JClass.java index 54f15dd6e318..45ddd6866929 100644 --- a/misc/ballerina-bindgen/src/main/java/org/ballerinalang/bindgen/model/JClass.java +++ b/misc/ballerina-bindgen/src/main/java/org/ballerinalang/bindgen/model/JClass.java @@ -131,7 +131,7 @@ private void populateConstructors(Constructor[] constructors) { } } tempList.sort(Comparator.comparing(JConstructor::getParamTypes)); - for (JConstructor constructor:tempList) { + for (JConstructor constructor : tempList) { JConstructor jConstructor = new JConstructor(constructor.getConstructor(), env, this, "new" + shortClassName + i); if (modulesFlag) { diff --git a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingOptions.java b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingOptions.java index 214b8eb4405e..938ebeb76881 100644 --- a/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingOptions.java +++ b/misc/formatter/modules/formatter-core/src/main/java/org/ballerinalang/formatter/core/FormattingOptions.java @@ -30,17 +30,20 @@ public class FormattingOptions { private boolean lineWrapping; + private int continuationIndent; + private ForceFormattingOptions forceFormattingOptions; private ImportFormattingOptions importFormattingOptions; private FormattingOptions(int tabSize, String wsCharacter, int columnLimit, boolean lineWrapping, - ForceFormattingOptions forceFormattingOptions, + int continuationIndent, ForceFormattingOptions forceFormattingOptions, ImportFormattingOptions importFormattingOptions) { this.tabSize = tabSize; this.wsCharacter = wsCharacter; this.columnLimit = columnLimit; this.lineWrapping = lineWrapping; + this.continuationIndent = continuationIndent; this.forceFormattingOptions = forceFormattingOptions; this.importFormattingOptions = importFormattingOptions; } @@ -140,6 +143,10 @@ public void setLineWrapping(boolean lineWrapping) { this.lineWrapping = lineWrapping; } + public int getContinuationIndent() { + return continuationIndent; + } + public ForceFormattingOptions getForceFormattingOptions() { return forceFormattingOptions; } @@ -162,6 +169,7 @@ public static class FormattingOptionsBuilder { private String wsCharacter = " "; private int columnLimit = 120; private boolean lineWrapping = false; + private int continuationIndent = 2; private ForceFormattingOptions forceFormattingOptions = ForceFormattingOptions.builder().build(); private ImportFormattingOptions importFormattingOptions = ImportFormattingOptions.builder().build(); @@ -198,8 +206,8 @@ public FormattingOptions.FormattingOptionsBuilder setImportFormattingOptions( } public FormattingOptions build() { - return new FormattingOptions(tabSize, wsCharacter, columnLimit, lineWrapping, forceFormattingOptions, - importFormattingOptions); + return new FormattingOptions(tabSize, wsCharacter, columnLimit, lineWrapping, continuationIndent, + forceFormattingOptions, importFormattingOptions); } } } 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 6526e00fadbe..185d1094f875 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 @@ -365,10 +365,10 @@ public FunctionSignatureNode transform(FunctionSignatureNode functionSignatureNo Token openPara = formatToken(functionSignatureNode.openParenToken(), 0, parenTrailingNL); // Start a new indentation of two tabs for the parameters. - indent(2); + indent(options.getContinuationIndent()); SeparatedNodeList parameters = formatSeparatedNodeList(functionSignatureNode.parameters(), 0, 0, 0, 0, 0, 0, true); - unindent(2); + unindent(options.getContinuationIndent()); Token closePara; ReturnTypeDescriptorNode returnTypeDesc = null; @@ -1062,8 +1062,15 @@ public ReturnStatementNode transform(ReturnStatementNode returnStatementNode) { public FunctionCallExpressionNode transform(FunctionCallExpressionNode functionCallExpressionNode) { NameReferenceNode functionName = formatNode(functionCallExpressionNode.functionName(), 0, 0); Token functionCallOpenPara = formatToken(functionCallExpressionNode.openParenToken(), 0, 0); + int prevIndentation = env.currentIndentation; + if (functionCallExpressionNode.arguments().size() > 0) { + if (!isScopedFunctionArgument(functionCallExpressionNode.arguments().get(0))) { + indent(options.getContinuationIndent()); + } + } SeparatedNodeList arguments = formatSeparatedNodeList(functionCallExpressionNode - .arguments(), 0, 0, 0, 0); + .arguments(), 0, 0, 0, 0, true); + env.currentIndentation = prevIndentation; Token functionCallClosePara = formatToken(functionCallExpressionNode.closeParenToken(), env.trailingWS, env.trailingNL); @@ -1836,6 +1843,9 @@ public MarkdownCodeLineNode transform(MarkdownCodeLineNode markdownCodeLineNode) @Override public PositionalArgumentNode transform(PositionalArgumentNode positionalArgumentNode) { + if (env.lineLength != 0 && isScopedFunctionArgument(positionalArgumentNode)) { + env.currentIndentation = env.lineLength; + } ExpressionNode expression = formatNode(positionalArgumentNode.expression(), env.trailingWS, env.trailingNL); return positionalArgumentNode.modify() .withExpression(expression) @@ -4472,10 +4482,14 @@ private void preserveIndentation(boolean value) { */ private int getPreservedIndentation(Token token) { int position = token.lineRange().startLine().offset(); - int offset = position % 4; + int tabSize = options.getTabSize(); + int offset = position % tabSize; + if (env.currentIndentation % tabSize == 0 && env.currentIndentation > position) { + return env.currentIndentation; + } if (offset != 0) { if (offset > 2) { - position = position + 4 - offset; + position = position + tabSize - offset; } else { position = position - offset; } @@ -4713,4 +4727,15 @@ private NodeList sortAndGroupImportDeclarationNodes( imports.addAll(thirdPartyImportNodes.stream().collect(Collectors.toList())); return NodeFactory.createNodeList(imports); } + + private boolean isScopedFunctionArgument(FunctionArgumentNode functionArgumentNode) { + if (functionArgumentNode.parent().kind() == SyntaxKind.FUNCTION_CALL && + functionArgumentNode.children().size() > 0) { + SyntaxKind kind = functionArgumentNode.children().get(0).kind(); + if (kind == SyntaxKind.OBJECT_CONSTRUCTOR || kind == SyntaxKind.MAPPING_CONSTRUCTOR) { + return true; + } + } + return false; + } } diff --git a/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_3.bal b/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_3.bal index 2ae7f56b3534..6ce4f5736fdd 100644 --- a/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_3.bal +++ b/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_3.bal @@ -1,7 +1,7 @@ public function foo() { ( ) y = () -; + ; var x = (); int diff --git a/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_4.bal index c314dd697088..cbf973139ef2 100644 --- a/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_4.bal +++ b/misc/formatter/modules/formatter-core/src/test/resources/misc/linebreaks/assert/line_breaks_4.bal @@ -1,7 +1,7 @@ public function foo() { foreach string animal in animals { match - animal + animal { "Mouse" => { diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_2.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_2.bal new file mode 100644 index 000000000000..d4b192fb7f58 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_2.bal @@ -0,0 +1,13 @@ +import ballerina/io; + +function calculateTotalInvoiceAmount(int customerId, string invoiceDate, + decimal[] itemPrices, boolean isTaxable) returns decimal { + decimal totalAmount = 0.0; + return totalAmount; +} + +public function main() { + decimal invoiceAmount = calculateTotalInvoiceAmount(12345, "2023-09-13", + [25.99, 19.95, 12.49, 7.99, 34.50], true); + io:println(invoiceAmount); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_3.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_3.bal new file mode 100644 index 000000000000..b4570806ec28 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_3.bal @@ -0,0 +1,21 @@ +function calculate() returns int { + int result = subtract(add([21, 45, 6, 12, 67, 89], [1, 5, 6, 9]), + add([11, 12, 13, 14, 15, 16, 17, 18, 19, 20], + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); + return result; +} + +function add(int[] a, int[] b) returns int { + int sum = 0; + foreach int n in a { + sum += n; + } + foreach int n in b { + sum += n; + } + return sum; +} + +function subtract(int x, int y) returns int { + return x - y; +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_4.bal new file mode 100644 index 000000000000..b7be24b37726 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_4.bal @@ -0,0 +1,13 @@ +type SourcePatient record { + string message; + string detail; + string cause; +}; + +function foo(string m, int c, int t, string d, string cause) { +} + +function bar(SourcePatient sourcePatient, int errorCode, int errorType) { + return foo(sourcePatient.message, errorCode, errorType, sourcePatient.detail, + sourcePatient.cause); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_5.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_5.bal new file mode 100644 index 000000000000..061faf40c6f2 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_5.bal @@ -0,0 +1,32 @@ +public function main() { + foo(object { + int i = 1; + }, a, + b); +} + +public function bar() { + bar(t1, object { + int i = 1; + }, t2, t3); +} + +public function baz() { + baz(t1, t2, object { + int i = 1; + int y = 2; + }, + b, + c, + d); +} + +public function fox() { + foz(t1, + object { + int i = 1; + }, + b, + c, + d); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_6.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_6.bal new file mode 100644 index 000000000000..5f3cb33a835a --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/assert/call_statement_6.bal @@ -0,0 +1,21 @@ +function processEmployeeInfo(string firstName, string lastName, string department, string jobTitle, + int employeeId, float salary) { +} + +function foo() { + string firstName = "John"; + string lastName = "Doe"; + string department = "Engineering"; + string jobTitle = "Software Engineer"; + int employeeId = 1001; + float salary = 75000.0; + + processEmployeeInfo( + firstName, + lastName, + department, + jobTitle, + employeeId, + salary + ); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_2.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_2.bal new file mode 100644 index 000000000000..fe29d6cb3bdd --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_2.bal @@ -0,0 +1,13 @@ +import ballerina/io; + +function calculateTotalInvoiceAmount(int customerId, string invoiceDate, + decimal[] itemPrices, boolean isTaxable) returns decimal { + decimal totalAmount = 0.0; + return totalAmount; +} + +public function main() { + decimal invoiceAmount = calculateTotalInvoiceAmount ( 12345, "2023-09-13", + [25.99, 19.95, 12.49, 7.99, 34.50], true ) ; + io:println ( invoiceAmount ) ; +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_3.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_3.bal new file mode 100644 index 000000000000..a64ab1eecd1b --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_3.bal @@ -0,0 +1,21 @@ +function calculate() returns int { + int result = subtract(add([21, 45, 6, 12, 67, 89], [1,5,6,9]), + add([11,12,13,14,15,16,17,18,19,20], + [1,2,3,4,5,6,7,8,9,10])); + return result; +} + +function add(int[] a, int[] b) returns int { + int sum = 0; + foreach int n in a { + sum += n; + } + foreach int n in b { + sum += n; + } + return sum; +} + +function subtract(int x, int y) returns int { + return x - y; +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_4.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_4.bal new file mode 100644 index 000000000000..46a52510845b --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_4.bal @@ -0,0 +1,13 @@ +type SourcePatient record { + string message; + string detail; + string cause; +}; + +function foo(string m, int c, int t, string d, string cause) { +} + +function bar(SourcePatient sourcePatient, int errorCode, int errorType) { + return foo(sourcePatient.message, errorCode, errorType, sourcePatient.detail, + sourcePatient.cause); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_5.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_5.bal new file mode 100644 index 000000000000..4b94f5bbf6cd --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_5.bal @@ -0,0 +1,32 @@ +public function main() { + foo(object { + int i = 1; + }, a, + b); +} + +public function bar() { + bar(t1, object { + int i = 1; + }, t2, t3); +} + +public function baz() { + baz(t1, t2, object { + int i = 1; + int y = 2; + }, + b, + c, + d); +} + +public function fox() { + foz(t1, + object { + int i = 1; + }, + b, + c, + d); +} diff --git a/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_6.bal b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_6.bal new file mode 100644 index 000000000000..1601f40175a2 --- /dev/null +++ b/misc/formatter/modules/formatter-core/src/test/resources/statements/call/source/call_statement_6.bal @@ -0,0 +1,21 @@ +function processEmployeeInfo(string firstName, string lastName, string department, string jobTitle, + int employeeId, float salary) { +} + +function foo() { + string firstName = "John"; + string lastName = "Doe"; + string department = "Engineering"; + string jobTitle = "Software Engineer"; + int employeeId = 1001; + float salary = 75000.0; + + processEmployeeInfo( + firstName, + lastName, + department, + jobTitle, + employeeId, + salary + ); +} diff --git a/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/packaging/ModuleExecutionFlowTests.java b/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/packaging/ModuleExecutionFlowTests.java index dd9722b53eb8..e29f1801e14e 100644 --- a/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/packaging/ModuleExecutionFlowTests.java +++ b/tests/jballerina-integration-test/src/test/java/org/ballerinalang/test/packaging/ModuleExecutionFlowTests.java @@ -140,6 +140,8 @@ public void testStopHandlerExecution() throws BallerinaTestException { LogLeecher infoLeecher1 = new LogLeecher("Stopped stopHandlerFunc3"); LogLeecher infoLeecher2 = new LogLeecher("Stopped stopHandlerFunc2"); LogLeecher infoLeecher3 = new LogLeecher("Stopped stopHandlerFunc1"); + LogLeecher infoLeecher4 = new LogLeecher("Stopped inlineStopHandler"); + serverInstance.addLogLeecher(infoLeecher4); serverInstance.addLogLeecher(infoLeecher1); serverInstance.addLogLeecher(infoLeecher2); serverInstance.addLogLeecher(infoLeecher3); diff --git a/tests/jballerina-integration-test/src/test/resources/packaging/stop_handler_execution/main.bal b/tests/jballerina-integration-test/src/test/resources/packaging/stop_handler_execution/main.bal index 41637860fe75..54bd4a2819be 100644 --- a/tests/jballerina-integration-test/src/test/resources/packaging/stop_handler_execution/main.bal +++ b/tests/jballerina-integration-test/src/test/resources/packaging/stop_handler_execution/main.bal @@ -22,19 +22,19 @@ int count = 0; function stopHandlerFunc1() returns error? { incrementCount(); - assertCount(5); + assertCount(6); println("Stopped stopHandlerFunc1"); } function stopHandlerFunc2() returns error? { incrementCount(); - assertCount(4); + assertCount(5); println("Stopped stopHandlerFunc2"); } function stopHandlerFunc3() returns error? { incrementCount(); - assertCount(3); + assertCount(4); println("Stopped stopHandlerFunc3"); } @@ -49,6 +49,12 @@ public function main() { incrementCount(); assertCount(2); runtime:onGracefulStop(stopHandlerFunc3); + runtime:StopHandler inlineStopHandler = function() returns error? { + incrementCount(); + assertCount(3); + println("Stopped inlineStopHandler"); + }; + runtime:onGracefulStop(inlineStopHandler); runtime:sleep(3); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/AbstractClass.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/AbstractClass.java new file mode 100644 index 000000000000..34a5b4681be2 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/AbstractClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. + * + * 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.nativeimpl.jvm.tests; + +import io.ballerina.runtime.api.values.BString; + +/** + * This class contains abstract methods required for interoperability testing. + * + * @since 2201.9.0 + */ +public abstract class AbstractClass { + + public abstract BString getMessage(); +} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/ClassWithDefaultConstructor.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/ClassWithDefaultConstructor.java index b81e4f01f7b2..3c4320bd9d63 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/ClassWithDefaultConstructor.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/ClassWithDefaultConstructor.java @@ -17,12 +17,15 @@ */ package org.ballerinalang.nativeimpl.jvm.tests; +import io.ballerina.runtime.api.utils.StringUtils; +import io.ballerina.runtime.api.values.BString; + /** * This class is used for Java interoperability tests. * * @since 1.0.0 */ -public class ClassWithDefaultConstructor { +public class ClassWithDefaultConstructor extends AbstractClass { private int a; public ClassWithDefaultConstructor() { @@ -32,4 +35,9 @@ public ClassWithDefaultConstructor() { public Integer getValue() { return a; } + + @Override + public BString getMessage() { + return StringUtils.fromString("Hello from Java!"); + } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/Interface.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/Interface.java new file mode 100644 index 000000000000..b81b3b4ad6e2 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/nativeimpl/jvm/tests/Interface.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. + * + * 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.nativeimpl.jvm.tests; + +import io.ballerina.runtime.api.values.BString; + +/** + * This is an interface used for interoperability testing. + * + * @since 2201.9.0 + */ +public interface Interface { + + BString getMessage(); +} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/InstanceMethodTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/InstanceMethodTest.java index 8cd9ab6dd04c..01dc960316ca 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/InstanceMethodTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/InstanceMethodTest.java @@ -286,6 +286,11 @@ public Object[] unionWithErrorTestFunctions() { }; } + @Test + public void testInteropCallToAbstractClassMethod() { + BRunUtil.invoke(result, "testInteropCallToAbstractClassMethod"); + } + @AfterClass public void tearDown() { result = null; diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java index c73e6c70a6bf..a3381dab4d75 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/javainterop/basic/NegativeValidationTest.java @@ -539,4 +539,17 @@ public void testMethodSignatureNotMatch17() { "no return type expected but found 'error''", "method_sig_not_match17.bal", 19, 1); } + + @Test + public void testAbstractClassInstantiationError() { + String path = "test-src/javainterop/negative/instantiation_error.bal"; + CompileResult compileResult = BCompileUtil.compile(path); + Assert.assertEquals(compileResult.getDiagnostics().length, 2); + BAssertUtil.validateError(compileResult, 0, "{ballerina/jballerina.java}INSTANTIATION_ERROR" + + " ''org.ballerinalang.nativeimpl.jvm.tests.AbstractClass' is abstract, " + + "and cannot be instantiated'", 19, 1); + BAssertUtil.validateError(compileResult, 1, "{ballerina/jballerina.java}INSTANTIATION_ERROR" + + " ''org.ballerinalang.nativeimpl.jvm.tests.Interface' is abstract, and cannot be instantiated'", + 23, 1); + } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordAssignabilityTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordAssignabilityTest.java index f985d7c68353..56c42e8fe54b 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordAssignabilityTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/record/RecordAssignabilityTest.java @@ -20,6 +20,8 @@ import org.ballerinalang.test.BCompileUtil; import org.ballerinalang.test.BRunUtil; import org.ballerinalang.test.CompileResult; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -31,7 +33,12 @@ */ public class RecordAssignabilityTest { - private final CompileResult result = BCompileUtil.compile("test-src/record/record_assignability.bal"); + private CompileResult result; + + @BeforeClass + public void setup() { + result = BCompileUtil.compile("test-src/record/record_assignability.bal"); + } @DataProvider public static Object[] recordAssignabilityTestFunctions() { @@ -95,4 +102,9 @@ public void testRecordAssignabilityNegative() { "found 'record {| readonly int? b; int...; |}'", 70, 33); assertEquals(negativeResult.getErrorCount(), i); } + + @AfterClass + public void tearDown() { + result = null; + } } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/runtime/api/RuntimeAPITest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/runtime/api/RuntimeAPITest.java index 19480a6932ef..7ca9edaca1d8 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/runtime/api/RuntimeAPITest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/runtime/api/RuntimeAPITest.java @@ -45,7 +45,6 @@ public Object[] packageNameProvider() { "invalid_values", "async", "utils", - "stop_handler", "identifier_utils", "environment" }; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/basic/instance_method_tests.bal b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/basic/instance_method_tests.bal index 47f8269d41c8..86c9789a7892 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/basic/instance_method_tests.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/basic/instance_method_tests.bal @@ -267,6 +267,21 @@ public function testBalEnvAcceptingMethodRetType(handle receiver) { test:assertEquals(mapResult, {"a":10,"b":12.5}); } +public function testInteropCallToAbstractClassMethod() { + handle receiver = getConstructor(); + string message = getMessage(receiver); + test:assertEquals(message, "Hello from Java!"); +} + +function getMessage(handle receiver) returns string = @java:Method { + name: "getMessage", + 'class:"org/ballerinalang/nativeimpl/jvm/tests/AbstractClass" +} external; + +function getConstructor() returns handle = @java:Constructor { + 'class: "org.ballerinalang.nativeimpl.jvm.tests.ClassWithDefaultConstructor" +} external; + function assertEquals(anydata|error expected, anydata|error actual) { if isEqual(actual, expected) { return; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/negative/instantiation_error.bal b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/negative/instantiation_error.bal new file mode 100644 index 000000000000..864f055cf3d3 --- /dev/null +++ b/tests/jballerina-unit-test/src/test/resources/test-src/javainterop/negative/instantiation_error.bal @@ -0,0 +1,25 @@ +// Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com) All Rights Reserved. +// +// 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; + +function getAbstractClass() returns handle = @java:Constructor { + 'class: "org.ballerinalang.nativeimpl.jvm.tests.AbstractClass" +} external; + +function getInterface() returns handle = @java:Constructor { + 'class: "org.ballerinalang.nativeimpl.jvm.tests.Interface" +} external; diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/Ballerina.toml b/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/Ballerina.toml deleted file mode 100644 index 1b09d3767f68..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/Ballerina.toml +++ /dev/null @@ -1,4 +0,0 @@ -[package] -org= "testorg" -name="stop_handler" -version= "1.0.0" diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/main.bal b/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/main.bal deleted file mode 100644 index 5660560faa34..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/main.bal +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -import ballerina/lang.runtime; -import ballerina/test; - -import stop_handler.moduleA; - -function stopHandlerFunc1() returns error? { - runtime:sleep(1); - moduleA:incrementCount(); - moduleA:assertCount(10); -} - -function stopHandlerFunc2() returns error? { - moduleA:incrementCount(); - moduleA:assertCount(9); -} - -function stopHandlerFunc3() returns error? { - runtime:sleep(0.5); - moduleA:incrementCount(); - moduleA:assertCount(7); -} - -function stopHandlerFunc4() returns error? { - runtime:sleep(1.5); - moduleA:incrementCount(); - moduleA:assertCount(8); -} - -function init() { - moduleA:incrementCount(); - moduleA:assertCount(1); - runtime:onGracefulStop(stopHandlerFunc1); - runtime:onGracefulStop(stopHandlerFunc2); - runtime:onGracefulStop(stopHandlerFunc4); -} - -final moduleA:ListenerObj lo = new moduleA:ListenerObj("ModDyncListener"); - -public function main() { - moduleA:incrementCount(); - moduleA:assertCount(2); - runtime:registerListener(lo); - runtime:onGracefulStop(stopHandlerFunc3); - - checkpanic lo.'start(); - error? v = lo.gracefulStop(); - if (v is error) { - test:assertEquals(v.message(), "listener in main stopped"); - } - runtime:deregisterListener(lo); - moduleA:main(); -} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/modules/moduleA/main.bal b/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/modules/moduleA/main.bal deleted file mode 100644 index 088aca81c2b2..000000000000 --- a/tests/jballerina-unit-test/src/test/resources/test-src/runtime/api/stop_handler/modules/moduleA/main.bal +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2022 WSO2 Inc. (http://www.wso2.org) All Rights Reserved. -// -// WSO2 Inc. licenses this file to you under the Apache License, -// Version 2.0 (the "License"); you may not use this file except -// in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -import ballerina/lang.runtime; -import ballerina/test; - -int count = 0; - -function stopHandlerFunc1() returns error? { - runtime:sleep(1); - incrementCount(); - assertCount(11); -} - -function stopHandlerFunc2() returns error? { - incrementCount(); - assertCount(6); -} - -function init() { - runtime:onGracefulStop(stopHandlerFunc1); -} - -public class ListenerObj { - - *runtime:DynamicListener; - private string name = ""; - - public function init(string name) { - self.name = name; - } - - public function 'start() returns error? { - if (self.name == "ModDyncListener") { - incrementCount(); - assertCount(3); - } - } - - public function gracefulStop() returns error? { - if (self.name == "ModDyncListener") { - runtime:sleep(1.5); - incrementCount(); - assertCount(4); - return error("listener in main stopped"); - } else if (self.name == "ModDyncListenerA") { - return error("listener in moduleA stopped"); - } - } - - public function immediateStop() { - } - - public function attach(service object {} s, string[]|string? name = ()) returns error? { - } - - public function detach(service object {} s) returns error? { - } -} - -final ListenerObj lo = new ListenerObj("ModDyncListenerA"); - -public function main() { - incrementCount(); - assertCount(5); - runtime:registerListener(lo); - runtime:onGracefulStop(stopHandlerFunc2); - - checkpanic lo.'start(); - error? v = lo.gracefulStop(); - if (v is error) { - test:assertEquals(v.message(), "listener in moduleA stopped"); - } - runtime:deregisterListener(lo); -} - -public function incrementCount() { - count += 1; -} - -public function assertCount(int val) { - test:assertEquals(count, val); -}