From c4fa51c16e9ee7a1305b9b82bc2498fa28c687ed Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 3 Jan 2011 17:10:15 +0300 Subject: [PATCH] Call with closure is available inside the by clause in nested expressions, see the test --- .../jet/lang/parsing/JetParsing.java | 13 +- .../SemanticWhitespaceAwarePsiBuilder.java | 1 + ...anticWhitespaceAwarePsiBuilderAdapter.java | 36 ++ ...cWhitespaceAwarePsiBuilderForByClause.java | 37 ++ ...atedSemanticWhitespaceAwarePsiBuilder.java | 28 +- idea/testData/psi/ByCaluses.jet | 23 ++ idea/testData/psi/ByCaluses.txt | 326 ++++++++++++++++++ 7 files changed, 434 insertions(+), 30 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderAdapter.java create mode 100644 idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderForByClause.java create mode 100644 idea/testData/psi/ByCaluses.jet create mode 100644 idea/testData/psi/ByCaluses.txt diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 4632f8202bb..aa1e880d0f8 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -46,10 +46,14 @@ public class JetParsing extends AbstractJetParsing { } public static JetParsing createForByClause(final SemanticWhitespaceAwarePsiBuilder builder) { - JetParsing jetParsing = new JetParsing(builder); - jetParsing.myExpressionParsing = new JetExpressionParsing(builder, jetParsing) { + final SemanticWhitespaceAwarePsiBuilderForByClause builderForByClause = new SemanticWhitespaceAwarePsiBuilderForByClause(builder); + JetParsing jetParsing = new JetParsing(builderForByClause); + jetParsing.myExpressionParsing = new JetExpressionParsing(builderForByClause, jetParsing) { @Override protected boolean parseCallWithClosure() { + if (builderForByClause.getStackSize() > 0) { + return super.parseCallWithClosure(); + } return false; } @@ -527,7 +531,7 @@ public class JetParsing extends AbstractJetParsing { * ; */ /*package*/ void parseClassBody() { - // TODO : initializer? + // TODO : anonymous initializer, like {...} in Java? assert at(LBRACE); PsiBuilder.Marker body = mark(); @@ -1003,7 +1007,6 @@ public class JetParsing extends AbstractJetParsing { if (at(BY_KEYWORD)) { advance(); // BY_KEYWORD - // TODO: discuss: in nested expressions (including method bodies) one cannot use foo {bar} either, but this is required only for the top level createForByClause(myBuilder).myExpressionParsing.parseExpression(); delegator.done(DELEGATOR_BY); } @@ -1336,7 +1339,7 @@ public class JetParsing extends AbstractJetParsing { int lastLPar = findLastBefore(TokenSet.create(LPAR), TokenSet.create(RBRACE, COLON), false); if (lastLPar >= 0 && lastLPar > myBuilder.getCurrentOffset()) { PsiBuilder.Marker receiverType = mark(); - // TODO : -1 is a hack + // TODO : -1 is a hack? createTruncatedBuilder(lastLPar - 1).parseTypeRef(); receiverType.done(RECEIVER_TYPE); advance(); // DOT diff --git a/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilder.java b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilder.java index 7815ed8e842..db52db97a14 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilder.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilder.java @@ -6,6 +6,7 @@ import com.intellij.lang.PsiBuilder; * @author abreslav */ public interface SemanticWhitespaceAwarePsiBuilder extends PsiBuilder { + // TODO: Wrong name, should be something like "EOL before current token" boolean eolInLastWhitespace(); void disableEols(); void enableEols(); diff --git a/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderAdapter.java b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderAdapter.java new file mode 100644 index 00000000000..5e6c4a1bef4 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderAdapter.java @@ -0,0 +1,36 @@ +package org.jetbrains.jet.lang.parsing; + +/** + * @author abreslav + */ +public class SemanticWhitespaceAwarePsiBuilderAdapter extends PsiBuilderAdapter implements SemanticWhitespaceAwarePsiBuilder { + + private final SemanticWhitespaceAwarePsiBuilder myBuilder; + + + public SemanticWhitespaceAwarePsiBuilderAdapter(SemanticWhitespaceAwarePsiBuilder builder) { + super(builder); + this.myBuilder = builder; + } + + @Override + public boolean eolInLastWhitespace() { + return myBuilder.eolInLastWhitespace(); + } + + @Override + public void disableEols() { + myBuilder.disableEols(); + } + + @Override + public void enableEols() { + myBuilder.enableEols(); + } + + @Override + public void restoreEolsState() { + myBuilder.restoreEolsState(); + } + +} diff --git a/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderForByClause.java b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderForByClause.java new file mode 100644 index 00000000000..9fafbbb847b --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/parsing/SemanticWhitespaceAwarePsiBuilderForByClause.java @@ -0,0 +1,37 @@ +package org.jetbrains.jet.lang.parsing; + +import com.intellij.psi.tree.IElementType; + +/** + * @author abreslav + */ +public class SemanticWhitespaceAwarePsiBuilderForByClause extends SemanticWhitespaceAwarePsiBuilderAdapter { + + private int stackSize = 0; + + public SemanticWhitespaceAwarePsiBuilderForByClause(SemanticWhitespaceAwarePsiBuilder builder) { + super(builder); + } + + @Override + public void disableEols() { + super.disableEols(); + stackSize++; + } + + @Override + public void enableEols() { + super.enableEols(); + stackSize++; + } + + @Override + public void restoreEolsState() { + super.restoreEolsState(); + stackSize--; + } + + public int getStackSize() { + return stackSize; + } +} diff --git a/idea/src/org/jetbrains/jet/lang/parsing/TruncatedSemanticWhitespaceAwarePsiBuilder.java b/idea/src/org/jetbrains/jet/lang/parsing/TruncatedSemanticWhitespaceAwarePsiBuilder.java index 010c17e9808..b9700249cee 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/TruncatedSemanticWhitespaceAwarePsiBuilder.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/TruncatedSemanticWhitespaceAwarePsiBuilder.java @@ -5,38 +5,16 @@ import com.intellij.psi.tree.IElementType; /** * @author abreslav */ -public class TruncatedSemanticWhitespaceAwarePsiBuilder extends PsiBuilderAdapter implements SemanticWhitespaceAwarePsiBuilder { +public class TruncatedSemanticWhitespaceAwarePsiBuilder extends SemanticWhitespaceAwarePsiBuilderAdapter { - private final SemanticWhitespaceAwarePsiBuilder myBuilder; private final int myEOFPosition; - public TruncatedSemanticWhitespaceAwarePsiBuilder(SemanticWhitespaceAwarePsiBuilder myBuilder, int eofPosition) { - super(myBuilder); - this.myBuilder = myBuilder; + public TruncatedSemanticWhitespaceAwarePsiBuilder(SemanticWhitespaceAwarePsiBuilder builder, int eofPosition) { + super(builder); this.myEOFPosition = eofPosition; } - @Override - public boolean eolInLastWhitespace() { - return myBuilder.eolInLastWhitespace(); - } - - @Override - public void disableEols() { - myBuilder.disableEols();; - } - - @Override - public void enableEols() { - myBuilder.enableEols(); - } - - @Override - public void restoreEolsState() { - myBuilder.restoreEolsState(); - } - @Override public boolean eof() { if (super.eof()) return true; diff --git a/idea/testData/psi/ByCaluses.jet b/idea/testData/psi/ByCaluses.jet new file mode 100644 index 00000000000..b6cab943917 --- /dev/null +++ b/idea/testData/psi/ByCaluses.jet @@ -0,0 +1,23 @@ +class A : b by a { + this() {} +} +class A : b by a + b() * 5 { + this() {} +} +class A : b by (a) { + this() {} +} +class A : b by (a {}) { + this() {} +} +class A : b by a[a {}] { + this() {} +} +class A : b by a(a {}) { + this() {} +} +class A : b by object { + fun f() = a {} +} { + this() {} +} \ No newline at end of file diff --git a/idea/testData/psi/ByCaluses.txt b/idea/testData/psi/ByCaluses.txt new file mode 100644 index 00000000000..c91eadf006f --- /dev/null +++ b/idea/testData/psi/ByCaluses.txt @@ -0,0 +1,326 @@ +JetFile: ByCaluses.jet + NAMESPACE + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + BINARY_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(PLUS)('+') + PsiWhiteSpace(' ') + BINARY_EXPRESSION + CALL_EXPRESSION + PsiElement(IDENTIFIER)('b') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(MUL)('*') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('5') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + TUPLE + PsiElement(LPAR)('(') + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + TUPLE + PsiElement(LPAR)('(') + CALL_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + BODY + + PsiElement(RBRACE)('}') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + ARRAY_ACCESS_EXPRESSION + PsiElement(IDENTIFIER)('a') + INDICES + PsiElement(LBRACKET)('[') + CALL_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + BODY + + PsiElement(RBRACE)('}') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + CALL_EXPRESSION + PsiElement(IDENTIFIER)('a') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + CALL_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + BODY + + PsiElement(RBRACE)('}') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + CLASS + PsiElement(class)('class') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('A') + PsiWhiteSpace(' ') + TYPE_PARAMETER_LIST + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + DELEGATION_SPECIFIER_LIST + DELEGATION_SPECIFIER + DELEGATOR_BY + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('b') + PsiWhiteSpace(' ') + PsiElement(by)('by') + PsiWhiteSpace(' ') + OBJECT_LITERAL + PsiElement(object)('object') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') + TYPE_PARAMETER_LIST + + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + CALL_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + BODY + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CLASS_BODY + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CONSTRUCTOR + PsiElement(this)('this') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file