New Java parser - diamonds support

This commit is contained in:
Roman Shevchenko
2010-09-01 21:45:09 +04:00
parent 2f3c82c575
commit 593c0519f5
11 changed files with 114 additions and 32 deletions
@@ -205,7 +205,7 @@ public class DeclarationParser {
}
// adding a reference, not simple tokens allows "Browse ..." to work well
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false);
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false, false);
if (ref == null) {
builder.advanceLexer();
}
@@ -518,7 +518,7 @@ public class DeclarationParser {
}
// adding a reference, not simple tokens allows "Browse .." to work well
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false);
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false, false);
if (ref == null && builder.getTokenType() != null) {
builder.advanceLexer();
}
@@ -538,7 +538,7 @@ public class DeclarationParser {
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
final PsiBuilder.Marker type = ellipsis ? ReferenceParser.parseTypeWithEllipsis(builder, true, true) :
ReferenceParser.parseType(builder, true, true);
ReferenceParser.parseType(builder, true, true, false);
if (type == null && modListInfo.second) {
param.rollbackTo();
@@ -676,7 +676,7 @@ public class DeclarationParser {
final PsiBuilder.Marker anno = builder.mark();
builder.advanceLexer();
final PsiBuilder.Marker classRef = ReferenceParser.parseJavaCodeReference(builder, true, false, false);
final PsiBuilder.Marker classRef = ReferenceParser.parseJavaCodeReference(builder, true, false, false, false);
if (classRef == null) {
error(builder, JavaErrorMessages.message("expected.class.reference"));
}
@@ -356,7 +356,7 @@ public class ExpressionParser {
final PsiBuilder.Marker copy = startMarker.precede();
startMarker.rollbackTo();
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, false, true, false);
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, false, true, false, false);
if (ref == null || builder.getTokenType() != JavaTokenType.DOT) {
copy.rollbackTo();
return parsePrimary(builder, BreakPoint.P2);
@@ -383,7 +383,7 @@ public class ExpressionParser {
else {
dotPos.drop();
final PsiBuilder.Marker refExpr = expr.precede();
ReferenceParser.parseReferenceParameterList(builder, false);
ReferenceParser.parseReferenceParameterList(builder, false, false);
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"))) {
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
@@ -637,14 +637,15 @@ public class ExpressionParser {
final PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
builder.advanceLexer();
ReferenceParser.parseReferenceParameterList(builder, false);
final boolean parseDiamonds = areDiamondsSupported(builder);
ReferenceParser.parseReferenceParameterList(builder, false, parseDiamonds);
final PsiBuilder.Marker refOrType;
final boolean parseAnnotations = areTypeAnnotationsSupported(builder) && builder.getTokenType() == JavaTokenType.AT;
final IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.IDENTIFIER || parseAnnotations) {
refOrType = ReferenceParser.parseJavaCodeReference(builder, true, true, parseAnnotations);
refOrType = ReferenceParser.parseJavaCodeReference(builder, true, true, parseAnnotations, parseDiamonds);
if (refOrType == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
newExpr.done(JavaElementType.NEW_EXPRESSION);
@@ -715,7 +716,7 @@ public class ExpressionParser {
private static PsiBuilder.Marker parseClassObjectAccess(final PsiBuilder builder) {
final PsiBuilder.Marker expr = builder.mark();
final PsiBuilder.Marker type = ReferenceParser.parseType(builder, false, false);
final PsiBuilder.Marker type = ReferenceParser.parseType(builder, false, false, false);
if (type == null) {
expr.drop();
return null;
@@ -116,7 +116,7 @@ public class FileParser {
}
}
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, false, false);
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, false, false, false);
if (ref == null) {
statement.rollbackTo();
return null;
@@ -116,8 +116,11 @@ public class JavaParserUtil {
}
public static boolean areTypeAnnotationsSupported(final PsiBuilder builder) {
final LanguageLevel level = getLanguageLevel(builder);
return level.isAtLeast(LanguageLevel.JDK_1_7);
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_7);
}
public static boolean areDiamondsSupported(final PsiBuilder builder) {
return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_7);
}
@NotNull
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.PsiBuilderUtil.nextTokenType;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
import static com.intellij.lang.java.parser.JavaParserUtil.emptyElement;
public class ReferenceParser {
@@ -45,18 +46,18 @@ public class ReferenceParser {
@Nullable
public static TypeInfo parseType(final PsiBuilder builder) {
return parseTypeWithInfo(builder, true, true);
return parseTypeWithInfo(builder, true, true, false);
}
@Nullable
public static PsiBuilder.Marker parseType(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard);
public static PsiBuilder.Marker parseType(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard, final boolean diamonds) {
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard, diamonds);
return typeInfo != null ? typeInfo.marker : null;
}
@Nullable
public static PsiBuilder.Marker parseTypeWithEllipsis(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard);
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard, false);
if (typeInfo == null) return null;
PsiBuilder.Marker type = typeInfo.marker;
@@ -70,7 +71,7 @@ public class ReferenceParser {
}
@Nullable
private static TypeInfo parseTypeWithInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
private static TypeInfo parseTypeWithInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard, final boolean diamonds) {
if (builder.getTokenType() == null) return null;
final TypeInfo typeInfo = new TypeInfo();
@@ -86,13 +87,19 @@ public class ReferenceParser {
typeInfo.isPrimitive = true;
}
else if (tokenType == JavaTokenType.IDENTIFIER) {
parseJavaCodeReference(builder, eatLastDot, true, annotationsSupported, false, false, typeInfo);
parseJavaCodeReference(builder, eatLastDot, true, annotationsSupported, false, false, diamonds, typeInfo);
}
else if (wildcard && tokenType == JavaTokenType.QUEST) {
type.drop();
typeInfo.marker = parseWildcardType(builder);
return typeInfo.marker != null ? typeInfo : null;
}
else if (diamonds && tokenType == JavaTokenType.GT) {
emptyElement(builder, JavaElementType.DIAMOND_TYPE);
type.done(JavaElementType.TYPE);
typeInfo.marker = type;
return typeInfo;
}
else {
type.drop();
return null;
@@ -129,7 +136,7 @@ public class ReferenceParser {
builder.advanceLexer();
if (expect(builder, WILDCARD_KEYWORD_SET)) {
final PsiBuilder.Marker boundType = parseType(builder, true, false);
final PsiBuilder.Marker boundType = parseType(builder, true, false, false);
if (boundType == null) {
error(builder, JavaErrorMessages.message("expected.type"));
}
@@ -141,13 +148,13 @@ public class ReferenceParser {
@Nullable
public static PsiBuilder.Marker parseJavaCodeReference(final PsiBuilder builder, final boolean eatLastDot,
final boolean parameterList, final boolean annotations) {
return parseJavaCodeReference(builder, eatLastDot, parameterList, annotations, false, false, new TypeInfo());
final boolean parameterList, final boolean annotations, final boolean diamonds) {
return parseJavaCodeReference(builder, eatLastDot, parameterList, annotations, false, false, diamonds, new TypeInfo());
}
public static boolean parseImportCodeReference(final PsiBuilder builder, final boolean isStatic) {
final TypeInfo typeInfo = new TypeInfo();
parseJavaCodeReference(builder, true, false, false, true, isStatic, typeInfo);
parseJavaCodeReference(builder, true, false, false, true, isStatic, false, typeInfo);
return !typeInfo.hasErrors;
}
@@ -155,7 +162,7 @@ public class ReferenceParser {
private static PsiBuilder.Marker parseJavaCodeReference(final PsiBuilder builder, final boolean eatLastDot,
final boolean parameterList, final boolean annotations,
final boolean isImport, final boolean isStaticImport,
final TypeInfo typeInfo) {
final boolean diamonds, final TypeInfo typeInfo) {
PsiBuilder.Marker refElement = builder.mark();
if (annotations) {
@@ -173,7 +180,7 @@ public class ReferenceParser {
if (parameterList) {
typeInfo.isParameterized = (builder.getTokenType() == JavaTokenType.LT);
parseReferenceParameterList(builder, true);
parseReferenceParameterList(builder, true, diamonds);
}
else {
if (!isStaticImport || builder.getTokenType() == JavaTokenType.DOT) {
@@ -223,7 +230,7 @@ public class ReferenceParser {
if (parameterList) {
typeInfo.isParameterized = (builder.getTokenType() == JavaTokenType.LT);
parseReferenceParameterList(builder, true);
parseReferenceParameterList(builder, true, diamonds);
}
else if (!isStaticImport || builder.getTokenType() == JavaTokenType.DOT) {
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -235,7 +242,7 @@ public class ReferenceParser {
}
@NotNull
public static PsiBuilder.Marker parseReferenceParameterList(final PsiBuilder builder, final boolean wildcard) {
public static PsiBuilder.Marker parseReferenceParameterList(final PsiBuilder builder, final boolean wildcard, final boolean diamonds) {
final PsiBuilder.Marker list = builder.mark();
if (!expect(builder, JavaTokenType.LT)) {
list.done(JavaElementType.REFERENCE_PARAMETER_LIST);
@@ -243,7 +250,7 @@ public class ReferenceParser {
}
while (true) {
final PsiBuilder.Marker type = parseType(builder, true, wildcard);
final PsiBuilder.Marker type = parseType(builder, true, wildcard, diamonds);
if (type == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
@@ -323,7 +330,7 @@ public class ReferenceParser {
if (expect(builder, start)) {
while (true) {
final PsiBuilder.Marker classReference = parseJavaCodeReference(builder, true, true, true);
final PsiBuilder.Marker classReference = parseJavaCodeReference(builder, true, true, true, false);
if (classReference == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
}
@@ -227,7 +227,7 @@ public class StatementParser {
final PsiBuilder.Marker declStatement = builder.mark();
final PsiBuilder.Marker decl = DeclarationParser.parse(builder, DeclarationParser.Context.CODE_BLOCK);
if (decl == null) {
ReferenceParser.parseType(builder, false, false);
ReferenceParser.parseType(builder, false, false, false);
error(builder, JavaErrorMessages.message("expected.identifier"));
}
done(declStatement, JavaElementType.DECLARATION_STATEMENT);