Script refactoring, parser: wrap statements in script as if they are init blocks of a class

This commit is contained in:
Pavel V. Talanov
2015-11-17 15:03:21 +03:00
parent e45585be21
commit daa1a08213
9 changed files with 154 additions and 116 deletions
@@ -1181,13 +1181,21 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
* : SEMI* statement{SEMI+} SEMI* * : SEMI* statement{SEMI+} SEMI*
*/ */
public void parseStatements() { public void parseStatements() {
parseStatements(false);
}
/*
* expressions
* : SEMI* statement{SEMI+} SEMI*
*/
public void parseStatements(boolean isScriptTopLevel) {
while (at(SEMICOLON)) advance(); // SEMICOLON while (at(SEMICOLON)) advance(); // SEMICOLON
while (!eof() && !at(RBRACE)) { while (!eof() && !at(RBRACE)) {
if (!atSet(STATEMENT_FIRST)) { if (!atSet(STATEMENT_FIRST)) {
errorAndAdvance("Expecting an element"); errorAndAdvance("Expecting an element");
} }
if (atSet(STATEMENT_FIRST)) { if (atSet(STATEMENT_FIRST)) {
parseStatement(); parseStatement(isScriptTopLevel);
} }
if (at(SEMICOLON)) { if (at(SEMICOLON)) {
while (at(SEMICOLON)) advance(); // SEMICOLON while (at(SEMICOLON)) advance(); // SEMICOLON
@@ -1214,11 +1222,16 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
* : declaration * : declaration
* ; * ;
*/ */
private void parseStatement() { private void parseStatement(boolean isScriptTopLevel) {
if (!parseLocalDeclaration()) { if (!parseLocalDeclaration()) {
if (!atSet(EXPRESSION_FIRST)) { if (!atSet(EXPRESSION_FIRST)) {
errorAndAdvance("Expecting a statement"); errorAndAdvance("Expecting a statement");
} }
else if (isScriptTopLevel){
PsiBuilder.Marker scriptInitializer = mark();
parseExpression();
scriptInitializer.done(ANONYMOUS_INITIALIZER);
}
else { else {
parseExpression(); parseExpression();
} }
@@ -160,7 +160,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
PsiBuilder.Marker blockMarker = mark(); PsiBuilder.Marker blockMarker = mark();
myExpressionParsing.parseStatements(); myExpressionParsing.parseStatements(/*isScriptTopLevel = */true);
checkForUnexpectedSymbols(); checkForUnexpectedSymbols();
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi;
import com.intellij.lang.ASTNode; import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.lexer.KtTokens;
@@ -59,4 +60,15 @@ public class KtClassInitializer extends KtDeclarationStub<KotlinPlaceHolderStub<
public PsiElement getInitKeyword() { public PsiElement getInitKeyword() {
return findChildByType(KtTokens.INIT_KEYWORD); return findChildByType(KtTokens.INIT_KEYWORD);
} }
@NotNull
public KtDeclaration getContainingDeclaration() {
KtClassOrObject classOrObject = PsiTreeUtil.getParentOfType(this, KtClassOrObject.class, true);
if (classOrObject != null) {
return classOrObject;
}
KtScript type = PsiTreeUtil.getParentOfType(this, KtScript.class, true);
assert type != null : "Should only be present in class, object or script";
return type;
}
} }
+2
View File
@@ -58,6 +58,7 @@ JetFile: ComplexScript.kts
PsiWhiteSpace('\n') PsiWhiteSpace('\n')
PsiElement(RBRACE)('}') PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n') PsiWhiteSpace('\n\n')
ANONYMOUS_INITIALIZER
IF IF
PsiElement(if)('if') PsiElement(if)('if')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
@@ -97,6 +98,7 @@ JetFile: ComplexScript.kts
PsiWhiteSpace('\n') PsiWhiteSpace('\n')
PsiElement(RBRACE)('}') PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n') PsiWhiteSpace('\n\n')
ANONYMOUS_INITIALIZER
FOR FOR
PsiElement(for)('for') PsiElement(for)('for')
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
+1
View File
@@ -7,6 +7,7 @@ JetFile: Shebang.kts
PsiWhiteSpace('\n\n') PsiWhiteSpace('\n\n')
SCRIPT SCRIPT
BLOCK BLOCK
ANONYMOUS_INITIALIZER
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('println') PsiElement(IDENTIFIER)('println')
+2
View File
@@ -5,6 +5,7 @@ JetFile: ShebangIncorrect.kts
<empty list> <empty list>
SCRIPT SCRIPT
BLOCK BLOCK
ANONYMOUS_INITIALIZER
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('println') PsiElement(IDENTIFIER)('println')
@@ -18,6 +19,7 @@ JetFile: ShebangIncorrect.kts
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
PsiErrorElement:Expecting an element PsiErrorElement:Expecting an element
PsiElement(HASH)('#') PsiElement(HASH)('#')
ANONYMOUS_INITIALIZER
BINARY_EXPRESSION BINARY_EXPRESSION
PREFIX_EXPRESSION PREFIX_EXPRESSION
OPERATION_REFERENCE OPERATION_REFERENCE
+1
View File
@@ -5,6 +5,7 @@ JetFile: SimpleScript.kts
<empty list> <empty list>
SCRIPT SCRIPT
BLOCK BLOCK
ANONYMOUS_INITIALIZER
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('println') PsiElement(IDENTIFIER)('println')
+1
View File
@@ -5,6 +5,7 @@ JetFile: unexpectedSymbol.kts
<empty list> <empty list>
SCRIPT SCRIPT
BLOCK BLOCK
ANONYMOUS_INITIALIZER
CALL_EXPRESSION CALL_EXPRESSION
REFERENCE_EXPRESSION REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('println') PsiElement(IDENTIFIER)('println')
@@ -41,6 +41,12 @@ public abstract class AbstractParsingTest extends ParsingTestCase {
System.setProperty("idea.platform.prefix", "Idea"); System.setProperty("idea.platform.prefix", "Idea");
} }
@Override
protected void setUp() throws Exception {
super.setUp();
getProject().registerService(KotlinScriptDefinitionProvider.class);
}
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return KotlinTestUtils.getHomeDirectory(); return KotlinTestUtils.getHomeDirectory();