diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 7b933bc52379..5e19fa2b585c 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -174,7 +174,7 @@ public class DeclarationParser { } } - private static void parseClassBodyDeclarations(final PsiBuilder builder, final boolean isAnnotation) { + public static void parseClassBodyDeclarations(final PsiBuilder builder, final boolean isAnnotation) { final Context context = isAnnotation ? Context.ANNOTATION_INTERFACE : Context.CLASS; PsiBuilder.Marker invalidElements = null; diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index 5f7105e29f22..f6f698da2cf3 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -20,7 +20,9 @@ import com.intellij.lang.*; import com.intellij.lang.java.JavaParserDefinition; import com.intellij.lexer.Lexer; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.JavaTokenType; @@ -43,6 +45,8 @@ import java.util.List; public class JavaParserUtil { private static final Key LANG_LEVEL_KEY = Key.create("JavaParserUtil.LanguageLevel"); + private static final Key DEEP_PARSE_BLOCKS_IN_STATEMENTS = Key.create("JavaParserUtil.ParserExtender"); + private static final Key PARSER_EXTENDER_KEY = Key.create("JavaParserUtil.ParserExtender"); public interface ParserWrapper { void parse(PsiBuilder builder); @@ -52,6 +56,10 @@ public class JavaParserUtil { @Nullable PsiBuilder.Marker parse(PsiBuilder builder); } + public interface ParserExtender extends MarkingParserWrapper { + boolean enroll(PsiBuilder builder); + } + public static final WhitespacesAndCommentsBinder GREEDY_RIGHT_EDGE_PROCESSOR = new WhitespacesAndCommentsBinder() { public int getEdgePosition(final List tokens, final boolean atStreamEdge, final TokenTextGetter getter) { return tokens.size(); @@ -145,6 +153,24 @@ public class JavaParserUtil { return level; } + public static void setParseStatementCodeBlocksDeep(final PsiBuilder builder, final boolean deep) { + builder.putUserDataUnprotected(DEEP_PARSE_BLOCKS_IN_STATEMENTS, deep); + } + + public static boolean isParseStatementCodeBlocksDeep(final PsiBuilder builder) { + return Boolean.TRUE.equals(builder.getUserDataUnprotected(DEEP_PARSE_BLOCKS_IN_STATEMENTS)); + } + + public static void setParserExtender(final PsiBuilder builder, final ParserExtender extender) { + builder.putUserDataUnprotected(PARSER_EXTENDER_KEY, extender); + } + + @Nullable + public static ParserExtender getParserExtender(final PsiBuilder builder) { + final ParserExtender extender = builder.getUserDataUnprotected(PARSER_EXTENDER_KEY); + return extender != null && extender.enroll(builder) ? extender : null; + } + @NotNull public static PsiBuilder createBuilder(final ASTNode chameleon) { final PsiElement psi = chameleon.getPsi(); @@ -291,6 +317,22 @@ public class JavaParserUtil { }; } + public static PsiBuilder stoppingBuilder(final PsiBuilder builder, final Condition> condition) { + return new PsiBuilderAdapter(builder) { + @Override + public IElementType getTokenType() { + final Pair input = Pair.create(builder.getTokenType(), builder.getTokenText()); + return condition.value(input) ? null : super.getTokenType(); + } + + @Override + public boolean eof() { + final Pair input = Pair.create(builder.getTokenType(), builder.getTokenText()); + return condition.value(input) || super.eof(); + } + }; + } + public static class PsiBuilderAdapter implements PsiBuilder { protected final PsiBuilder myDelegate; @@ -298,23 +340,27 @@ public class JavaParserUtil { myDelegate = delegate; } + @Override public Project getProject() { return myDelegate.getProject(); } + @Override public CharSequence getOriginalText() { return myDelegate.getOriginalText(); } + @Override public void advanceLexer() { myDelegate.advanceLexer(); } - @Nullable + @Override @Nullable public IElementType getTokenType() { return myDelegate.getTokenType(); } + @Override public void setTokenTypeRemapper(final ITokenTypeRemapper remapper) { myDelegate.setTokenTypeRemapper(remapper); } @@ -344,53 +390,62 @@ public class JavaParserUtil { return myDelegate.rawTokenTypeStart(steps); } - @Nullable @NonNls + @Override @Nullable @NonNls public String getTokenText() { return myDelegate.getTokenText(); } + @Override public int getCurrentOffset() { return myDelegate.getCurrentOffset(); } + @Override public Marker mark() { return myDelegate.mark(); } + @Override public void error(final String messageText) { myDelegate.error(messageText); } + @Override public boolean eof() { return myDelegate.eof(); } + @Override public ASTNode getTreeBuilt() { return myDelegate.getTreeBuilt(); } + @Override public FlyweightCapableTreeStructure getLightTree() { return myDelegate.getLightTree(); } + @Override public void setDebugMode(final boolean dbgMode) { myDelegate.setDebugMode(dbgMode); } + @Override public void enforceCommentTokens(final TokenSet tokens) { myDelegate.enforceCommentTokens(tokens); } - @Nullable + @Override @Nullable public LighterASTNode getLatestDoneMarker() { return myDelegate.getLatestDoneMarker(); } - @Nullable + @Override @Nullable public T getUserData(@NotNull final Key key) { return myDelegate.getUserData(key); } + @Override public void putUserData(@NotNull final Key key, @Nullable final T value) { myDelegate.putUserData(key, value); } @@ -401,7 +456,7 @@ public class JavaParserUtil { } @Override - public void putUserDataUnprotected(@NotNull Key key, @Nullable T value) { + public void putUserDataUnprotected(@NotNull final Key key, @Nullable final T value) { myDelegate.putUserDataUnprotected(key, value); } } diff --git a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java index 42c861dc6cfa..38f055b08a61 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/StatementParser.java @@ -34,8 +34,6 @@ import static com.intellij.lang.java.parser.JavaParserUtil.*; public class StatementParser { - private static final boolean DEEP_PARSE_BLOCKS_IN_STATEMENTS = false; - private enum BraceMode { TILL_FIRST, TILL_LAST } @@ -46,8 +44,13 @@ public class StatementParser { @Nullable public static PsiBuilder.Marker parseCodeBlock(final PsiBuilder builder) { + return parseCodeBlock(builder, false); + } + + @Nullable + public static PsiBuilder.Marker parseCodeBlock(final PsiBuilder builder, final boolean isStatement) { if (builder.getTokenType() != JavaTokenType.LBRACE) return null; - else if (DEEP_PARSE_BLOCKS_IN_STATEMENTS) return parseCodeBlockDeep(builder, false); + else if (isStatement && isParseStatementCodeBlocksDeep(builder)) return parseCodeBlockDeep(builder, false); final PsiBuilder.Marker codeBlock = builder.mark(); builder.advanceLexer(); @@ -166,10 +169,10 @@ public class StatementParser { @Nullable public static PsiBuilder.Marker parseStatement(final PsiBuilder builder) { + final ParserExtender extender = getParserExtender(builder); + if (extender != null) return extender.parse(builder); + final IElementType tokenType = builder.getTokenType(); - - // todo: custom parsers (?) - if (tokenType == JavaTokenType.IF_KEYWORD) { return parseIfStatement(builder); } @@ -507,7 +510,7 @@ public class StatementParser { return statement; } - final PsiBuilder.Marker body = parseCodeBlock(builder); + final PsiBuilder.Marker body = parseCodeBlock(builder, true); if (body == null) { error(builder, JavaErrorMessages.message("expected.lbrace")); } @@ -595,7 +598,7 @@ public class StatementParser { return statement; } - final PsiBuilder.Marker body = parseCodeBlock(builder); + final PsiBuilder.Marker body = parseCodeBlock(builder, true); if (body == null) { error(builder, JavaErrorMessages.message("expected.lbrace")); } @@ -609,7 +612,7 @@ public class StatementParser { final PsiBuilder.Marker statement = builder.mark(); builder.advanceLexer(); - final PsiBuilder.Marker tryBlock = parseCodeBlock(builder); + final PsiBuilder.Marker tryBlock = parseCodeBlock(builder, true); if (tryBlock == null) { error(builder, JavaErrorMessages.message("expected.lbrace")); done(statement, JavaElementType.TRY_STATEMENT); @@ -627,7 +630,7 @@ public class StatementParser { } if (expect(builder, JavaTokenType.FINALLY_KEYWORD)) { - final PsiBuilder.Marker finallyBlock = parseCodeBlock(builder); + final PsiBuilder.Marker finallyBlock = parseCodeBlock(builder, true); if (finallyBlock == null) { error(builder, JavaErrorMessages.message("expected.lbrace")); } @@ -659,7 +662,7 @@ public class StatementParser { return false; } - final PsiBuilder.Marker body = parseCodeBlock(builder); + final PsiBuilder.Marker body = parseCodeBlock(builder, true); if (body == null) { error(builder, JavaErrorMessages.message("expected.lbrace")); done(section, JavaElementType.CATCH_SECTION); @@ -699,7 +702,7 @@ public class StatementParser { @NotNull private static PsiBuilder.Marker parseBlockStatement(final PsiBuilder builder) { final PsiBuilder.Marker statement = builder.mark(); - parseCodeBlock(builder); + parseCodeBlock(builder, true); done(statement, JavaElementType.BLOCK_STATEMENT); return statement; } diff --git a/java/jsp-spi/src/com/intellij/psi/jsp/JspElementType.java b/java/jsp-spi/src/com/intellij/psi/jsp/JspElementType.java index 77201eca79bf..a9f7ca3dbb6a 100644 --- a/java/jsp-spi/src/com/intellij/psi/jsp/JspElementType.java +++ b/java/jsp-spi/src/com/intellij/psi/jsp/JspElementType.java @@ -15,27 +15,32 @@ */ package com.intellij.psi.jsp; -import com.intellij.lang.StdLanguages; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.jsp.IJspElementType; /** * @author peter + * todo[r.sh] replace usages with JspElementTypeEx in implementation modules */ -public interface JspElementType extends JspTokenType /*extends BaseJspElementType, ELElementType*/ { - IElementType HOLDER_TEMPLATE_DATA = new IJspElementType("HOLDER_TEMPLATE_DATA"); +public interface JspElementType extends JspTokenType { + enum Kind { + HOLDER_TEMPLATE_DATA, JSP_TEMPLATE_EXPRESSION, HOLDER_METHOD, JSP_TEMPLATE_STATEMENT, JSP_CLASS_LEVEL_DECLARATION_STATEMENT, + JSP_CODE_BLOCK, JSP_WHILE_STATEMENT, JSP_BLOCK_STATEMENT, JSP_CLASS, JSP_METHOD_CALL, JSP_EXPRESSION, JSP_SCRIPTLET + } - IElementType JSP_TEMPLATE_EXPRESSION = new IElementType("JSP_TEMPLATE_EXPRESSION", StdLanguages.JAVA); - IElementType HOLDER_METHOD = new IJspElementType("HOLDER_METHOD"); + IElementType HOLDER_TEMPLATE_DATA = JspSpiUtil.getJspElementType(Kind.HOLDER_TEMPLATE_DATA); + + IElementType JSP_TEMPLATE_EXPRESSION = JspSpiUtil.getJspElementType(Kind.JSP_TEMPLATE_EXPRESSION); + IElementType HOLDER_METHOD = JspSpiUtil.getJspElementType(Kind.HOLDER_METHOD); - IElementType JSP_TEMPLATE_STATEMENT = new IElementType("JSP_TEMPLATE_STATEMENT", StdLanguages.JAVA); - IElementType JSP_CLASS_LEVEL_DECLARATION_STATEMENT = new IElementType("JSP_CLASS_LEVEL_DECLARATION_STATEMENT", StdLanguages.JAVA); - IElementType JSP_CODE_BLOCK = new IElementType("JSP_CODE_BLOCK", StdLanguages.JAVA); - IElementType JSP_WHILE_STATEMENT = new IElementType("JSP_DO_WHILE_STATEMENT", StdLanguages.JAVA); - IElementType JSP_BLOCK_STATEMENT = new IElementType("JSP_BLOCK_STATEMENT", StdLanguages.JAVA); + IElementType JSP_TEMPLATE_STATEMENT = JspSpiUtil.getJspElementType(Kind.JSP_TEMPLATE_STATEMENT); + IElementType JSP_CLASS_LEVEL_DECLARATION_STATEMENT = JspSpiUtil.getJspElementType(Kind.JSP_CLASS_LEVEL_DECLARATION_STATEMENT); + IElementType JSP_CODE_BLOCK = JspSpiUtil.getJspElementType(Kind.JSP_CODE_BLOCK); + IElementType JSP_WHILE_STATEMENT = JspSpiUtil.getJspElementType(Kind.JSP_WHILE_STATEMENT); + IElementType JSP_BLOCK_STATEMENT = JspSpiUtil.getJspElementType(Kind.JSP_BLOCK_STATEMENT); + + IElementType JSP_CLASS = JspSpiUtil.getJspElementType(Kind.JSP_CLASS); + IElementType JSP_METHOD_CALL = JspSpiUtil.getJspElementType(Kind.JSP_METHOD_CALL); - IElementType JSP_CLASS = new IJspElementType("JSP_CLASS"); - IElementType JSP_METHOD_CALL = new IElementType("JSP_METHOD_CALL", StdLanguages.JAVA); IElementType JSP_EXPRESSION = JspSpiUtil.getJspExpressionType(); IElementType JSP_SCRIPTLET = JspSpiUtil.getJspScriptletType(); } diff --git a/java/jsp-spi/src/com/intellij/psi/jsp/JspSpiUtil.java b/java/jsp-spi/src/com/intellij/psi/jsp/JspSpiUtil.java index 01ba9e47b174..5f78d155c774 100644 --- a/java/jsp-spi/src/com/intellij/psi/jsp/JspSpiUtil.java +++ b/java/jsp-spi/src/com/intellij/psi/jsp/JspSpiUtil.java @@ -217,16 +217,21 @@ public abstract class JspSpiUtil { } } + @Nullable + public static IElementType getJspElementType(@NotNull final JspElementType.Kind kind) { + final JspSpiUtil spiUtil = getJspSpiUtil(); + return spiUtil != null ? spiUtil._getJspElementType(kind) : null; + } + + @Nullable public static IElementType getJspScriptletType() { - JspSpiUtil spiUtil = getJspSpiUtil(); - return spiUtil != null ? spiUtil._getJspScriptletType():null; + return getJspElementType(JspElementType.Kind.JSP_SCRIPTLET); } + @Nullable public static IElementType getJspExpressionType() { - JspSpiUtil spiUtil = getJspSpiUtil(); - return spiUtil != null ? spiUtil._getJspExpressionType():null; + return getJspElementType(JspElementType.Kind.JSP_EXPRESSION); } - protected abstract IElementType _getJspExpressionType(); - protected abstract IElementType _getJspScriptletType(); + protected abstract IElementType _getJspElementType(@NotNull final JspElementType.Kind kind); }