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 e25e1b30b237..18319f1636c9 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 @@ -778,7 +778,8 @@ public enum DiagnosticErrorCode implements DiagnosticCode { UNSUPPORTED_RESOURCE_ACCESS_REST_SEGMENT_TYPE("BCE4032", "unsupported.resource.access.rest.segment.type"), INVALID_RESOURCE_METHOD_RETURN_TYPE("BCE4033", "invalid.resource.method.return.type"), OUT_OF_RANGE("BCE4034", "numeric.literal.out.of.range"), - INCOMPATIBLE_QUERY_CONSTRUCT_TYPE("BCE4035", "invalid.error.query.construct.type") + INCOMPATIBLE_QUERY_CONSTRUCT_TYPE("BCE4035", "invalid.error.query.construct.type"), + INCOMPATIBLE_QUERY_CONSTRUCT_MAP_TYPE("BCE4036", "invalid.error.query.construct.map.type"); ; private String diagnosticId; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java index 95895be00a31..dc1aa4804ed1 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/TypeChecker.java @@ -6300,7 +6300,8 @@ private BType getNonContextualQueryType(BType staticType, BType basicType, Locat case TypeTags.STREAM: return symTable.streamType; case TypeTags.MAP: - return symTable.mapType; + dlog.error(pos, INCOMPATIBLE_QUERY_CONSTRUCT_MAP_TYPE); + return symTable.semanticError; case TypeTags.XML: if (types.isSubTypeOfBaseType(staticType, symTable.xmlType.tag)) { return new BXMLType(staticType, null); @@ -6315,8 +6316,6 @@ private BType getNonContextualQueryType(BType staticType, BType basicType, Locat case TypeTags.TUPLE: case TypeTags.OBJECT: return new BArrayType(staticType); - default: - return symTable.semanticError; } dlog.error(pos, INCOMPATIBLE_QUERY_CONSTRUCT_TYPE, staticType, basicType); return symTable.semanticError; diff --git a/compiler/ballerina-lang/src/main/resources/compiler.properties b/compiler/ballerina-lang/src/main/resources/compiler.properties index a3e4231387e6..e7da1d059a09 100644 --- a/compiler/ballerina-lang/src/main/resources/compiler.properties +++ b/compiler/ballerina-lang/src/main/resources/compiler.properties @@ -924,6 +924,9 @@ error.invalid.error.detail.type=\ error.invalid.error.query.construct.type=\ incompatible type ''{0}'', expected a construct type of ''{1}'' +error.invalid.error.query.construct.map.type=\ + query expression that constructs a mapping must start with the map keyword + error.error.detail.arg.not.named.arg=\ error detail argument must be passed as named arguments diff --git a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateVariableTest.java b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateVariableTest.java index ba9d644ada87..cf6f130a44b9 100644 --- a/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateVariableTest.java +++ b/language-server/modules/langserver-core/src/test/java/org/ballerinalang/langserver/codeaction/CreateVariableTest.java @@ -112,7 +112,6 @@ public Object[][] dataProvider() { {"createVariableInQueryAction1.json"}, {"createVariableInQueryAction2.json"}, {"createVariableInQueryAction3.json"}, - {"createVariableInQueryAction4.json"}, // Tuple related {"createVariableWithTuple1.json"}, diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction1.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction1.json index 555564451a32..a3d98c2dac4e 100644 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction1.json +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction1.json @@ -20,7 +20,7 @@ "character": 4 } }, - "newText": "string[] listResult = " + "newText": "int[] listResult = " } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction3.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction3.json index b07b6c48f1cc..7373b2781229 100644 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction3.json +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction3.json @@ -20,9 +20,10 @@ "character": 4 } }, - "newText": "(xml:Element|xml:Comment|xml:ProcessingInstruction|xml:Text)[] listResult = " + "newText": "xml xmlResult = " } - ] + ], + "resolvable": false } ] } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction4.json b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction4.json deleted file mode 100644 index cb513af9ffae..000000000000 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/config/createVariableInQueryAction4.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "position": { - "line": 2, - "character": 4 - }, - "source": "createVariableInQueryAction4.bal", - "expected": [ - { - "title": "Create variable", - "kind": "quickfix", - "edits": [ - { - "range": { - "start": { - "line": 2, - "character": 4 - }, - "end": { - "line": 2, - "character": 4 - } - }, - "newText": "int[] listResult = " - } - ] - } - ] -} diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction1.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction1.bal index 31d0664a3dea..006acddb1574 100644 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction1.bal +++ b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction1.bal @@ -1,4 +1,4 @@ public function func() { - xml x1 = xml `The Lost World`; - from xml element in x1 select element.toBalString(); + int[] x1 = [1, 2, 3, 4, 5]; + from int element in x1 select element; } diff --git a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction4.bal b/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction4.bal deleted file mode 100644 index 006acddb1574..000000000000 --- a/language-server/modules/langserver-core/src/test/resources/codeaction/create-variable/source/createVariableInQueryAction4.bal +++ /dev/null @@ -1,4 +0,0 @@ -public function func() { - int[] x1 = [1, 2, 3, 4, 5]; - from int element in x1 select element; -} diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java index f4911adba49a..d829cabd9362 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/query/QueryExprWithQueryConstructTypeTest.java @@ -156,10 +156,16 @@ public void testKeyLessTableWithReturnTable() { Assert.assertTrue((Boolean) returnValues); } + @Test public void testConstructTablesWithRecords() { BRunUtil.invoke(result, "testConstructTablesWithRecords"); } + @Test + public void testConstructMapsWithTuples() { + BRunUtil.invoke(result, "testConstructMapsWithTuples"); + } + @Test(description = "Test negative scenarios for query expr with query construct type") public void testNegativeScenarios() { int index = 0; @@ -306,6 +312,16 @@ public void testNegativeScenarios() { " type of 'table key(name)'", 463, 41); validateError(negativeResult, index++, "incompatible type 'table key(name)'," + " expected a construct type of 'table key(name)'", 464, 41); + validateError(negativeResult, index++, "query expression that constructs a mapping must " + + "start with the map keyword", 468, 36); + validateError(negativeResult, index++, "query expression that constructs a mapping must " + + "start with the map keyword", 469, 36); + validateError(negativeResult, index++, "query expression that constructs a mapping must " + + "start with the map keyword", 470, 36); + validateError(negativeResult, index++, "incompatible type in select clause: expected " + + "[string,any|error], found 'int'", 471, 40); + validateError(negativeResult, index++, "incompatible type in select clause: expected " + + "[string,any|error], found 'record {| int A; |}'", 472, 40); Assert.assertEquals(negativeResult.getErrorCount(), index); } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-query-construct-type-negative.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-query-construct-type-negative.bal index c324dc409fdb..76a057f1047f 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-query-construct-type-negative.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-query-construct-type-negative.bal @@ -462,4 +462,12 @@ function testQueryConstructWithInvalidStaticType() { var _ = from Employee e in t select 1; var _ = from Employee e in t select ["name", 35000]; var _ = from Employee e in t select t; + + map m = {"a": 1, "b": 2}; + + var _ = from var i in m select ["A",1]; + var _ = from var i in m select 1; + var _ = from var i in m select {"A": 1}; + var _ = map from var i in m select 1; + var _ = map from var i in m select {"A": 1}; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal index 33f9b447dd7e..482850266fe3 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/query/query-expr-with-query-construct-type.bal @@ -347,6 +347,15 @@ function testConstructTablesWithRecords() { assertEqual(a3.toString(), "[{\"name\":\"John\"},{\"name\":\"Jane\"}]"); } +function testConstructMapsWithTuples() { + map a = {"a": 1, "b": 2}; + + var cm = map from var i in a select ["A",1]; + assertTrue(cm is map); + map cm2 = cm; + assertEqual(cm2, {"A": 1}); +} + function testInnerJoinAndLimitReturnStream() returns boolean { boolean testPassed = true;