diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java index 5718e6b33668..106a0fc34818 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/IsolationAnalyzer.java @@ -27,6 +27,7 @@ import org.ballerinalang.model.tree.NodeKind; import org.ballerinalang.model.tree.expressions.ExpressionNode; import org.ballerinalang.model.tree.expressions.RecordLiteralNode; +import org.ballerinalang.model.types.TypeKind; import org.ballerinalang.util.diagnostic.DiagnosticErrorCode; import org.ballerinalang.util.diagnostic.DiagnosticHintCode; import org.ballerinalang.util.diagnostic.DiagnosticWarningCode; @@ -267,6 +268,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.Stack; @@ -293,10 +295,13 @@ public class IsolationAnalyzer extends BLangNodeVisitor { private boolean inferredIsolated = true; private boolean inLockStatement = false; + private boolean inIsolatedStartAction = false; private final Stack copyInLockInfoStack = new Stack<>(); private final Stack> isolatedLetVarStack = new Stack<>(); private final Map isolationInferenceInfoMap = new HashMap<>(); private final Map arrowFunctionTempSymbolMap = new HashMap<>(); + private List listConstructorExprs; + private List mappingConstructorExprs; private IsolationAnalyzer(CompilerContext context) { context.put(ISOLATION_ANALYZER_KEY, this); @@ -1134,14 +1139,26 @@ public void visit(BLangRecordLiteral recordLiteral) { analyzeNode(keyValuePair.key.expr, env); } analyzeNode(keyValuePair.valueExpr, env); + addToMappingConstructorExprs(keyValuePair); } else if (field.getKind() == NodeKind.SIMPLE_VARIABLE_REF) { analyzeNode((BLangRecordLiteral.BLangRecordVarNameField) field, env); + addToMappingConstructorExprs(field); } else { - analyzeNode(((BLangRecordLiteral.BLangRecordSpreadOperatorField) field).expr, env); + analyzeNode((BLangRecordLiteral.BLangRecordSpreadOperatorField) field, env); } } } + @Override + public void visit(BLangRecordLiteral.BLangRecordSpreadOperatorField spreadOperatorField) { + analyzeNode(spreadOperatorField.expr, env); + NodeKind kind = spreadOperatorField.expr.getKind(); + if (!(kind == NodeKind.RECORD_LITERAL_EXPR || kind == NodeKind.TYPE_CONVERSION_EXPR + || kind == NodeKind.GROUP_EXPR)) { + addToMappingConstructorExprs(spreadOperatorField); + } + } + @Override public void visit(BLangTupleVarRef varRefExpr) { for (BLangExpression expression : varRefExpr.expressions) { @@ -1270,9 +1287,12 @@ public void visit(BLangSimpleVarRef varRefExpr) { } } } - if (!recordFieldDefaultValue && !objectFieldDefaultValueRequiringIsolation && enclInvokable != null && isReferenceToVarDefinedInSameInvokable(symbol.owner, enclInvokable.symbol)) { + if (this.inIsolatedStartAction + && !isSubtypeOfReadOnlyOrIsolatedObjectOrInferableObject(symbol.owner, symbol.getType())) { + inferredIsolated = false; + } return; } @@ -1528,7 +1548,7 @@ public void visit(BLangInvocation.BLangResourceAccessInvocation resourceAccessIn analyzeNode(resourceAccessInvocation.resourceAccessPathSegments, env); analyzeInvocation(resourceAccessInvocation); } - + @Override public void visit(BLangTypeInit typeInitExpr) { BInvokableSymbol initInvocationSymbol = @@ -1611,13 +1631,16 @@ public void visit(BLangLetExpression letExpr) { @Override public void visit(BLangListConstructorExpr listConstructorExpr) { for (BLangExpression expr : listConstructorExpr.exprs) { - if (expr.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) { - expr = ((BLangListConstructorExpr.BLangListConstructorSpreadOpExpr) expr).expr; - } analyzeNode(expr, env); + addToListConstructorExprs(expr); } } + @Override + public void visit(BLangListConstructorExpr.BLangListConstructorSpreadOpExpr listConstructorSpreadOpExpr) { + analyzeNode(listConstructorSpreadOpExpr.expr, env); + } + @Override public void visit(BLangTableConstructorExpr tableConstructorExpr) { for (BLangRecordLiteral recordLiteral : tableConstructorExpr.recordLiteralList) { @@ -2079,7 +2102,10 @@ private void analyzeInvocation(BLangInvocation invocationExpr) { } if (isolatedFunctionCall) { + boolean prevInIsolationStartAction = this.inIsolatedStartAction; + this.inIsolatedStartAction = inStartAction; analyzeArgIsolatedness(invocationExpr, requiredArgs, restArgs, symbol, expectsIsolation); + this.inIsolatedStartAction = prevInIsolationStartAction; return; } @@ -2308,112 +2334,163 @@ private void analyzeArgIsolatedness(BLangInvocation invocationExpr, List memberTypes = tupleType.getTupleTypes(); - - BLangExpression varArgExpr = varArg.expr; - boolean listConstrVarArg = varArgExpr.getKind() == NodeKind.LIST_CONSTRUCTOR_EXPR; - BLangListConstructorExpr listConstructorExpr = listConstrVarArg ? - (BLangListConstructorExpr) varArgExpr : null; - - if (!listConstrVarArg) { - analyzeNode(varArg, env); + if (varArgType.tag == TypeTags.ARRAY || varArgType.tag == TypeTags.TUPLE) { + analyzeListConstructorRestArgs(invocationExpr, expectsIsolation, params, + paramsCount, reqArgCount, varArg, varArgType, varArgPos); + this.listConstructorExprs = null; + return; } + analyzeMappingConstructorRestArgs(invocationExpr, expectsIsolation, params, + paramsCount, reqArgCount, varArg, varArgPos); + this.mappingConstructorExprs = null; + return; + } + } - int tupleIndex = 0; - for (int i = reqArgCount; i < paramsCount; i++) { - if (!Symbols.isFlagOn(params.get(i).flags, Flags.ISOLATED_PARAM)) { - if (listConstrVarArg) { - analyzeNode(listConstructorExpr.exprs.get(tupleIndex), env); - } - tupleIndex++; - continue; - } - - BType type = memberTypes.get(tupleIndex); + if (!Symbols.isFlagOn(symbol.restParam.flags, Flags.ISOLATED_PARAM)) { + for (BLangExpression restArg : restArgs) { + analyzeNode(restArg, env); + } + } + } - BLangExpression arg = null; - if (listConstrVarArg) { - arg = listConstructorExpr.exprs.get(tupleIndex); - analyzeAndSetArrowFuncFlagForIsolatedParamArg(arg); - type = arg.getBType(); + private void analyzeMappingConstructorRestArgs(BLangInvocation invocationExpr, + boolean expectsIsolation, List params, int paramsCount, + int reqArgCount, BLangRestArgsExpression varArg, + Location varArgPos) { + BLangExpression varArgExpr = varArg.expr; + + BLangExpression recordLiteral = findRecordLiteral(varArgExpr); + if (!(recordLiteral instanceof BLangRecordLiteral)) { + analyzeNode(varArg, env); + return; + } + this.mappingConstructorExprs = new ArrayList<>(); + analyzeNode(recordLiteral, env); + + for (int i = reqArgCount; i < paramsCount; i++) { + BVarSymbol param = params.get(i); + if (Symbols.isFlagOn(param.flags, Flags.ISOLATED_PARAM)) { + BLangExpression arg = null; + BType type = null; + for (RecordLiteralNode.RecordField recordField: mappingConstructorExprs) { + if (recordField.isKeyValueField()) { + BLangRecordLiteral.BLangRecordKeyValueField keyValueField = + (BLangRecordLiteral.BLangRecordKeyValueField) recordField; + if (keyValueField.key.fieldSymbol.name.value.equals(param.name.value)) { + arg = keyValueField.valueExpr; + type = Types.getReferredType(arg.getBType()); + break; + } + } else if (recordField.getKind() == NodeKind.SIMPLE_VARIABLE_REF) { + BLangRecordLiteral.BLangRecordVarNameField varRefRecordField = + ((BLangRecordLiteral.BLangRecordVarNameField) recordField); + if (varRefRecordField.symbol.name.value.equals(param.name.value)) { + arg = varRefRecordField; + type = Types.getReferredType(arg.getBType()); + break; + } + } else { + BLangRecordLiteral.BLangRecordSpreadOperatorField spreadOpField = + (BLangRecordLiteral.BLangRecordSpreadOperatorField) recordField; + BVarSymbol varRefSymbol = (BVarSymbol) ((BLangSimpleVarRef) spreadOpField.expr).symbol; + BRecordType recordType = (BRecordType) Types.getReferredType(varRefSymbol.type); + Optional matchingField = recordType.fields.entrySet().stream() + .filter(k -> k.getKey().equals(param.name.value)) + .map(Map.Entry::getValue) + .findFirst(); + if (matchingField.isPresent()) { + arg = spreadOpField.expr; + type = Types.getReferredType(matchingField.get().getType()); + break; + } } - - handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, - type, varArgPos); - tupleIndex++; } + analyzeAndSetArrowFuncFlagForIsolatedParamArg(arg); + handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, + type, varArgPos); + } + } + } - BVarSymbol restParam = symbol.restParam; - - if (restParam == null) { - return; - } + private BLangExpression findRecordLiteral(BLangExpression expr) { + if (expr.getKind() == NodeKind.GROUP_EXPR) { + return findRecordLiteral(((BLangGroupExpr) expr).expression); + } + if (expr.getKind() == NodeKind.TYPE_CONVERSION_EXPR) { + return findRecordLiteral(((BLangTypeConversionExpr) expr).expr); + } + return expr; + } - if (!Symbols.isFlagOn(restParam.flags, Flags.ISOLATED_PARAM)) { - if (listConstructorExpr == null) { - return; - } + private void analyzeListConstructorRestArgs(BLangInvocation invocationExpr, + boolean expectsIsolation, List params, int paramsCount, + int reqArgCount, BLangRestArgsExpression varArg, BType varArgType, + Location varArgPos) { + BTupleType tupleType = varArgType.tag == TypeTags.ARRAY ? + getRepresentativeTupleTypeForRemainingArgs(paramsCount, reqArgCount, (BArrayType) varArgType) : + (BTupleType) varArgType; - List exprs = listConstructorExpr.exprs; - for (int i = tupleIndex; i < exprs.size(); i++) { - analyzeNode(exprs.get(i), env); - } - return; - } + List memberTypes = tupleType.getTupleTypes(); - int memberTypeCount = memberTypes.size(); - if (tupleIndex < memberTypeCount) { - for (int i = tupleIndex; i < memberTypeCount; i++) { - BType type = memberTypes.get(i); - BLangExpression arg = null; - if (listConstrVarArg) { - arg = listConstructorExpr.exprs.get(i); - analyzeAndSetArrowFuncFlagForIsolatedParamArg(arg); - type = arg.getBType(); - } + BLangExpression varArgExpr = varArg.expr; + boolean listConstrVarArg = varArgExpr.getKind() == NodeKind.LIST_CONSTRUCTOR_EXPR; + BLangListConstructorExpr listConstructorExpr = listConstrVarArg ? + (BLangListConstructorExpr) varArgExpr : null; - handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, - type, varArgPos); - } - } + if (!listConstrVarArg) { + analyzeNode(varArg, env); + } else { + this.listConstructorExprs = new ArrayList<>(); + analyzeNode(listConstructorExpr, env); + } + int tupleIndex = 0; + int pointer = 0; + for (int i = reqArgCount; i < paramsCount; i++) { + if (Symbols.isFlagOn(params.get(i).flags, Flags.ISOLATED_PARAM)) { + BType type = memberTypes.get(tupleIndex); + BLangExpression arg = null; if (listConstrVarArg) { - List exprs = listConstructorExpr.exprs; - for (int i = tupleIndex; i < exprs.size(); i++) { - BLangExpression arg = exprs.get(i); - analyzeAndSetArrowFuncFlagForIsolatedParamArg(arg); + // find the appropriate arg from the list constructor expr - handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, - arg.getBType(), varArgPos); + for (int j = pointer; j < listConstructorExprs.size(); j++) { + BLangExpression argExpr = listConstructorExprs.get(j); + if (!(argExpr.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP)) { + continue; + } + BType argBType = Types.getReferredType( + ((BLangListConstructorExpr.BLangListConstructorSpreadOpExpr) argExpr).expr.getBType()); + int size = 0; + if (argBType.getKind() == TypeKind.ARRAY) { + size = ((BArrayType) argBType).getSize(); + } + if (argBType.getKind() == TypeKind.TUPLE) { + size = ((BTupleType) argBType).getTupleTypes().size(); + } + if (size + j > tupleIndex) { + break; + } + } + arg = listConstructorExprs.get(pointer); + if (arg.getKind() == NodeKind.LIST_CONSTRUCTOR_SPREAD_OP) { + arg = ((BLangListConstructorExpr.BLangListConstructorSpreadOpExpr) arg).expr; + } + analyzeAndSetArrowFuncFlagForIsolatedParamArg(arg); + type = Types.getReferredType(arg.getBType()); + if (type.getKind() == TypeKind.ARRAY) { // do we really need this? + type = ((BArrayType) type).eType; + } + if (type.getKind() == TypeKind.TUPLE) { + type = ((BTupleType) type).getTupleTypes().get(tupleIndex - pointer); } - return; - } - - BType tupleRestType = tupleType.restType; - if (tupleRestType == null) { - return; } - handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, null, expectsIsolation, - tupleRestType, varArgPos); - - return; + handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, + type, varArgPos); } + tupleIndex++; } - - if (!Symbols.isFlagOn(symbol.restParam.flags, Flags.ISOLATED_PARAM)) { - for (BLangExpression restArg : restArgs) { - analyzeNode(restArg, env); - } - return; - } - - // Args for rest param provided as both individual args and vararg. - analyzeRestArgsForRestParam(invocationExpr, restArgs, symbol, expectsIsolation); } private BTupleType getRepresentativeTupleTypeForRemainingArgs(int paramCount, int reqArgCount, @@ -2432,35 +2509,6 @@ private BTupleType getRepresentativeTupleTypeForRemainingArgs(int paramCount, in return new BTupleType(members); } - private void analyzeRestArgsForRestParam(BLangInvocation invocationExpr, List restArgs, - BInvokableSymbol symbol, boolean expectsIsolation) { - if (Symbols.isFlagOn(((BArrayType) symbol.restParam.type).eType.flags, Flags.ISOLATED)) { - for (BLangExpression restArg : restArgs) { - analyzeNode(restArg, env); - } - return; - } - - for (BLangExpression restArg : restArgs) { - analyzeAndSetArrowFuncFlagForIsolatedParamArg(restArg); - } - - int size = restArgs.size(); - BLangExpression lastArg = restArgs.get(size - 1); - - boolean lastArgIsVarArg = lastArg.getKind() == NodeKind.REST_ARGS_EXPR; - - for (int i = 0; i < (lastArgIsVarArg ? size - 1 : size); i++) { - BLangExpression arg = restArgs.get(i); - handleNonExplicitlyIsolatedArgForIsolatedParam(invocationExpr, arg, expectsIsolation, - arg.getBType(), arg.pos); - } - - if (lastArgIsVarArg) { - analyzeVarArgIsolatedness(invocationExpr, (BLangRestArgsExpression) lastArg, lastArg.pos, expectsIsolation); - } - } - private void analyzeVarArgIsolatedness(BLangInvocation invocationExpr, BLangRestArgsExpression restArgsExpression, Location pos, boolean expectsIsolation) { BLangExpression expr = restArgsExpression.expr; @@ -3558,6 +3606,21 @@ private void markFunctionDependentlyIsolatedOnFunction(BLangInvokableNode enclIn isolationInferenceInfoMap.get(enclInvokableSymbol).dependsOnFunctions.add(symbol); } + + private void addToMappingConstructorExprs(RecordLiteralNode.RecordField field) { + // need to collect only args given as rest args + if (this.mappingConstructorExprs != null) { + this.mappingConstructorExprs.add(field); + } + } + + private void addToListConstructorExprs(BLangExpression expr) { + // need to collect only args given as rest args + if (this.listConstructorExprs != null) { + this.listConstructorExprs.add(expr); + } + } + private boolean isNotInArrowFunctionBody(SymbolEnv env) { return env.node.getKind() != NodeKind.EXPR_FUNCTION_BODY || env.enclEnv.node.getKind() != NodeKind.ARROW_EXPR; } @@ -4125,7 +4188,8 @@ private boolean inferFunctionIsolation(BSymbol symbol, IsolationInferenceInfo fu } for (BLangExpression dependsOnArg : functionIsolationInferenceInfo.dependsOnFuncCallArgExprs) { - if (!isIsolatedExpression(dependsOnArg)) { + if (!isIsolatedExpression(dependsOnArg, false, true, new ArrayList<>(), true, + publiclyExposedObjectTypes, classDefinitions, moduleLevelVariables, new HashSet<>())) { return false; } } diff --git a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/IsolatedParamTest.java b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/IsolatedParamTest.java index 82d497652ff9..f66dd26b38a8 100644 --- a/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/IsolatedParamTest.java +++ b/langlib/langlib-test/src/test/java/org/ballerinalang/langlib/test/IsolatedParamTest.java @@ -73,6 +73,17 @@ public void testIsolatedParamNegative() { validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 51, 59); validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 57, 82); validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 65, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 66, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 67, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 68, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 71, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 72, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 73, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 87, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 88, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 89, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 90, 22); + validateError(result, index++, NON_ISOLATED_ARG_FOR_ISOLATED_PARAM_ERROR, 91, 22); Assert.assertEquals(result.getErrorCount(), index); } diff --git a/langlib/langlib-test/src/test/resources/test-src/isolated-param/isolated_param_negative.bal b/langlib/langlib-test/src/test/resources/test-src/isolated-param/isolated_param_negative.bal index 08e5a2c50ea6..64420002e0c3 100644 --- a/langlib/langlib-test/src/test/resources/test-src/isolated-param/isolated_param_negative.bal +++ b/langlib/langlib-test/src/test/resources/test-src/isolated-param/isolated_param_negative.bal @@ -63,4 +63,30 @@ isolated function testInvalidNonIsolatedFuncArgInFixedLengthArrayRestArg() { int[] marks = [75, 80, 45, 90]; (function (int x) returns boolean)[1] fns = [x => x > 79]; _ = marks.filter(...fns); + _ = marks.filter(...[...fns]); + _ = marks.filter(...[...[...fns]]); + _ = marks.filter(...[fns[0]]); + + [(function (int x) returns boolean)] fnTuple = [x => x > 79]; + _ = marks.filter(...fnTuple); + _ = marks.filter(...[...fnTuple]); + _ = marks.filter(...[fnTuple[0]]); +} + +type Rec record {| + function(int) returns (boolean) func; +|}; + +isolated function testInvalidNonIsolatedFuncArgAsMappingsInFixedLengthArrayRestArg() { + int[] marks = [75, 80, 45, 90]; + (function (int x) returns boolean) func = x => x > 79; + Rec rec = { + func + }; + _ = marks.filter(...rec); + _ = marks.filter(...{...rec}); + _ = marks.filter(...({...rec})); + _ = marks.filter(...{func}); + _ = marks.filter(...{func: func}); + _ = marks.filter(...{...{...rec}}); } diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/isolation/IsolationWarningTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/isolation/IsolationWarningTest.java index 45313c669723..2c5479d5259c 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/isolation/IsolationWarningTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/isolation/IsolationWarningTest.java @@ -46,28 +46,136 @@ public void testIsolationWarnings() { int i = 0; validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 26, 5); validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 30, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 43, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 47, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 62, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 66, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 79, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 83, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 101, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 105, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 118, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 122, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 137, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 141, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 154, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 158, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 176, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 180, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 193, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 197, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 211, 5); - validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 215, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 228, 5); - validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 232, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 39, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 43, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 47, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 51, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 55, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 59, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 63, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 67, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 71, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 79, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 83, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 93, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 97, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 101, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 105, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 109, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 113, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 117, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 121, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 125, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 134, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 138, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 146, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 150, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 154, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 158, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 162, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 166, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 170, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 174, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 178, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 187, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 191, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 201, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 205, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 209, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 213, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 217, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 221, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 225, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 229, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 233, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 245, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 249, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 258, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 262, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 266, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 270, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 274, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 278, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 282, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 286, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 290, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 298, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 302, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 312, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 316, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 320, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 324, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 328, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 332, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 336, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 340, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 344, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 353, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 357, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 365, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 369, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 373, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 377, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 381, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 385, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 389, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 393, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 397, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 406, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 410, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 420, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 424, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 428, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 432, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 436, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 440, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 444, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 448, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 452, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 464, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_HINT, 468, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 477, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 481, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 485, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 489, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 493, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 497, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 501, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 505, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 509, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 517, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 521, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 531, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 535, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 539, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 543, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 547, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 551, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 555, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 559, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 563, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 571, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 575, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 583, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 587, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 591, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 595, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 599, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 603, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 607, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 611, 5); + validateHint(result, i++, NON_ISOLATED_METHOD_HINT, 615, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 624, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 628, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 638, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 642, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 646, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 650, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 654, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 658, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 662, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 666, 5); + validateHint(result, i++, NON_ISOLATED_SERVICE_AND_METHOD_HINT, 670, 5); assertEquals(result.getHintCount(), i); LineRange lineRange = result.getDiagnostics()[0].location().lineRange(); diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_analysis.bal b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_analysis.bal index 8297d860e444..26c56f8aa59e 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_analysis.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_analysis.bal @@ -610,3 +610,11 @@ isolated function assertEquality(any|error expected, any|error actual) { } type IsolatedFunction isolated function () returns int; + +isolated function func() { + _ = start process(getMutableIntArray()); +} + +isolated function process(int[] array) { + +} diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_warnings_for_service_methods.bal b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_warnings_for_service_methods.bal index d0918ade8590..bf3467ea7b5c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_warnings_for_service_methods.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_warnings_for_service_methods.bal @@ -14,7 +14,7 @@ // specific language governing permissions and limitations // under the License. -int nonIsolatedVar = 0; +int nonIsolatedVar = 0; //////////////////// Service Declarations //////////////////// @@ -35,6 +35,42 @@ service on new Listener() { function func() { } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } isolated service "ser2" on new Listener() { @@ -53,6 +89,42 @@ isolated service "ser2" on new Listener() { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } // Inferred isolated. @@ -70,6 +142,42 @@ service "ser3" on new Listener() { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } service "ser4" on new Listener() { @@ -89,6 +197,42 @@ service "ser4" on new Listener() { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } //////////////////// Service Classes //////////////////// @@ -110,6 +254,42 @@ service class Serv1 { function func() { } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } isolated service class Serv2 { @@ -128,6 +308,42 @@ isolated service class Serv2 { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } // Inferred isolated. @@ -145,6 +361,42 @@ service class Serv3 { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } service class Serv4 { @@ -164,6 +416,42 @@ service class Serv4 { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } } //////////////////// Service Object Constructors //////////////////// @@ -185,6 +473,42 @@ var s1 = service object { function func() { } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } }; var s2 = isolated service object { @@ -203,6 +527,42 @@ var s2 = isolated service object { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } }; var s3 = service object { @@ -219,6 +579,42 @@ var s3 = service object { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } }; service object {} s4 = service object { @@ -238,6 +634,42 @@ service object {} s4 = service object { function func() { nonIsolatedFunc(); } + + resource function post bar(string[] mutableVal) { + _ = start mutableValueAccess(mutableVal); + } + + resource function post bas([string[], string[], string[]] args) { + _ = start passParamsAsRestArgs(...args); + } + + resource function post baz(string[] arg1, string[] arg2, string[] arg3) { + _ = start passParamsAsRestArgs(...[arg1, arg2, arg3]); + } + + resource function post qux(string[] arg1, string[] arg2, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[arg1, arg2, ...restArgs]); + } + + resource function post quxx([string[], string[]] args, string[]... restArgs) { + _ = start passRequiredArgsAndRestArgs(...[...args, ...restArgs]); + } + + resource function post quxxx(string[] arg1, string[] arg2, string[] arg3) { + _ = start passRestArgsAsArgs(arg1, arg2, arg3); + } + + resource function post path(T1 t1) { + _ = start passParamsAsRestArgs(t1.arg1, [], []); + } + + resource function post path2(T1 t1, T2 t2) { + _ = start passParamsAsRestArgs(...{...t1, ...t2, arg3: []}); + } + + resource function post path3(T3 t3) { + _ = start passParamsAsRestArgs(...{...{...{...t3}}}); + } }; function nonIsolatedFunc() { @@ -315,6 +747,33 @@ var s6 = isolated service object { } }; +isolated function mutableValueAccess(string[] value) { +} + +isolated function passParamsAsRestArgs(string[] arg1, string[] arg2, string[] arg3) { +} + +isolated function passRequiredArgsAndRestArgs(string[] arg1, string[] arg2, string[]... restArg) { +} + +isolated function passRestArgsAsArgs(string[]... restArg) { +} + + +type T1 record {| + string[] arg1; +|}; + +type T2 record {| + string[] arg2; +|}; + +type T3 record {| + *T1; + *T2; + string[] arg3; +|}; + public class Listener { public isolated function 'start() returns error? { return;