Make KtLambdaExpression lazy parsable element
(cherry picked from commit 533fca1)
This commit is contained in:
committed by
Nikolay Krasko
parent
1d24fc3a7b
commit
37492fcc78
@@ -16,9 +16,20 @@
|
||||
|
||||
package org.jetbrains.kotlin;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiBuilderFactory;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.IErrorCounterReparseableElementType;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage;
|
||||
import org.jetbrains.kotlin.lexer.KotlinLexer;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.parsing.KotlinParser;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
|
||||
|
||||
@@ -115,7 +126,48 @@ public interface KtNodeTypes {
|
||||
KtNodeType LOOP_RANGE = new KtNodeType("LOOP_RANGE", KtContainerNode.class);
|
||||
KtNodeType BODY = new KtNodeType("BODY", KtContainerNode.class);
|
||||
KtNodeType BLOCK = new KtNodeType("BLOCK", KtBlockExpression.class);
|
||||
KtNodeType LAMBDA_EXPRESSION = new KtNodeType("LAMBDA_EXPRESSION", KtLambdaExpression.class);
|
||||
|
||||
IElementType LAMBDA_EXPRESSION = new IErrorCounterReparseableElementType("LAMBDA_EXPRESSION", KotlinLanguage.INSTANCE) {
|
||||
@Override
|
||||
public ASTNode parseContents(ASTNode chameleon) {
|
||||
Project project = chameleon.getPsi().getProject();
|
||||
PsiBuilder builder = PsiBuilderFactory.getInstance().createBuilder(project, chameleon, null, KotlinLanguage.INSTANCE, chameleon.getChars());
|
||||
return KotlinParser.parseLambdaExpression(builder).getFirstChildNode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ASTNode createNode(CharSequence text) {
|
||||
return new KtLambdaExpression(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getErrorsCount(CharSequence seq, Language fileLanguage, Project project) {
|
||||
Lexer lexer = new KotlinLexer();
|
||||
|
||||
lexer.start(seq);
|
||||
if (lexer.getTokenType() != KtTokens.LBRACE) return IErrorCounterReparseableElementType.FATAL_ERROR;
|
||||
lexer.advance();
|
||||
int balance = 1;
|
||||
while (true) {
|
||||
IElementType type = lexer.getTokenType();
|
||||
if (type == null) break;
|
||||
if (balance == 0) {
|
||||
return IErrorCounterReparseableElementType.FATAL_ERROR;
|
||||
}
|
||||
if (type == KtTokens.LBRACE) {
|
||||
balance++;
|
||||
}
|
||||
else if (type == KtTokens.RBRACE) {
|
||||
balance--;
|
||||
}
|
||||
lexer.advance();
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KtNodeType FUNCTION_LITERAL = new KtNodeType("FUNCTION_LITERAL", KtFunctionLiteral.class);
|
||||
KtNodeType ANNOTATED_EXPRESSION = new KtNodeType("ANNOTATED_EXPRESSION", KtAnnotatedExpression.class);
|
||||
|
||||
|
||||
@@ -573,7 +573,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
return false;
|
||||
}
|
||||
|
||||
parseFunctionLiteral(preferBlock);
|
||||
parseFunctionLiteral(preferBlock, /* collapse = */true);
|
||||
|
||||
doneOrDrop(labeled, LABELED_EXPRESSION, wasLabel);
|
||||
doneOrDrop(annotated, ANNOTATED_EXPRESSION, wereAnnotations);
|
||||
@@ -1033,10 +1033,10 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
* ;
|
||||
*/
|
||||
private void parseFunctionLiteral() {
|
||||
parseFunctionLiteral(/* preferBlock = */false);
|
||||
parseFunctionLiteral(/* preferBlock = */false, /* collapse = */true);
|
||||
}
|
||||
|
||||
private void parseFunctionLiteral(boolean preferBlock) {
|
||||
public void parseFunctionLiteral(boolean preferBlock, boolean collapse) {
|
||||
assert _at(LBRACE);
|
||||
|
||||
PsiBuilder.Marker literalExpression = mark();
|
||||
@@ -1088,7 +1088,12 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
myBuilder.restoreNewlinesState();
|
||||
|
||||
literal.done(FUNCTION_LITERAL);
|
||||
literalExpression.done(LAMBDA_EXPRESSION);
|
||||
if (collapse) {
|
||||
literalExpression.collapse(LAMBDA_EXPRESSION);
|
||||
}
|
||||
else {
|
||||
literalExpression.done(LAMBDA_EXPRESSION);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean rollbackOrDropAt(PsiBuilder.Marker rollbackMarker, IElementType dropAt) {
|
||||
|
||||
@@ -73,4 +73,11 @@ public class KotlinParser implements PsiParser {
|
||||
ktParsing.parseBlockCodeFragment();
|
||||
return psiBuilder.getTreeBuilt();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ASTNode parseLambdaExpression(PsiBuilder psiBuilder) {
|
||||
KotlinParsing ktParsing = KotlinParsing.createForTopLevel(new SemanticWhitespaceAwarePsiBuilderImpl(psiBuilder));
|
||||
ktParsing.parseLambdaExpression();
|
||||
return psiBuilder.getTreeBuilt();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +156,10 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
marker.done(BLOCK_CODE_FRAGMENT);
|
||||
}
|
||||
|
||||
void parseLambdaExpression() {
|
||||
myExpressionParsing.parseFunctionLiteral(/* preferBlock = */ false, /* collapse = */false);
|
||||
}
|
||||
|
||||
void parseScript() {
|
||||
PsiBuilder.Marker fileMarker = mark();
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
package org.jetbrains.kotlin.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.LazyParseablePsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.KtNodeTypes;
|
||||
@@ -24,9 +27,9 @@ import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class KtLambdaExpression extends KtExpressionImpl {
|
||||
public KtLambdaExpression(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
public class KtLambdaExpression extends LazyParseablePsiElement implements KtExpression {
|
||||
public KtLambdaExpression(CharSequence text) {
|
||||
super(KtNodeTypes.LAMBDA_EXPRESSION, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,7 +39,7 @@ public class KtLambdaExpression extends KtExpressionImpl {
|
||||
|
||||
@NotNull
|
||||
public KtFunctionLiteral getFunctionLiteral() {
|
||||
return (KtFunctionLiteral) findChildByType(KtNodeTypes.FUNCTION_LITERAL);
|
||||
return findChildByType(KtNodeTypes.FUNCTION_LITERAL).getPsi(KtFunctionLiteral.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -67,4 +70,32 @@ public class KtLambdaExpression extends KtExpressionImpl {
|
||||
public ASTNode getRightCurlyBrace() {
|
||||
return getFunctionLiteral().getNode().findChildByType(KtTokens.RBRACE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KtFile getContainingKtFile() {
|
||||
PsiFile file = getContainingFile();
|
||||
assert file instanceof KtFile : "KtElement not inside KtFile: " + file + " " + file.getText();
|
||||
return (KtFile) file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D> void acceptChildren(@NotNull KtVisitor<Void, D> visitor, D data) {
|
||||
KtPsiUtil.visitChildren(this, visitor, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof KtVisitor) {
|
||||
accept((KtVisitor) visitor, null);
|
||||
}
|
||||
else {
|
||||
visitor.visitElement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNode().getElementType().toString();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user