From daa1a0821382a6edc04f43d87c9aeaff48cb8702 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Tue, 17 Nov 2015 15:03:21 +0300 Subject: [PATCH] Script refactoring, parser: wrap statements in script as if they are init blocks of a class --- .../parsing/KotlinExpressionParsing.java | 17 ++- .../kotlin/parsing/KotlinParsing.java | 2 +- .../kotlin/psi/KtClassInitializer.java | 12 ++ .../testData/psi/script/ComplexScript.txt | 136 +++++++++--------- compiler/testData/psi/script/Shebang.txt | 19 +-- .../testData/psi/script/ShebangIncorrect.txt | 38 ++--- compiler/testData/psi/script/SimpleScript.txt | 19 +-- .../testData/psi/script/unexpectedSymbol.txt | 21 +-- .../kotlin/parsing/AbstractParsingTest.java | 6 + 9 files changed, 154 insertions(+), 116 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java index fa536ccdfb8..7c42b207612 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java @@ -1181,13 +1181,21 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { * : SEMI* statement{SEMI+} SEMI* */ public void parseStatements() { + parseStatements(false); + } + + /* + * expressions + * : SEMI* statement{SEMI+} SEMI* + */ + public void parseStatements(boolean isScriptTopLevel) { while (at(SEMICOLON)) advance(); // SEMICOLON while (!eof() && !at(RBRACE)) { if (!atSet(STATEMENT_FIRST)) { errorAndAdvance("Expecting an element"); } if (atSet(STATEMENT_FIRST)) { - parseStatement(); + parseStatement(isScriptTopLevel); } if (at(SEMICOLON)) { while (at(SEMICOLON)) advance(); // SEMICOLON @@ -1214,11 +1222,16 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { * : declaration * ; */ - private void parseStatement() { + private void parseStatement(boolean isScriptTopLevel) { if (!parseLocalDeclaration()) { if (!atSet(EXPRESSION_FIRST)) { errorAndAdvance("Expecting a statement"); } + else if (isScriptTopLevel){ + PsiBuilder.Marker scriptInitializer = mark(); + parseExpression(); + scriptInitializer.done(ANONYMOUS_INITIALIZER); + } else { parseExpression(); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java index 6229b593d90..dbc9febca88 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java @@ -160,7 +160,7 @@ public class KotlinParsing extends AbstractKotlinParsing { PsiBuilder.Marker blockMarker = mark(); - myExpressionParsing.parseStatements(); + myExpressionParsing.parseStatements(/*isScriptTopLevel = */true); checkForUnexpectedSymbols(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassInitializer.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassInitializer.java index ec8f4f83f5f..37350560d3c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassInitializer.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtClassInitializer.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.lexer.KtTokens; @@ -59,4 +60,15 @@ public class KtClassInitializer extends KtDeclarationStub SCRIPT BLOCK - CALL_EXPRESSION - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('println') - VALUE_ARGUMENT_LIST - PsiElement(LPAR)('(') - VALUE_ARGUMENT - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('1') - PsiElement(RPAR)(')') + ANONYMOUS_INITIALIZER + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('println') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') PsiElement(SEMICOLON)(';') PsiWhiteSpace(' ') PsiErrorElement:Expecting an element PsiElement(HASH)('#') - BINARY_EXPRESSION - PREFIX_EXPRESSION + ANONYMOUS_INITIALIZER + BINARY_EXPRESSION + PREFIX_EXPRESSION + OPERATION_REFERENCE + PsiElement(EXCL)('!') + PsiErrorElement:Expecting an element + PsiElement(DIV)('/') OPERATION_REFERENCE - PsiElement(EXCL)('!') + PsiElement(IDENTIFIER)('usr') + PsiWhiteSpace('\n\n') PsiErrorElement:Expecting an element - PsiElement(DIV)('/') - OPERATION_REFERENCE - PsiElement(IDENTIFIER)('usr') - PsiWhiteSpace('\n\n') - PsiErrorElement:Expecting an element - PsiElement(HASH)('#') + PsiElement(HASH)('#') PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) PsiElement(EXCL)('!') PsiElement(DIV)('/') diff --git a/compiler/testData/psi/script/SimpleScript.txt b/compiler/testData/psi/script/SimpleScript.txt index 2e81e94cbac..06a9ac9044a 100644 --- a/compiler/testData/psi/script/SimpleScript.txt +++ b/compiler/testData/psi/script/SimpleScript.txt @@ -5,12 +5,13 @@ JetFile: SimpleScript.kts SCRIPT BLOCK - CALL_EXPRESSION - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('println') - VALUE_ARGUMENT_LIST - PsiElement(LPAR)('(') - VALUE_ARGUMENT - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('1') - PsiElement(RPAR)(')') + ANONYMOUS_INITIALIZER + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('println') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') \ No newline at end of file diff --git a/compiler/testData/psi/script/unexpectedSymbol.txt b/compiler/testData/psi/script/unexpectedSymbol.txt index 94df8e465ec..68236c1d34d 100644 --- a/compiler/testData/psi/script/unexpectedSymbol.txt +++ b/compiler/testData/psi/script/unexpectedSymbol.txt @@ -5,15 +5,16 @@ JetFile: unexpectedSymbol.kts SCRIPT BLOCK - CALL_EXPRESSION - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('println') - VALUE_ARGUMENT_LIST - PsiElement(LPAR)('(') - VALUE_ARGUMENT - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('1') - PsiElement(RPAR)(')') + ANONYMOUS_INITIALIZER + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('println') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') PsiWhiteSpace('\n') PsiErrorElement:unexpected symbol - PsiElement(RBRACE)('}') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java b/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java index 04e4f20ebbd..52341746aa1 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/AbstractParsingTest.java @@ -41,6 +41,12 @@ public abstract class AbstractParsingTest extends ParsingTestCase { System.setProperty("idea.platform.prefix", "Idea"); } + @Override + protected void setUp() throws Exception { + super.setUp(); + getProject().registerService(KotlinScriptDefinitionProvider.class); + } + @Override protected String getTestDataPath() { return KotlinTestUtils.getHomeDirectory();