From 1535873c071782aa9461539a0b9054f008fe1880 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 15 Apr 2020 20:00:32 +0300 Subject: [PATCH] Do not try to lazy parse a block without opening bracket It can consume the whole file in such case which will result PsiBuilder going crazy #KT-36191 fixed --- .../kotlin/parsing/KotlinParsing.java | 13 +++--- ...gTemplateWithTryWithoutBlockInLongEntry.kt | 3 ++ ...TemplateWithTryWithoutBlockInLongEntry.txt | 40 +++++++++++++++++++ ...TemplateWithTryWithoutBlockInShortEntry.kt | 3 ++ ...emplateWithTryWithoutBlockInShortEntry.txt | 32 +++++++++++++++ .../kotlin/parsing/ParsingTestGenerated.java | 10 +++++ 6 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.kt create mode 100644 compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.txt create mode 100644 compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.kt create mode 100644 compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.txt diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java index 20c52923f3f65..1fbd6c71d2072 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java @@ -1804,20 +1804,23 @@ private void parseBlock(boolean collapse) { myBuilder.enableNewlines(); - expect(LBRACE, "Expecting '{' to open a block"); + boolean hasOpeningBrace = expect(LBRACE, "Expecting '{' to open a block"); + boolean canCollapse = collapse && hasOpeningBrace; - if(collapse){ + if (canCollapse) { advanceBalancedBlock(); - }else{ + } + else { myExpressionParsing.parseStatements(); expect(RBRACE, "Expecting '}'"); } myBuilder.restoreNewlinesState(); - if(collapse){ + if (canCollapse) { lazyBlock.collapse(BLOCK); - }else{ + } + else { lazyBlock.done(BLOCK); } } diff --git a/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.kt b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.kt new file mode 100644 index 0000000000000..b37dc72741abe --- /dev/null +++ b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.kt @@ -0,0 +1,3 @@ +fun foo() { + println("${try}") +} diff --git a/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.txt b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.txt new file mode 100644 index 0000000000000..fcc188ba30b1f --- /dev/null +++ b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.txt @@ -0,0 +1,40 @@ +KtFile: StringTemplateWithTryWithoutBlockInLongEntry.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('println') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + LONG_STRING_TEMPLATE_ENTRY + PsiElement(LONG_TEMPLATE_ENTRY_START)('${') + TRY + PsiElement(try)('try') + BLOCK + PsiErrorElement:Expecting '{' to open a block + + PsiErrorElement:Expecting an element + PsiElement(LONG_TEMPLATE_ENTRY_END)('}') + PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) + PsiElement(CLOSING_QUOTE)('"') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiErrorElement:Expecting 'catch' or 'finally' + \ No newline at end of file diff --git a/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.kt b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.kt new file mode 100644 index 0000000000000..c97f3c53f57d4 --- /dev/null +++ b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.kt @@ -0,0 +1,3 @@ +fun foo() { + println("$try") +} diff --git a/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.txt b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.txt new file mode 100644 index 0000000000000..f94605a62123d --- /dev/null +++ b/compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.txt @@ -0,0 +1,32 @@ +KtFile: StringTemplateWithTryWithoutBlockInShortEntry.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('println') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + STRING_TEMPLATE + PsiElement(OPEN_QUOTE)('"') + SHORT_STRING_TEMPLATE_ENTRY + PsiElement(SHORT_TEMPLATE_ENTRY_START)('$') + PsiErrorElement:Keyword cannot be used as a reference + PsiElement(try)('try') + PsiElement(CLOSING_QUOTE)('"') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ 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 29b7576aba350..ba748440744b6 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java @@ -2742,6 +2742,16 @@ public void testAllFilesPresentInStringTemplates() throws Exception { public void testRawStringsWithManyQuotes() throws Exception { runTest("compiler/testData/psi/stringTemplates/RawStringsWithManyQuotes.kt"); } + + @TestMetadata("StringTemplateWithTryWithoutBlockInLongEntry.kt") + public void testStringTemplateWithTryWithoutBlockInLongEntry() throws Exception { + runTest("compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInLongEntry.kt"); + } + + @TestMetadata("StringTemplateWithTryWithoutBlockInShortEntry.kt") + public void testStringTemplateWithTryWithoutBlockInShortEntry() throws Exception { + runTest("compiler/testData/psi/stringTemplates/StringTemplateWithTryWithoutBlockInShortEntry.kt"); + } } }