diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractTokenStreamPattern.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractTokenStreamPattern.java index c5882440fd8..437b1536408 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractTokenStreamPattern.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/AbstractTokenStreamPattern.java @@ -40,5 +40,9 @@ public abstract class AbstractTokenStreamPattern implements TokenStreamPattern { public boolean handleUnmatchedClosing(IElementType token) { return false; } + + public void reset() { + lastOccurrence = -1; + } } diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java index a2bd46aa745..e0193bdc311 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/KotlinParsing.java @@ -133,6 +133,33 @@ public class KotlinParsing extends AbstractKotlinParsing { private KotlinExpressionParsing myExpressionParsing; + private final FirstBefore lastDotAfterReceiverLParPattern = new FirstBefore( + new AtSet(RECEIVER_TYPE_TERMINATORS), + new AbstractTokenStreamPredicate() { + @Override + public boolean matching(boolean topLevel) { + if (topLevel && atSet(definitelyOutOfReceiverSet)) { + return true; + } + return topLevel && !at(QUEST) && !at(LPAR) && !at(RPAR); + } + } + ); + + private final LastBefore lastDotAfterReceiverNotLParPattern = new LastBefore( + new AtSet(RECEIVER_TYPE_TERMINATORS), + new AbstractTokenStreamPredicate() { + @Override + public boolean matching(boolean topLevel) { + if (topLevel && (atSet(definitelyOutOfReceiverSet) || at(LPAR))) return true; + if (topLevel && at(IDENTIFIER)) { + IElementType lookahead = lookahead(1); + return lookahead != LT && lookahead != DOT && lookahead != SAFE_ACCESS && lookahead != QUEST; + } + return false; + } + }); + private KotlinParsing(SemanticWhitespaceAwarePsiBuilder builder) { super(builder); } @@ -1848,41 +1875,9 @@ public class KotlinParsing extends AbstractKotlinParsing { } private int lastDotAfterReceiver() { - if (at(LPAR)) { - return matchTokenStreamPredicate( - new FirstBefore( - new AtSet(RECEIVER_TYPE_TERMINATORS), - new AbstractTokenStreamPredicate() { - @Override - public boolean matching(boolean topLevel) { - if (topLevel && definitelyOutOfReceiver()) { - return true; - } - return topLevel && !at(QUEST) && !at(LPAR) && !at(RPAR); - } - } - )); - } - else { - return matchTokenStreamPredicate( - new LastBefore( - new AtSet(RECEIVER_TYPE_TERMINATORS), - new AbstractTokenStreamPredicate() { - @Override - public boolean matching(boolean topLevel) { - if (topLevel && (definitelyOutOfReceiver() || at(LPAR))) return true; - if (topLevel && at(IDENTIFIER)) { - IElementType lookahead = lookahead(1); - return lookahead != LT && lookahead != DOT && lookahead != SAFE_ACCESS && lookahead != QUEST; - } - return false; - } - })); - } - } - - private boolean definitelyOutOfReceiver() { - return atSet(definitelyOutOfReceiverSet); + AbstractTokenStreamPattern pattern = at(LPAR) ? lastDotAfterReceiverLParPattern : lastDotAfterReceiverNotLParPattern; + pattern.reset(); + return matchTokenStreamPredicate(pattern); } /* diff --git a/compiler/psi/src/org/jetbrains/kotlin/parsing/LastBefore.java b/compiler/psi/src/org/jetbrains/kotlin/parsing/LastBefore.java index f6033ad462a..c3bd59546e5 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/parsing/LastBefore.java +++ b/compiler/psi/src/org/jetbrains/kotlin/parsing/LastBefore.java @@ -47,4 +47,10 @@ public class LastBefore extends AbstractTokenStreamPattern { previousLookForResult = lookForResult; return false; } + + @Override + public void reset() { + super.reset(); + previousLookForResult = false; + } }