diff --git a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java index 9b6c6d6cf7e5..73fe1a7857ec 100644 --- a/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java +++ b/compiler/ballerina-parser/src/main/java/io/ballerina/compiler/internal/parser/BallerinaParser.java @@ -10790,6 +10790,12 @@ private STNode parseTemplateItem() { } // Template string component + if (nextToken.kind != SyntaxKind.TEMPLATE_STRING) { + nextToken = consume(); + return STNodeFactory.createLiteralValueToken(SyntaxKind.TEMPLATE_STRING, + nextToken.text(), nextToken.leadingMinutiae(), nextToken.trailingMinutiae(), + nextToken.diagnostics()); + } return consume(); } diff --git a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/declarations/FunctionDefinitionTest.java b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/declarations/FunctionDefinitionTest.java index 8b5980ab9cc9..a4a84f49199f 100644 --- a/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/declarations/FunctionDefinitionTest.java +++ b/compiler/ballerina-parser/src/test/java/io/ballerinalang/compiler/parser/test/syntax/declarations/FunctionDefinitionTest.java @@ -208,4 +208,9 @@ public void testOptionalSemicolonRecovery() { public void testReKeywordAsFuncNameAndParamName() { testFile("func-definition/func_def_source_36.bal", "func-definition/func_def_assert_36.json"); } + + @Test + public void testInvalidResourceQualifierWithStringTemplate() { + testFile("func-definition/func_def_source_37.bal", "func-definition/func_def_assert_37.json"); + } } diff --git a/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_assert_37.json b/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_assert_37.json new file mode 100644 index 000000000000..8d99f92a0f4d --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_assert_37.json @@ -0,0 +1,550 @@ +{ + "kind": "MODULE_PART", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "MODULE_VAR_DECL", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "TYPED_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "OBJECT_TYPE_DESC", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "OBJECT_KEYWORD", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OBJECT_KEYWORD" + ] + }, + { + "kind": "OPEN_BRACE_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OPEN_BRACE_TOKEN" + ] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "RESOURCE_ACCESSOR_DECLARATION", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [ + { + "kind": "RESOURCE_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "FUNCTION_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "value": "processUser", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "value": "rf" + } + ] + }, + { + "kind": "FUNCTION_SIGNATURE", + "children": [ + { + "kind": "OPEN_PAREN_TOKEN" + }, + { + "kind": "LIST", + "children": [] + }, + { + "kind": "CLOSE_PAREN_TOKEN", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + }, + { + "kind": "OBJECT_FIELD", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "OBJECT_TYPE_DESC", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "OBJECT_KEYWORD", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_OBJECT_KEYWORD" + ] + }, + { + "kind": "OPEN_BRACE_TOKEN", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "LIST", + "hasDiagnostics": true, + "children": [ + { + "kind": "OBJECT_FIELD", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_TYPE_DESC" + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + }, + { + "kind": "OBJECT_FIELD", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_TYPE_DESC" + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + }, + { + "kind": "OBJECT_FIELD", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "SIMPLE_NAME_REFERENCE", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_TYPE_DESC" + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ], + "leadingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "RETURN_KEYWORD", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + }, + { + "kind": "OBJECT_FIELD", + "hasDiagnostics": true, + "children": [ + { + "kind": "LIST", + "children": [] + }, + { + "kind": "STRING_TYPE_DESC", + "children": [ + { + "kind": "STRING_KEYWORD", + "trailingMinutiae": [ + { + "kind": "WHITESPACE_MINUTIAE", + "value": " " + } + ] + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "value": "user", + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "BACKTICK_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "INTERPOLATION_START_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN" + } + ] + }, + { + "kind": "IDENTIFIER_TOKEN", + "hasDiagnostics": true, + "value": "user", + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "TEMPLATE_STRING", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ], + "value": " is " + } + ] + } + }, + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "INTERPOLATION_START_TOKEN", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ] + } + ] + } + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "CLOSE_BRACE_TOKEN" + } + ] + }, + { + "kind": "CAPTURE_BINDING_PATTERN", + "hasDiagnostics": true, + "children": [ + { + "kind": "IDENTIFIER_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_IDENTIFIER" + ] + } + ] + } + ] + }, + { + "kind": "EQUAL_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_EQUAL_TOKEN" + ] + }, + { + "kind": "RAW_TEMPLATE_EXPRESSION", + "hasDiagnostics": true, + "children": [ + { + "kind": "BACKTICK_TOKEN", + "hasDiagnostics": true, + "leadingMinutiae": [ + { + "kind": "INVALID_NODE_MINUTIAE", + "invalidNode": { + "kind": "INVALID_TOKEN_MINUTIAE_NODE", + "hasDiagnostics": true, + "children": [ + { + "kind": "TEMPLATE_STRING", + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_INVALID_TOKEN" + ], + "value": " " + } + ] + } + } + ] + }, + { + "kind": "LIST", + "children": [ + { + "kind": "TEMPLATE_STRING", + "value": ";", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + }, + { + "kind": "TEMPLATE_STRING", + "value": "}", + "trailingMinutiae": [ + { + "kind": "END_OF_LINE_MINUTIAE", + "value": "\n" + } + ] + } + ] + }, + { + "kind": "BACKTICK_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_BACKTICK_TOKEN" + ] + } + ] + }, + { + "kind": "SEMICOLON_TOKEN", + "isMissing": true, + "hasDiagnostics": true, + "diagnostics": [ + "ERROR_MISSING_SEMICOLON_TOKEN" + ] + } + ] + } + ] + }, + { + "kind": "EOF_TOKEN" + } + ] +} diff --git a/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_source_37.bal b/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_source_37.bal new file mode 100644 index 000000000000..0acafcffdfe4 --- /dev/null +++ b/compiler/ballerina-parser/src/test/resources/declarations/func-definition/func_def_source_37.bal @@ -0,0 +1,3 @@ +resource function processUser rf() returns string { + return string `${user} is ${user} `; +}