diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java index cd6102462b8..caffeedc21c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java @@ -764,9 +764,24 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { advance(); // LONG_TEMPLATE_ENTRY_START - parseExpression(); + while (!eof()) { + int offset = myBuilder.getCurrentOffset(); + + parseExpression(); + + if (_at(LONG_TEMPLATE_ENTRY_END)) { + advance(); + break; + } + else { + error("Expecting '}'"); + if (offset == myBuilder.getCurrentOffset()) { + // Prevent hang if can't advance with parseExpression() + advance(); + } + } + } - expect(LONG_TEMPLATE_ENTRY_END, "Expecting '}'", TokenSet.create(CLOSING_QUOTE, DANGLING_NEWLINE, REGULAR_STRING_PART, ESCAPE_SEQUENCE, SHORT_TEMPLATE_ENTRY_START)); longTemplateEntry.done(LONG_STRING_TEMPLATE_ENTRY); } else { diff --git a/compiler/testData/psi/recovery/lambdaExpressionInString_1.kt b/compiler/testData/psi/recovery/lambdaExpressionInString_1.kt new file mode 100644 index 00000000000..7b96f7230fe --- /dev/null +++ b/compiler/testData/psi/recovery/lambdaExpressionInString_1.kt @@ -0,0 +1,6 @@ +fun some1() { + { + """${dM$ { "$a -> $" }} + + """} +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/lambdaExpressionInString_1.txt b/compiler/testData/psi/recovery/lambdaExpressionInString_1.txt new file mode 100644 index 00000000000..05306c3a48f --- /dev/null +++ b/compiler/testData/psi/recovery/lambdaExpressionInString_1.txt @@ -0,0 +1,60 @@ +JetFile: lambdaExpressionInString_1.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('some1') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"""') + LONG_STRING_TEMPLATE_ENTRY + PsiElement(LONG_TEMPLATE_ENTRY_START)('${') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('dM') + PsiErrorElement:Expecting '}' + + PsiElement(BAD_CHARACTER)('$') + PsiWhiteSpace(' ') + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + BLOCK + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + SHORT_STRING_TEMPLATE_ENTRY + PsiElement(SHORT_TEMPLATE_ENTRY_START)('$') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)(' -> ') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)('$') + PsiElement(CLOSING_QUOTE)('"') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiElement(LONG_TEMPLATE_ENTRY_END)('}') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)('\n') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)('\n') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)(' ') + PsiElement(CLOSING_QUOTE)('"""') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/recovery/lambdaExpressionInString_2.kt b/compiler/testData/psi/recovery/lambdaExpressionInString_2.kt new file mode 100644 index 00000000000..aff8ecc05c0 --- /dev/null +++ b/compiler/testData/psi/recovery/lambdaExpressionInString_2.kt @@ -0,0 +1,4 @@ +fun main(args: Array) { + { "${"} + { "" } +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/lambdaExpressionInString_2.txt b/compiler/testData/psi/recovery/lambdaExpressionInString_2.txt new file mode 100644 index 00000000000..36a5be6974e --- /dev/null +++ b/compiler/testData/psi/recovery/lambdaExpressionInString_2.txt @@ -0,0 +1,66 @@ +JetFile: lambdaExpressionInString_2.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('main') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('args') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Array') + TYPE_ARGUMENT_LIST + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('String') + PsiElement(GT)('>') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + BLOCK + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + LONG_STRING_TEMPLATE_ENTRY + PsiElement(LONG_TEMPLATE_ENTRY_START)('${') + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + LITERAL_STRING_TEMPLATE_ENTRY + PsiElement(REGULAR_STRING_PART)('}') + PsiErrorElement:Expecting '"' + + PsiErrorElement:Expecting '}' + + PsiWhiteSpace('\n ') + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + BLOCK + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + PsiElement(CLOSING_QUOTE)('"') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(LONG_TEMPLATE_ENTRY_END)('}') + PsiErrorElement:Expecting '"' + + PsiErrorElement:Expecting '}' + \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java index 5267ee6eef0..e02553f97d4 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java @@ -2305,6 +2305,18 @@ public class ParsingTestGenerated extends AbstractParsingTest { doParsingTest(fileName); } + @TestMetadata("lambdaExpressionInString_1.kt") + public void testLambdaExpressionInString_1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/lambdaExpressionInString_1.kt"); + doParsingTest(fileName); + } + + @TestMetadata("lambdaExpressionInString_2.kt") + public void testLambdaExpressionInString_2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/lambdaExpressionInString_2.kt"); + doParsingTest(fileName); + } + @TestMetadata("MissingCommaInConstructorValueParameterList.kt") public void testMissingCommaInConstructorValueParameterList() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/recovery/MissingCommaInConstructorValueParameterList.kt");