mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
New Java parser (work in progress)
This commit is contained in:
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.ILazyParseableElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.lang.PsiBuilderUtil.expect;
|
||||
import static com.intellij.lang.java.parser.JavaParserUtil.*;
|
||||
|
||||
|
||||
public class DeclarationParser {
|
||||
public enum Context {
|
||||
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE
|
||||
}
|
||||
|
||||
private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD);
|
||||
|
||||
private DeclarationParser() { }
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseClassBodyWithBraces(final PsiBuilder builder, final boolean isAnnotation, final boolean isEnum) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACE) return null;
|
||||
|
||||
final PsiBuilder.Marker marker = builder.mark();
|
||||
marker.drop();
|
||||
builder.advanceLexer();
|
||||
|
||||
if (isEnum) {
|
||||
parseEnumConstants(builder);
|
||||
}
|
||||
parseClassBodyDeclarations(builder, isAnnotation);
|
||||
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseClassFromKeyword(final PsiBuilder builder, final PsiBuilder.Marker start,
|
||||
final boolean isAnnotation) {
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString() + start + isAnnotation);
|
||||
}
|
||||
|
||||
private static void parseEnumConstants(final PsiBuilder builder) {
|
||||
while (builder.getTokenType() != null) {
|
||||
if (expect(builder, JavaTokenType.SEMICOLON)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.PRIVATE_KEYWORD || builder.getTokenType() == JavaTokenType.PROTECTED_KEYWORD) {
|
||||
error(builder, JavaErrorMessages.message("expected.semicolon"));
|
||||
return;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker enumConstant = parseEnumConstant(builder);
|
||||
if (enumConstant == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.COMMA)) {
|
||||
if (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.SEMICOLON) {
|
||||
error(builder, JavaErrorMessages.message("expected.comma.or.semicolon"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseEnumConstant(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker constant = builder.mark();
|
||||
|
||||
parseModifierList(builder);
|
||||
|
||||
if (expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
if (builder.getTokenType() == JavaTokenType.LPARENTH) {
|
||||
ExpressionParser.parseArgumentList(builder);
|
||||
}
|
||||
else {
|
||||
emptyElement(builder, JavaElementType.EXPRESSION_LIST);
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.LBRACE) {
|
||||
final PsiBuilder.Marker constantInit = builder.mark();
|
||||
parseClassBodyWithBraces(builder, false, false);
|
||||
constantInit.done(JavaElementType.ENUM_CONSTANT_INITIALIZER);
|
||||
}
|
||||
|
||||
constant.done(JavaElementType.ENUM_CONSTANT);
|
||||
return constant;
|
||||
}
|
||||
else {
|
||||
constant.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseClassBodyDeclarations(final PsiBuilder builder, final boolean isAnnotation) {
|
||||
final Context context = isAnnotation ? Context.ANNOTATION_INTERFACE : Context.CLASS;
|
||||
|
||||
PsiBuilder.Marker invalidElements = null;
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null || tokenType == JavaTokenType.RBRACE) break;
|
||||
|
||||
if (tokenType == JavaTokenType.SEMICOLON) {
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(JavaErrorMessages.message("unexpected.token"));
|
||||
invalidElements = null;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
continue;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker declaration = parseDeclaration(builder, context);
|
||||
if (declaration != null) {
|
||||
if (invalidElements != null) {
|
||||
invalidElements.errorBefore(JavaErrorMessages.message("unexpected.token"), declaration);
|
||||
invalidElements = null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invalidElements == null) {
|
||||
invalidElements = builder.mark();
|
||||
}
|
||||
|
||||
// adding a reference, not simple tokens allows "Browse ..." to work well
|
||||
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false);
|
||||
if (ref == null) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(JavaErrorMessages.message("unexpected.token"));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseDeclaration(final PsiBuilder builder, final Context context) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null) return null;
|
||||
|
||||
if (tokenType == JavaTokenType.LBRACE) {
|
||||
if (context == Context.FILE || context == Context.CODE_BLOCK) return null;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.IDENTIFIER || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
|
||||
if (context == Context.FILE) return null;
|
||||
}
|
||||
else if (tokenType instanceof ILazyParseableElementType) {
|
||||
final PsiBuilder.Marker declaration = builder.mark();
|
||||
declaration.drop();
|
||||
builder.advanceLexer();
|
||||
return declaration;
|
||||
}
|
||||
else if (!ElementType.MODIFIER_BIT_SET.contains(tokenType) &&
|
||||
!ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType) &&
|
||||
tokenType != JavaTokenType.AT &&
|
||||
(context == Context.CODE_BLOCK || tokenType != JavaTokenType.LT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker declaration = builder.mark();
|
||||
|
||||
final PsiBuilder.Marker modList = parseModifierList(builder);
|
||||
|
||||
if (expect(builder, JavaTokenType.AT)) {
|
||||
if (tokenType == JavaTokenType.INTERFACE_KEYWORD) {
|
||||
return parseClassFromKeyword(builder, declaration, true);
|
||||
}
|
||||
else {
|
||||
declaration.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType)) {
|
||||
final PsiBuilder.Marker root = parseClassFromKeyword(builder, declaration, false);
|
||||
|
||||
if (context == Context.FILE) {
|
||||
// todo: append following declarations to root
|
||||
boolean declarationsAfterEnd = false;
|
||||
|
||||
while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) {
|
||||
final PsiBuilder.Marker position = builder.mark();
|
||||
final PsiBuilder.Marker element = parseDeclaration(builder, Context.CLASS);
|
||||
if (element != null && AFTER_END_DECLARATION_SET.contains(((LighterASTNode)element).getTokenType())) {
|
||||
if (!declarationsAfterEnd) {
|
||||
element.precede().error(JavaErrorMessages.message("expected.class.or.interface"));
|
||||
}
|
||||
declarationsAfterEnd = true;
|
||||
position.drop();
|
||||
}
|
||||
else {
|
||||
position.rollbackTo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (declarationsAfterEnd) {
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
PsiBuilder.Marker typeParams = null;
|
||||
if (builder.getTokenType() == JavaTokenType.LT) {
|
||||
typeParams = ReferenceParser.parseTypeParameters(builder);
|
||||
}
|
||||
|
||||
if (context == Context.FILE) {
|
||||
if (typeParams == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.class.or.interface"));
|
||||
}
|
||||
else {
|
||||
typeParams.precede().errorBefore(JavaErrorMessages.message("expected.class.or.interface"), typeParams);
|
||||
}
|
||||
declaration.drop();
|
||||
return modList;
|
||||
}
|
||||
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString() + context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseModifierList(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker modList = builder.mark();
|
||||
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null) break;
|
||||
if (ElementType.MODIFIER_BIT_SET.contains(tokenType)) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else if (tokenType == JavaTokenType.AT) {
|
||||
final PsiBuilder.Marker pos = builder.mark();
|
||||
builder.advanceLexer();
|
||||
final IElementType nextTokenType = builder.getTokenType();
|
||||
pos.rollbackTo();
|
||||
if (ElementType.KEYWORD_BIT_SET.contains(nextTokenType)) {
|
||||
break;
|
||||
}
|
||||
parseAnnotation(builder);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modList.done(JavaElementType.MODIFIER_LIST);
|
||||
return modList;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseAnnotations(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker firstAnno = null;
|
||||
|
||||
while (builder.getTokenType() == JavaTokenType.AT) {
|
||||
final PsiBuilder.Marker anno = parseAnnotation(builder);
|
||||
if (firstAnno == null) firstAnno = anno;
|
||||
}
|
||||
|
||||
return firstAnno;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseAnnotation(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker anno = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker classRef = ReferenceParser.parseJavaCodeReference(builder, true, false, false);
|
||||
if (classRef == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.class.reference"));
|
||||
}
|
||||
|
||||
parseAnnotationParameterList(builder);
|
||||
|
||||
anno.done(JavaElementType.ANNOTATION);
|
||||
return anno;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseAnnotationParameterList(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker list = builder.mark();
|
||||
|
||||
if (!expect(builder, JavaTokenType.LPARENTH)) {
|
||||
list.done(JavaElementType.ANNOTATION_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.RPARENTH)) {
|
||||
list.done(JavaElementType.ANNOTATION_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
final boolean isFirstParamNamed = parseAnnotationParameter(builder, true);
|
||||
boolean isFirstParamWarned = false;
|
||||
|
||||
boolean afterBad = false;
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.parameter"));
|
||||
break;
|
||||
}
|
||||
else if (expect(builder, JavaTokenType.RPARENTH)) {
|
||||
break;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.COMMA) {
|
||||
final PsiBuilder.Marker errorStart = builder.mark();
|
||||
final PsiBuilder.Marker errorEnd = builder.mark();
|
||||
builder.advanceLexer();
|
||||
final boolean hasParamName = parseAnnotationParameter(builder, false);
|
||||
if (!isFirstParamNamed && hasParamName && !isFirstParamWarned) {
|
||||
errorStart.errorBefore(JavaErrorMessages.message("annotation.name.is.missing"), errorEnd);
|
||||
isFirstParamWarned = true;
|
||||
}
|
||||
else {
|
||||
errorStart.drop();
|
||||
}
|
||||
errorEnd.drop();
|
||||
}
|
||||
else if (!afterBad) {
|
||||
error(builder, JavaErrorMessages.message("expected.comma.or.rparen"));
|
||||
builder.advanceLexer();
|
||||
afterBad = true;
|
||||
}
|
||||
else {
|
||||
afterBad = false;
|
||||
parseAnnotationParameter(builder, false);
|
||||
}
|
||||
}
|
||||
|
||||
list.done(JavaElementType.ANNOTATION_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean parseAnnotationParameter(final PsiBuilder builder, final boolean mayBeSimple) {
|
||||
PsiBuilder.Marker pair = builder.mark();
|
||||
|
||||
if (mayBeSimple) {
|
||||
final PsiBuilder.Marker value = parseAnnotationValue(builder);
|
||||
if (value != null && builder.getTokenType() != JavaTokenType.EQ) {
|
||||
pair.done(JavaElementType.NAME_VALUE_PAIR);
|
||||
return false;
|
||||
}
|
||||
|
||||
pair.rollbackTo();
|
||||
pair = builder.mark();
|
||||
}
|
||||
|
||||
final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"));
|
||||
|
||||
expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"));
|
||||
|
||||
parseAnnotationValue(builder);
|
||||
|
||||
pair.done(JavaElementType.NAME_VALUE_PAIR);
|
||||
|
||||
return hasName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseAnnotationValue(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker result;
|
||||
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.AT) {
|
||||
result = parseAnnotation(builder);
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LBRACE) {
|
||||
result = parseAnnotationArrayInitializer(builder);
|
||||
}
|
||||
else {
|
||||
result = ExpressionParser.parseConditional(builder);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.value"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseAnnotationArrayInitializer(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker annoArray = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
if (expect(builder, JavaTokenType.RBRACE)) {
|
||||
annoArray.done(JavaElementType.ANNOTATION_ARRAY_INITIALIZER);
|
||||
return annoArray;
|
||||
}
|
||||
|
||||
parseAnnotationValue(builder);
|
||||
|
||||
while (true) {
|
||||
if (expect(builder, JavaTokenType.RBRACE)) {
|
||||
break;
|
||||
}
|
||||
else if (expect(builder, JavaTokenType.COMMA)) {
|
||||
parseAnnotationValue(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.rbrace"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
annoArray.done(JavaElementType.ANNOTATION_ARRAY_INITIALIZER);
|
||||
return annoArray;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,852 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiBuilderUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.lang.java.parser.JavaParserUtil.areTypeAnnotationsSupported;
|
||||
import static com.intellij.lang.java.parser.JavaParserUtil.error;
|
||||
|
||||
|
||||
public class ExpressionParser {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.java.parser.ExpressionParser");
|
||||
|
||||
private enum ExprType {
|
||||
CONDITIONAL_OR, CONDITIONAL_AND, OR, XOR, AND, EQUALITY, RELATIONAL, SHIFT, ADDITIVE, MULTIPLICATIVE, UNARY, TYPE
|
||||
}
|
||||
|
||||
private static final TokenSet ASSIGNMENT_OPS = TokenSet.create(
|
||||
JavaTokenType.EQ, JavaTokenType.ASTERISKEQ, JavaTokenType.DIVEQ, JavaTokenType.PERCEQ, JavaTokenType.PLUSEQ, JavaTokenType.MINUSEQ,
|
||||
JavaTokenType.LTLTEQ, JavaTokenType.GTGTEQ, JavaTokenType.GTGTGTEQ, JavaTokenType.ANDEQ, JavaTokenType.OREQ, JavaTokenType.XOREQ);
|
||||
private static final TokenSet RELATIONAL_OPS = TokenSet.create(JavaTokenType.LT, JavaTokenType.GT, JavaTokenType.LE, JavaTokenType.GE);
|
||||
private static final TokenSet POSTFIX_OPS = TokenSet.create(JavaTokenType.PLUSPLUS, JavaTokenType.MINUSMINUS);
|
||||
private static final TokenSet PREF_ARITHMETIC_OPS = TokenSet.orSet(POSTFIX_OPS, TokenSet.create(JavaTokenType.PLUS, JavaTokenType.MINUS));
|
||||
private static final TokenSet PREFIX_OPS = TokenSet.orSet(PREF_ARITHMETIC_OPS, TokenSet.create(JavaTokenType.TILDE, JavaTokenType.EXCL));
|
||||
private static final TokenSet LITERALS = TokenSet.create(
|
||||
JavaTokenType.TRUE_KEYWORD, JavaTokenType.FALSE_KEYWORD, JavaTokenType.NULL_KEYWORD, JavaTokenType.INTEGER_LITERAL,
|
||||
JavaTokenType.LONG_LITERAL, JavaTokenType.FLOAT_LITERAL, JavaTokenType.DOUBLE_LITERAL, JavaTokenType.CHARACTER_LITERAL,
|
||||
JavaTokenType.STRING_LITERAL);
|
||||
private static final TokenSet CONDITIONAL_OR_OPS = TokenSet.create(JavaTokenType.OROR);
|
||||
private static final TokenSet CONDITIONAL_AND_OPS = TokenSet.create(JavaTokenType.ANDAND);
|
||||
private static final TokenSet OR_OPS = TokenSet.create(JavaTokenType.OR);
|
||||
private static final TokenSet XOR_OPS = TokenSet.create(JavaTokenType.XOR);
|
||||
private static final TokenSet AND_OPS = TokenSet.create(JavaTokenType.AND);
|
||||
private static final TokenSet EQUALITY_OPS = TokenSet.create(JavaTokenType.EQEQ, JavaTokenType.NE);
|
||||
private static final TokenSet SHIFT_OPS = TokenSet.create(JavaTokenType.LTLT, JavaTokenType.GTGT, JavaTokenType.GTGTGT);
|
||||
private static final TokenSet ADDITIVE_OPS = TokenSet.create(JavaTokenType.PLUS, JavaTokenType.MINUS);
|
||||
private static final TokenSet MULTIPLICATIVE_OPS = TokenSet.create(JavaTokenType.ASTERISK, JavaTokenType.DIV, JavaTokenType.PERC);
|
||||
private static final TokenSet ARGS_LIST_END = TokenSet.create(JavaTokenType.RPARENTH, JavaTokenType.RBRACE, JavaTokenType.RBRACKET);
|
||||
private static final TokenSet ARGS_LIST_CONTINUE = TokenSet.create(
|
||||
JavaTokenType.IDENTIFIER, TokenType.BAD_CHARACTER, JavaTokenType.COMMA, JavaTokenType.INTEGER_LITERAL, JavaTokenType.STRING_LITERAL);
|
||||
|
||||
private ExpressionParser() { }
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parse(final PsiBuilder builder) {
|
||||
return parseAssignment(builder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseAssignment(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker left = parseConditional(builder);
|
||||
if (left == null) return null;
|
||||
|
||||
final IElementType tokenType = getGtTokenType(builder);
|
||||
if (ASSIGNMENT_OPS.contains(tokenType)) {
|
||||
final PsiBuilder.Marker assignment = left.precede();
|
||||
advanceGtToken(builder, tokenType);
|
||||
|
||||
final PsiBuilder.Marker right = parse(builder);
|
||||
if (right == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
|
||||
assignment.done(JavaElementType.ASSIGNMENT_EXPRESSION);
|
||||
return assignment;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseConditional(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker condition = parseExpression(builder, ExprType.CONDITIONAL_OR);
|
||||
if (condition == null) return null;
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.QUEST) return condition;
|
||||
final PsiBuilder.Marker ternary = condition.precede();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker truePart = parse(builder);
|
||||
if (truePart == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
|
||||
return ternary;
|
||||
}
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.COLON) {
|
||||
error(builder, JavaErrorMessages.message("expected.colon"));
|
||||
ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
|
||||
return ternary;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker falsePart = parseConditional(builder);
|
||||
if (falsePart == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
|
||||
return ternary;
|
||||
}
|
||||
|
||||
ternary.done(JavaElementType.CONDITIONAL_EXPRESSION);
|
||||
return ternary;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseExpression(final PsiBuilder builder, final ExprType type) {
|
||||
switch (type) {
|
||||
case CONDITIONAL_OR:
|
||||
return parseBinary(builder, ExprType.CONDITIONAL_AND, CONDITIONAL_OR_OPS);
|
||||
|
||||
case CONDITIONAL_AND:
|
||||
return parseBinary(builder, ExprType.OR, CONDITIONAL_AND_OPS);
|
||||
|
||||
case OR:
|
||||
return parseBinary(builder, ExprType.XOR, OR_OPS);
|
||||
|
||||
case XOR:
|
||||
return parseBinary(builder, ExprType.AND, XOR_OPS);
|
||||
|
||||
case AND:
|
||||
return parseBinary(builder, ExprType.EQUALITY, AND_OPS);
|
||||
|
||||
case EQUALITY:
|
||||
return parseBinary(builder, ExprType.RELATIONAL, EQUALITY_OPS);
|
||||
|
||||
case RELATIONAL:
|
||||
return parseRelational(builder);
|
||||
|
||||
case SHIFT:
|
||||
return parseBinary(builder, ExprType.ADDITIVE, SHIFT_OPS);
|
||||
|
||||
case ADDITIVE:
|
||||
return parseBinary(builder, ExprType.MULTIPLICATIVE, ADDITIVE_OPS);
|
||||
|
||||
case MULTIPLICATIVE:
|
||||
return parseBinary(builder, ExprType.UNARY, MULTIPLICATIVE_OPS);
|
||||
|
||||
case UNARY:
|
||||
return parseUnary(builder);
|
||||
|
||||
case TYPE:
|
||||
final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseType(builder);
|
||||
return typeInfo != null ? typeInfo.marker : null;
|
||||
|
||||
default:
|
||||
LOG.error("Unexpected type: " + type);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseBinary(final PsiBuilder builder, final ExprType type, final TokenSet ops) {
|
||||
PsiBuilder.Marker left = parseExpression(builder, type);
|
||||
if (left == null) return null;
|
||||
|
||||
while (true) {
|
||||
final IElementType tokenType = getGtTokenType(builder);
|
||||
if (tokenType == null || !ops.contains(tokenType)) break;
|
||||
|
||||
final PsiBuilder.Marker binary = left.precede();
|
||||
advanceGtToken(builder, tokenType);
|
||||
|
||||
final PsiBuilder.Marker right = parseExpression(builder, type);
|
||||
if (right == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
binary.done(JavaElementType.BINARY_EXPRESSION);
|
||||
return binary;
|
||||
}
|
||||
|
||||
binary.done(JavaElementType.BINARY_EXPRESSION);
|
||||
left = binary;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseRelational(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker left = parseExpression(builder, ExprType.SHIFT);
|
||||
if (left == null) return null;
|
||||
|
||||
while (true) {
|
||||
final IElementType toCreate;
|
||||
final ExprType toParse;
|
||||
final IElementType tokenType = getGtTokenType(builder);
|
||||
if (RELATIONAL_OPS.contains(tokenType)) {
|
||||
toCreate = JavaElementType.BINARY_EXPRESSION;
|
||||
toParse = ExprType.SHIFT;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.INSTANCEOF_KEYWORD) {
|
||||
toCreate = JavaElementType.INSTANCE_OF_EXPRESSION;
|
||||
toParse = ExprType.TYPE;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker expression = left.precede();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker right = parseExpression(builder, toParse);
|
||||
if (right == null) {
|
||||
error(builder, toParse == ExprType.TYPE ?
|
||||
JavaErrorMessages.message("expected.type") : JavaErrorMessages.message("expected.expression"));
|
||||
expression.done(toCreate);
|
||||
return expression;
|
||||
}
|
||||
|
||||
expression.done(toCreate);
|
||||
left = expression;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseUnary(final PsiBuilder builder) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
|
||||
if (PREFIX_OPS.contains(tokenType)) {
|
||||
final PsiBuilder.Marker unary = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker operand = parseUnary(builder);
|
||||
if (operand == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
|
||||
unary.done(JavaElementType.PREFIX_EXPRESSION);
|
||||
return unary;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LPARENTH) {
|
||||
final PsiBuilder.Marker typeCast = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseType(builder);
|
||||
|
||||
if (typeInfo == null || builder.getTokenType() != JavaTokenType.RPARENTH) {
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType())) {
|
||||
if (!typeInfo.isPrimitive) {
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker expr = parseUnary(builder);
|
||||
if (expr == null) {
|
||||
if (!typeInfo.isParameterized) {
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
}
|
||||
|
||||
typeCast.done(JavaElementType.TYPE_CAST_EXPRESSION);
|
||||
return typeCast;
|
||||
}
|
||||
else {
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker operand = parsePrimary(builder, false);
|
||||
if (operand == null) return null;
|
||||
|
||||
while (POSTFIX_OPS.contains(builder.getTokenType())) {
|
||||
final PsiBuilder.Marker postfix = operand.precede();
|
||||
builder.advanceLexer();
|
||||
postfix.done(JavaElementType.POSTFIX_EXPRESSION);
|
||||
operand = postfix;
|
||||
}
|
||||
|
||||
return operand;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parsePrimary(final PsiBuilder builder, final boolean planB) {
|
||||
PsiBuilder.Marker startMarker = builder.mark();
|
||||
|
||||
final Pair<PsiBuilder.Marker, IElementType> exprTypePair = parsePrimaryExpressionStart(builder);
|
||||
if (exprTypePair == null) {
|
||||
startMarker.drop();
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiBuilder.Marker expr = exprTypePair.first;
|
||||
IElementType exprType = exprTypePair.second;
|
||||
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.DOT) {
|
||||
final PsiBuilder.Marker dotPos = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final IElementType dotTokenType = builder.getTokenType();
|
||||
if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (planB) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
PsiBuilderUtil.drop(startMarker, dotPos);
|
||||
return expr;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
|
||||
if (classObjAccess == null) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
expr = classObjAccess;
|
||||
exprType = JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION;
|
||||
}
|
||||
else if (dotTokenType == JavaTokenType.NEW_KEYWORD) {
|
||||
dotPos.drop();
|
||||
expr = parseNew(builder, expr);
|
||||
exprType = JavaElementType.NEW_EXPRESSION;
|
||||
}
|
||||
else if ((dotTokenType == JavaTokenType.THIS_KEYWORD || dotTokenType == JavaTokenType.SUPER_KEYWORD) &&
|
||||
exprType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (planB) {
|
||||
dotPos.rollbackTo();
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, false, true, false);
|
||||
if (ref == null || builder.getTokenType() != JavaTokenType.DOT) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() != dotTokenType) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
startMarker = copy;
|
||||
exprType = dotTokenType == JavaTokenType.THIS_KEYWORD ? JavaElementType.THIS_EXPRESSION : JavaElementType.SUPER_EXPRESSION;
|
||||
expr = ref.precede();
|
||||
expr.done(exprType);
|
||||
}
|
||||
else if (dotTokenType == JavaTokenType.SUPER_KEYWORD) {
|
||||
dotPos.drop();
|
||||
final PsiBuilder.Marker refExpr = expr.precede();
|
||||
builder.advanceLexer();
|
||||
refExpr.done(exprType = JavaElementType.REFERENCE_EXPRESSION);
|
||||
expr = refExpr;
|
||||
}
|
||||
else {
|
||||
dotPos.drop();
|
||||
final PsiBuilder.Marker refExpr = expr.precede();
|
||||
ReferenceParser.parseReferenceParameterList(builder, false);
|
||||
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"))) {
|
||||
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
|
||||
startMarker.drop();
|
||||
return refExpr;
|
||||
}
|
||||
|
||||
refExpr.done(exprType = JavaElementType.REFERENCE_EXPRESSION);
|
||||
expr = refExpr;
|
||||
}
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LPARENTH) {
|
||||
if (exprType != JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (exprType == JavaElementType.SUPER_EXPRESSION) {
|
||||
if (planB) {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final Pair<PsiBuilder.Marker, IElementType> qualifier = parsePrimaryExpressionStart(builder);
|
||||
if (qualifier != null) {
|
||||
final PsiBuilder.Marker refExpr = qualifier.first.precede();
|
||||
if (builder.getTokenType() == JavaTokenType.DOT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.SUPER_KEYWORD) {
|
||||
builder.advanceLexer();
|
||||
refExpr.done(exprType = JavaElementType.REFERENCE_EXPRESSION);
|
||||
expr = refExpr;
|
||||
startMarker = copy;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
}
|
||||
else {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker callExpr = expr.precede();
|
||||
parseArgumentList(builder);
|
||||
callExpr.done(exprType = JavaElementType.METHOD_CALL_EXPRESSION);
|
||||
expr = callExpr;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LBRACKET) {
|
||||
if (planB) {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.RBRACKET && exprType == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
|
||||
if (classObjAccess == null) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
expr = classObjAccess;
|
||||
exprType = JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION;
|
||||
}
|
||||
else {
|
||||
final PsiBuilder.Marker arrayAccess = expr.precede();
|
||||
|
||||
final PsiBuilder.Marker index = parse(builder);
|
||||
if (index == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
|
||||
startMarker.drop();
|
||||
return arrayAccess;
|
||||
}
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.RBRACKET) {
|
||||
error(builder, JavaErrorMessages.message("expected.rbracket"));
|
||||
arrayAccess.done(JavaElementType.ARRAY_ACCESS_EXPRESSION);
|
||||
startMarker.drop();
|
||||
return arrayAccess;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
arrayAccess.done(exprType = JavaElementType.ARRAY_ACCESS_EXPRESSION);
|
||||
expr = arrayAccess;
|
||||
}
|
||||
}
|
||||
else {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<PsiBuilder.Marker, IElementType> parsePrimaryExpressionStart(final PsiBuilder builder) {
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
|
||||
if (LITERALS.contains(tokenType)) {
|
||||
final PsiBuilder.Marker literal = builder.mark();
|
||||
builder.advanceLexer();
|
||||
literal.done(JavaElementType.LITERAL_EXPRESSION);
|
||||
return Pair.create(literal, JavaElementType.LITERAL_EXPRESSION);
|
||||
}
|
||||
if (tokenType == JavaTokenType.LPARENTH) {
|
||||
final PsiBuilder.Marker parenth = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker inner = parse(builder);
|
||||
if (inner == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
|
||||
JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen"));
|
||||
|
||||
parenth.done(JavaElementType.PARENTH_EXPRESSION);
|
||||
return Pair.create(parenth, JavaElementType.PARENTH_EXPRESSION);
|
||||
}
|
||||
if (tokenType == JavaTokenType.LBRACE) {
|
||||
final PsiBuilder.Marker arrayInit = parseArrayInitializer(builder);
|
||||
return arrayInit != null ? Pair.create(arrayInit, JavaElementType.ARRAY_INITIALIZER_EXPRESSION) : null;
|
||||
}
|
||||
|
||||
PsiBuilder.Marker annotation = null;
|
||||
final PsiBuilder.Marker beforeAnnotation = builder.mark();
|
||||
if (tokenType == JavaTokenType.AT) {
|
||||
annotation = DeclarationParser.parseAnnotations(builder);
|
||||
tokenType = builder.getTokenType();
|
||||
}
|
||||
|
||||
if (tokenType == JavaTokenType.IDENTIFIER) {
|
||||
final PsiBuilder.Marker refExpr;
|
||||
if (annotation != null) {
|
||||
final PsiBuilder.Marker refParam = annotation.precede();
|
||||
refParam.doneBefore(JavaElementType.REFERENCE_PARAMETER_LIST, annotation);
|
||||
refExpr = refParam.precede();
|
||||
}
|
||||
else {
|
||||
refExpr = builder.mark();
|
||||
builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
}
|
||||
|
||||
builder.advanceLexer();
|
||||
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
|
||||
beforeAnnotation.drop();
|
||||
return Pair.create(refExpr, JavaElementType.REFERENCE_EXPRESSION);
|
||||
}
|
||||
|
||||
if (annotation != null) {
|
||||
beforeAnnotation.rollbackTo();
|
||||
tokenType = builder.getTokenType();
|
||||
}
|
||||
else {
|
||||
beforeAnnotation.drop();
|
||||
}
|
||||
|
||||
if (tokenType == JavaTokenType.THIS_KEYWORD) {
|
||||
final PsiBuilder.Marker expr = builder.mark();
|
||||
builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
builder.advanceLexer();
|
||||
final IElementType type = builder.getTokenType() != JavaTokenType.LPARENTH ?
|
||||
JavaElementType.THIS_EXPRESSION : JavaElementType.REFERENCE_EXPRESSION;
|
||||
expr.done(type);
|
||||
return Pair.create(expr, type);
|
||||
}
|
||||
if (tokenType == JavaTokenType.SUPER_KEYWORD) {
|
||||
final PsiBuilder.Marker expr = builder.mark();
|
||||
builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
builder.advanceLexer();
|
||||
final IElementType type = builder.getTokenType() != JavaTokenType.LPARENTH ?
|
||||
JavaElementType.SUPER_EXPRESSION : JavaElementType.REFERENCE_EXPRESSION;
|
||||
expr.done(type);
|
||||
return Pair.create(expr, type);
|
||||
}
|
||||
if (tokenType == JavaTokenType.NEW_KEYWORD) {
|
||||
final PsiBuilder.Marker newExpr = parseNew(builder, null);
|
||||
return Pair.create(newExpr, JavaElementType.NEW_EXPRESSION);
|
||||
}
|
||||
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
|
||||
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
|
||||
return classObjAccess != null ? Pair.create(classObjAccess, JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION) : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseArrayInitializer(final PsiBuilder builder) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACE) return null;
|
||||
|
||||
final PsiBuilder.Marker arrayInit = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
boolean expressionMissed = false;
|
||||
PsiBuilder.Marker lastComma = null;
|
||||
while (true) {
|
||||
if (builder.getTokenType() == JavaTokenType.RBRACE) {
|
||||
builder.advanceLexer();
|
||||
break;
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.rbrace"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (expressionMissed && lastComma != null) {
|
||||
// before comma must be an expression
|
||||
lastComma.precede().errorBefore(JavaErrorMessages.message("expected.expression"), lastComma);
|
||||
lastComma.drop();
|
||||
lastComma = null;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker arg = parse(builder);
|
||||
if (arg == null) {
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
expressionMissed = true;
|
||||
lastComma = builder.mark();
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.rbrace"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.COMMA) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else if (tokenType != JavaTokenType.RBRACE) {
|
||||
error(builder, JavaErrorMessages.message("expected.comma"));
|
||||
}
|
||||
}
|
||||
|
||||
if (lastComma != null) {
|
||||
lastComma.drop();
|
||||
}
|
||||
|
||||
arrayInit.done(JavaElementType.ARRAY_INITIALIZER_EXPRESSION);
|
||||
return arrayInit;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseNew(final PsiBuilder builder, final PsiBuilder.Marker start) {
|
||||
final PsiBuilder.Marker newExpr = (start != null ? start.precede() : builder.mark());
|
||||
builder.advanceLexer();
|
||||
|
||||
ReferenceParser.parseReferenceParameterList(builder, false);
|
||||
|
||||
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);
|
||||
if (refOrType == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
}
|
||||
else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
|
||||
refOrType = null;
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
|
||||
if (refOrType != null && builder.getTokenType() == JavaTokenType.LPARENTH) {
|
||||
parseArgumentList(builder);
|
||||
if (builder.getTokenType() == JavaTokenType.LBRACE) {
|
||||
final PsiBuilder.Marker classElement = refOrType.precede();
|
||||
DeclarationParser.parseClassBodyWithBraces(builder, false, false);
|
||||
classElement.done(JavaElementType.ANONYMOUS_CLASS);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACKET) {
|
||||
error(builder, refOrType == null ?
|
||||
JavaErrorMessages.message("expected.lbracket") : JavaErrorMessages.message("expected.lparen.or.lbracket"));
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
|
||||
int bracketCount = 0;
|
||||
int dimCount = 0;
|
||||
while (true) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACKET) break;
|
||||
builder.advanceLexer();
|
||||
|
||||
if (bracketCount == dimCount) {
|
||||
final PsiBuilder.Marker dimExpr = parse(builder);
|
||||
if (dimExpr != null) {
|
||||
dimCount++;
|
||||
}
|
||||
}
|
||||
bracketCount++;
|
||||
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) {
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
}
|
||||
|
||||
if (dimCount == 0) {
|
||||
if (builder.getTokenType() == JavaTokenType.LBRACE) {
|
||||
parseArrayInitializer(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.array.initializer"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseClassObjectAccess(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker expr = builder.mark();
|
||||
|
||||
final PsiBuilder.Marker type = ReferenceParser.parseType(builder, false, false);
|
||||
if (type == null) {
|
||||
expr.drop();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.DOT) {
|
||||
expr.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() != JavaTokenType.CLASS_KEYWORD) {
|
||||
expr.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
expr.done(JavaElementType.CLASS_OBJECT_ACCESS_EXPRESSION);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiBuilder.Marker parseArgumentList(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker list = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
boolean first = true;
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (first && (ARGS_LIST_END.contains(tokenType) || builder.eof())) break;
|
||||
if (!first && !ARGS_LIST_CONTINUE.contains(tokenType)) break;
|
||||
|
||||
boolean hasError = false;
|
||||
if (!first) {
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else {
|
||||
hasError = true;
|
||||
error(builder, JavaErrorMessages.message("expected.comma.or.rparen"));
|
||||
emptyExpression(builder);
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
|
||||
final PsiBuilder.Marker arg = parse(builder);
|
||||
if (arg == null) {
|
||||
if (!hasError) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
emptyExpression(builder);
|
||||
}
|
||||
if (!ARGS_LIST_CONTINUE.contains(builder.getTokenType())) break;
|
||||
if (builder.getTokenType() != JavaTokenType.COMMA && !builder.eof()) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen"));
|
||||
|
||||
list.done(JavaElementType.EXPRESSION_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static void emptyExpression(final PsiBuilder builder) {
|
||||
builder.mark().done(JavaElementType.EMPTY_EXPRESSION);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static IElementType getGtTokenType(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker sp = builder.mark();
|
||||
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTGTEQ;
|
||||
}
|
||||
else {
|
||||
tokenType = JavaTokenType.GTGTGT;
|
||||
}
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTEQ;
|
||||
}
|
||||
else {
|
||||
tokenType = JavaTokenType.GTGT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sp.rollbackTo();
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
private static void advanceGtToken(final PsiBuilder builder, final IElementType type) {
|
||||
final PsiBuilder.Marker gtToken = builder.mark();
|
||||
|
||||
if (type == JavaTokenType.GTGTGTEQ) {
|
||||
PsiBuilderUtil.advance(builder, 4);
|
||||
}
|
||||
else if (type == JavaTokenType.GTGTGT) {
|
||||
PsiBuilderUtil.advance(builder, 3);
|
||||
}
|
||||
else if (type == JavaTokenType.GTGTEQ) {
|
||||
PsiBuilderUtil.advance(builder, 3);
|
||||
}
|
||||
else if (type == JavaTokenType.GTGT) {
|
||||
PsiBuilderUtil.advance(builder, 2);
|
||||
}
|
||||
else {
|
||||
gtToken.drop();
|
||||
builder.advanceLexer();
|
||||
return;
|
||||
}
|
||||
|
||||
gtToken.collapse(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiParser;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.lang.java.parser.JavaParserUtil.setLanguageLevel;
|
||||
|
||||
|
||||
public class JavaParser implements PsiParser {
|
||||
private final LanguageLevel myLanguageLevel;
|
||||
|
||||
public JavaParser(final LanguageLevel languageLevel) {
|
||||
myLanguageLevel = languageLevel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ASTNode parse(final IElementType rootType, final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker root = builder.mark();
|
||||
setLanguageLevel(builder, myLanguageLevel);
|
||||
|
||||
// parse
|
||||
|
||||
root.done(rootType);
|
||||
return builder.getTreeBuilt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiBuilderUtil;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class JavaParserUtil {
|
||||
private static final Key<LanguageLevel> LANG_LEVEL_KEY = Key.create("JavaParserUtil.LanguageLevel");
|
||||
|
||||
private JavaParserUtil() { }
|
||||
|
||||
public static void setLanguageLevel(final PsiBuilder builder, final LanguageLevel level) {
|
||||
builder.putUserData(LANG_LEVEL_KEY, level);
|
||||
}
|
||||
|
||||
public static boolean areTypeAnnotationsSupported(final PsiBuilder builder) {
|
||||
final LanguageLevel level = getLanguageLevel(builder);
|
||||
return level.isAtLeast(LanguageLevel.JDK_1_7);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static LanguageLevel getLanguageLevel(final PsiBuilder builder) {
|
||||
final LanguageLevel level = builder.getUserData(LANG_LEVEL_KEY);
|
||||
assert level != null;
|
||||
return level;
|
||||
}
|
||||
|
||||
// used instead of PsiBuilder.error() as it drops all but first subsequent error messages
|
||||
public static void error(final PsiBuilder builder, final String message) {
|
||||
builder.mark().error(message);
|
||||
}
|
||||
|
||||
public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, final String errorMessage) {
|
||||
if (!PsiBuilderUtil.expect(builder, expectedType)) {
|
||||
error(builder, errorMessage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void emptyElement(final PsiBuilder builder, final IElementType type) {
|
||||
builder.mark().done(type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.*;
|
||||
|
||||
|
||||
public class ReferenceParser {
|
||||
public static class TypeInfo {
|
||||
public boolean isPrimitive = false;
|
||||
public boolean isParameterized = false;
|
||||
public boolean isArray = false;
|
||||
public PsiBuilder.Marker marker = null;
|
||||
}
|
||||
|
||||
private static final TokenSet WILDCARD_KEYWORD_SET = TokenSet.create(JavaTokenType.EXTENDS_KEYWORD, JavaTokenType.SUPER_KEYWORD);
|
||||
|
||||
private ReferenceParser() { }
|
||||
|
||||
@Nullable
|
||||
public static TypeInfo parseType(final PsiBuilder builder) {
|
||||
return parseTypeWithInfo(builder, true, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseType(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
|
||||
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard);
|
||||
return typeInfo != null ? typeInfo.marker : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TypeInfo parseTypeWithInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
|
||||
if (builder.getTokenType() == null) return null;
|
||||
|
||||
final TypeInfo typeInfo = new TypeInfo();
|
||||
|
||||
final boolean annotationsSupported = areTypeAnnotationsSupported(builder);
|
||||
PsiBuilder.Marker type = builder.mark();
|
||||
if (annotationsSupported) {
|
||||
DeclarationParser.parseAnnotations(builder);
|
||||
}
|
||||
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (expect(builder, ElementType.PRIMITIVE_TYPE_BIT_SET)) {
|
||||
typeInfo.isPrimitive = true;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.IDENTIFIER) {
|
||||
parseJavaCodeReference(builder, eatLastDot, true, annotationsSupported, typeInfo);
|
||||
}
|
||||
else if (wildcard && tokenType == JavaTokenType.QUEST) {
|
||||
type.drop();
|
||||
typeInfo.marker = parseWildcardType(builder);
|
||||
return typeInfo.marker != null ? typeInfo : null;
|
||||
}
|
||||
else {
|
||||
type.drop();
|
||||
return null;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (annotationsSupported) {
|
||||
DeclarationParser.parseAnnotations(builder);
|
||||
}
|
||||
type.done(JavaElementType.TYPE);
|
||||
|
||||
if (!expect(builder, JavaTokenType.LBRACKET)) {
|
||||
break;
|
||||
}
|
||||
typeInfo.isArray = true;
|
||||
if (!expectOrError(builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) {
|
||||
break;
|
||||
}
|
||||
|
||||
type = type.precede();
|
||||
}
|
||||
|
||||
typeInfo.marker = type;
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseWildcardType(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker type = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
if (expect(builder, WILDCARD_KEYWORD_SET)) {
|
||||
final PsiBuilder.Marker boundType = parseType(builder, true, false);
|
||||
if (boundType == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.type"));
|
||||
}
|
||||
}
|
||||
|
||||
type.done(JavaElementType.TYPE);
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseJavaCodeReference(final PsiBuilder builder, final boolean eatLastDot,
|
||||
final boolean parameterList, final boolean annotations) {
|
||||
return parseJavaCodeReference(builder, eatLastDot, parameterList, annotations, new TypeInfo());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseJavaCodeReference(final PsiBuilder builder, final boolean eatLastDot,
|
||||
final boolean parameterList, final boolean annotations,
|
||||
final TypeInfo typeInfo) {
|
||||
PsiBuilder.Marker refElement = builder.mark();
|
||||
|
||||
if (annotations) {
|
||||
DeclarationParser.parseAnnotations(builder);
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
refElement.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parameterList) {
|
||||
typeInfo.isParameterized = (builder.getTokenType() == JavaTokenType.LT);
|
||||
parseReferenceParameterList(builder, true);
|
||||
}
|
||||
else {
|
||||
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
}
|
||||
|
||||
boolean hasIdentifier;
|
||||
while (builder.getTokenType() == JavaTokenType.DOT) {
|
||||
refElement.done(JavaElementType.JAVA_CODE_REFERENCE);
|
||||
|
||||
final PsiBuilder.Marker dotPos = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
if (expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
hasIdentifier = true;
|
||||
}
|
||||
else {
|
||||
if (!eatLastDot) {
|
||||
dotPos.rollbackTo();
|
||||
return refElement;
|
||||
}
|
||||
hasIdentifier = false;
|
||||
}
|
||||
dotPos.drop();
|
||||
|
||||
refElement = refElement.precede();
|
||||
|
||||
if (!hasIdentifier) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (parameterList) {
|
||||
typeInfo.isParameterized = (builder.getTokenType() == JavaTokenType.LT);
|
||||
parseReferenceParameterList(builder, true);
|
||||
}
|
||||
else {
|
||||
emptyElement(builder, JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
}
|
||||
}
|
||||
|
||||
refElement.done(JavaElementType.JAVA_CODE_REFERENCE);
|
||||
return refElement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiBuilder.Marker parseReferenceParameterList(final PsiBuilder builder, final boolean wildcard) {
|
||||
final PsiBuilder.Marker list = builder.mark();
|
||||
if (!expect(builder, JavaTokenType.LT)) {
|
||||
list.done(JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
final PsiBuilder.Marker type = parseType(builder, true, wildcard);
|
||||
if (type == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.GT)) {
|
||||
break;
|
||||
}
|
||||
else if (!expectOrError(builder, JavaTokenType.COMMA, JavaErrorMessages.message("expected.gt.or.comma"))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
list.done(JavaElementType.REFERENCE_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiBuilder.Marker parseTypeParameters(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker list = builder.mark();
|
||||
if (!expect(builder, JavaTokenType.LT)) {
|
||||
list.done(JavaElementType.TYPE_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
final PsiBuilder.Marker param = parseTypeParameter(builder);
|
||||
if (param == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.type.parameter"));
|
||||
}
|
||||
if (!expect(builder, JavaTokenType.COMMA)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.GT)) {
|
||||
// hack for completion
|
||||
if (builder.getTokenType() == JavaTokenType.IDENTIFIER) {
|
||||
if (nextTokenType(builder) == JavaTokenType.GT) {
|
||||
final PsiBuilder.Marker errorElement = builder.mark();
|
||||
builder.advanceLexer();
|
||||
errorElement.error(JavaErrorMessages.message("unexpected.identifier"));
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.gt"));
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.gt"));
|
||||
}
|
||||
}
|
||||
|
||||
list.done(JavaElementType.TYPE_PARAMETER_LIST);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseTypeParameter(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker param = builder.mark();
|
||||
|
||||
DeclarationParser.parseAnnotations(builder);
|
||||
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
param.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.EXTENDS_KEYWORD)) {
|
||||
parseReferenceList(builder, JavaElementType.EXTENDS_BOUND_LIST, JavaTokenType.AND);
|
||||
}
|
||||
else {
|
||||
emptyElement(builder, JavaElementType.EXTENDS_BOUND_LIST);
|
||||
}
|
||||
|
||||
param.done(JavaElementType.TYPE_PARAMETER);
|
||||
return param;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseReferenceList(final PsiBuilder builder, final IElementType type, final IElementType delimiter) {
|
||||
final PsiBuilder.Marker element = builder.mark();
|
||||
|
||||
while (true) {
|
||||
final PsiBuilder.Marker classReference = parseJavaCodeReference(builder, true, true, true);
|
||||
if (classReference == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
if (!expect(builder, delimiter)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
element.done(type);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -42,7 +42,7 @@ import java.io.IOException;
|
||||
|
||||
public class JavaClassReferenceListElementType extends JavaStubElementType<PsiClassReferenceListStub, PsiReferenceList> {
|
||||
public JavaClassReferenceListElementType(@NotNull @NonNls String id) {
|
||||
super(id);
|
||||
super(id, true);
|
||||
}
|
||||
|
||||
public PsiReferenceList createPsi(final PsiClassReferenceListStub stub) {
|
||||
|
||||
@@ -29,8 +29,15 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class JavaStubElementType<StubT extends StubElement, PsiT extends PsiElement> extends IStubElementType<StubT, PsiT> {
|
||||
private final boolean myLeftBound;
|
||||
|
||||
protected JavaStubElementType(@NotNull @NonNls final String debugName) {
|
||||
this(debugName, false);
|
||||
}
|
||||
|
||||
protected JavaStubElementType(@NotNull @NonNls final String debugName, final boolean leftBound) {
|
||||
super(debugName, StdFileTypes.JAVA != null ? StdFileTypes.JAVA.getLanguage() : null);
|
||||
myLeftBound = leftBound;
|
||||
}
|
||||
|
||||
public String getExternalId() {
|
||||
@@ -47,4 +54,9 @@ public abstract class JavaStubElementType<StubT extends StubElement, PsiT extend
|
||||
}
|
||||
|
||||
public abstract PsiT createPsi(ASTNode node);
|
||||
|
||||
@Override
|
||||
public boolean isLeftBound() {
|
||||
return myLeftBound;
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public interface JavaElementType {
|
||||
|
||||
IElementType IMPORT_STATIC_REFERENCE = new IJavaElementType("IMPORT_STATIC_REFERENCE");
|
||||
IElementType TYPE = new IJavaElementType("TYPE");
|
||||
IElementType REFERENCE_PARAMETER_LIST = new IJavaElementType("REFERENCE_PARAMETER_LIST");
|
||||
IElementType REFERENCE_PARAMETER_LIST = new IJavaElementType("REFERENCE_PARAMETER_LIST", true);
|
||||
IElementType JAVA_CODE_REFERENCE = new IJavaElementType("JAVA_CODE_REFERENCE");
|
||||
IElementType PACKAGE_STATEMENT = new IJavaElementType("PACKAGE_STATEMENT");
|
||||
|
||||
@@ -120,7 +120,7 @@ public interface JavaElementType {
|
||||
|
||||
IElementType ANNOTATION_ARRAY_INITIALIZER = new IJavaElementType("ANNOTATION_ARRAY_INITIALIZER");
|
||||
IElementType NAME_VALUE_PAIR = new IJavaElementType("NAME_VALUE_PAIR");
|
||||
IElementType ANNOTATION_PARAMETER_LIST = new IJavaElementType("ANNOTATION_PARAMETER_LIST");
|
||||
IElementType ANNOTATION_PARAMETER_LIST = new IJavaElementType("ANNOTATION_PARAMETER_LIST", true);
|
||||
IElementType METHOD_RECEIVER = new IJavaElementType("METHOD_RECEIVER");
|
||||
|
||||
ILazyParseableElementType CODE_BLOCK = new IErrorCounterReparseableElementType("CODE_BLOCK", StdLanguages.JAVA) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:Array.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Endorsers
|
||||
PsiIdentifier:Endorsers('Endorsers')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiArrayInitializerMemberValue:{"Children", "Unscrupulous dentists"}
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiLiteralExpression:"Children"
|
||||
PsiJavaToken:STRING_LITERAL('"Children"')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:"Unscrupulous dentists"
|
||||
PsiJavaToken:STRING_LITERAL('"Unscrupulous dentists"')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:Complex.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Author
|
||||
PsiIdentifier:Author('Author')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:first('first')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiLiteralExpression:"Eugene"
|
||||
PsiJavaToken:STRING_LITERAL('"Eugene"')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:second('second')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiLiteralExpression:"Wampirchik"
|
||||
PsiJavaToken:STRING_LITERAL('"Wampirchik"')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,26 @@
|
||||
PsiJavaFile:FirstNameMissed.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Anno
|
||||
PsiIdentifier:Anno('Anno')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiReferenceExpression:value1
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:value1('value1')
|
||||
PsiErrorElement:Annotation attribute must be of the form 'name=value'
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:param2('param2')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiReferenceExpression:value2
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:value2('value2')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:Marker.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Preliminary
|
||||
PsiIdentifier:Preliminary('Preliminary')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,26 @@
|
||||
PsiJavaFile:Multiple.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Preliminary
|
||||
PsiIdentifier:Preliminary('Preliminary')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Other
|
||||
PsiIdentifier:Other('Other')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:name('name')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiReferenceExpression:value
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:value('value')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,32 @@
|
||||
PsiJavaFile:Nested.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Author
|
||||
PsiIdentifier:Author('Author')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Name
|
||||
PsiIdentifier:Name('Name')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:first('first')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiLiteralExpression:"Eugene"
|
||||
PsiJavaToken:STRING_LITERAL('"Eugene"')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiNameValuePair
|
||||
PsiIdentifier:second('second')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiLiteralExpression:"Wampirchik"
|
||||
PsiJavaToken:STRING_LITERAL('"Wampirchik"')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:ParameterizedAnnotation.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Nullable
|
||||
PsiIdentifier:Nullable('Nullable')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:LT('<')
|
||||
PsiIdentifier:T('T')
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,24 @@
|
||||
PsiJavaFile:QualifiedAnnotation.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:org.jetbrains.annotations.Nullable
|
||||
PsiJavaCodeReferenceElement:org.jetbrains.annotations
|
||||
PsiJavaCodeReferenceElement:org.jetbrains
|
||||
PsiJavaCodeReferenceElement:org
|
||||
PsiIdentifier:org('org')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiIdentifier:jetbrains('jetbrains')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiIdentifier:annotations('annotations')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiIdentifier:Nullable('Nullable')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:Simple0.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Copyright
|
||||
PsiIdentifier:Copyright('Copyright')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiLiteralExpression:"bla-bla-bla"
|
||||
PsiJavaToken:STRING_LITERAL('"bla-bla-bla"')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:Simple1.java
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:Copyright
|
||||
PsiIdentifier:Copyright('Copyright')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNameValuePair
|
||||
PsiReferenceExpression:treatedAsValue
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:treatedAsValue('treatedAsValue')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,5 @@
|
||||
PsiJavaFile:ArrayInitializer0.java
|
||||
PsiArrayInitializerExpression:{ }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,8 @@
|
||||
PsiJavaFile:ArrayInitializer1.java
|
||||
PsiArrayInitializerExpression:{ 1 }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:ArrayInitializer2.java
|
||||
PsiArrayInitializerExpression:{ 1, }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:ArrayInitializer3.java
|
||||
PsiArrayInitializerExpression:{ 1,2 }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:ArrayInitializer4.java
|
||||
PsiArrayInitializerExpression:{ 1 2 }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiErrorElement:',' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:ArrayInitializer5.java
|
||||
PsiArrayInitializerExpression:{ { }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiArrayInitializerExpression:{ }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiErrorElement:',' expected
|
||||
<empty list>
|
||||
PsiErrorElement:'}' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,7 @@
|
||||
PsiJavaFile:ArrayInitializer6.java
|
||||
PsiArrayInitializerExpression:{ , }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:ArrayInitializer7.java
|
||||
PsiArrayInitializerExpression:{ , , 7 }
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:7
|
||||
PsiJavaToken:INTEGER_LITERAL('7')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:Assignment0.java
|
||||
PsiAssignmentExpression:a = 0
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:Assignment1.java
|
||||
PsiAssignmentExpression:a =
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:Cast.java
|
||||
PsiTypeCastExpression:(Type)var
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeElement:Type
|
||||
PsiJavaCodeReferenceElement:Type
|
||||
PsiIdentifier:Type('Type')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceExpression:var
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:var('var')
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:Cond0.java
|
||||
PsiConditionalExpression:cond ? true : false
|
||||
PsiReferenceExpression:cond
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:cond('cond')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:true
|
||||
PsiJavaToken:TRUE_KEYWORD('true')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:COLON(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:false
|
||||
PsiJavaToken:FALSE_KEYWORD('false')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:Cond1.java
|
||||
PsiConditionalExpression:cond ?
|
||||
PsiReferenceExpression:cond
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:cond('cond')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:Cond2.java
|
||||
PsiConditionalExpression:cond ? true
|
||||
PsiReferenceExpression:cond
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:cond('cond')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:true
|
||||
PsiJavaToken:TRUE_KEYWORD('true')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:Cond3.java
|
||||
PsiConditionalExpression:cond ? true :
|
||||
PsiReferenceExpression:cond
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:cond('cond')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:true
|
||||
PsiJavaToken:TRUE_KEYWORD('true')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:COLON(':')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,21 @@
|
||||
PsiJavaFile:CondOr0.java
|
||||
PsiBinaryExpression:a || b || c
|
||||
PsiBinaryExpression:a || b
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OROR('||')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:b
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:b('b')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OROR('||')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:c
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:c('c')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:CondOr1.java
|
||||
PsiBinaryExpression:a ||
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OROR('||')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:ExprList0.java
|
||||
PsiMethodCallExpression:f(1,2)
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:ExprList1.java
|
||||
PsiMethodCallExpression:f(
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:ExprList2.java
|
||||
PsiMethodCallExpression:f(1
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,17 @@
|
||||
PsiJavaFile:ExprList3.java
|
||||
PsiMethodCallExpression:f(1,
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiExpression(empty)
|
||||
<empty list>
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:ExprList4.java
|
||||
PsiMethodCallExpression:f(1,)
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiExpression(empty)
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,19 @@
|
||||
PsiJavaFile:ExprList5.java
|
||||
PsiMethodCallExpression:f(1,,2)
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiExpression(empty)
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:ExprList6.java
|
||||
PsiMethodCallExpression:f(,2)
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiExpression(empty)
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,17 @@
|
||||
PsiJavaFile:GE.java
|
||||
PsiAssignmentExpression:x >>>= 8 >> 2
|
||||
PsiReferenceExpression:x
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:x('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:GTGTGTEQ('>>>=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBinaryExpression:8 >> 2
|
||||
PsiLiteralExpression:8
|
||||
PsiJavaToken:INTEGER_LITERAL('8')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:GTGT('>>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
@@ -0,0 +1,24 @@
|
||||
PsiJavaFile:IllegalWildcard.java
|
||||
PsiConditionalExpression:this.<?
|
||||
PsiReferenceExpression:this.<
|
||||
PsiThisExpression:this
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiErrorElement:'>' or ',' expected.
|
||||
<empty list>
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:GT('>')
|
||||
PsiIdentifier:foo('foo')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,26 @@
|
||||
PsiJavaFile:IncompleteCast.java
|
||||
PsiMethodCallExpression:f((ArrayList<String>) )
|
||||
PsiReferenceExpression:f
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeCastExpression:(ArrayList<String>)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiTypeElement:ArrayList<String>
|
||||
PsiJavaCodeReferenceElement:ArrayList<String>
|
||||
PsiIdentifier:ArrayList('ArrayList')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:InstanceOf0.java
|
||||
PsiInstanceofExpression:a instanceof String
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:instanceof('instanceof')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:InstanceOf1.java
|
||||
PsiInstanceofExpression:a instanceof
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:instanceof('instanceof')
|
||||
PsiErrorElement:Type expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:New0.java
|
||||
PsiNewExpression:new A()
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:New1.java
|
||||
PsiNewExpression:new A[1][]
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:New10.java
|
||||
PsiNewExpression:new int
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:int('int')
|
||||
PsiErrorElement:'[' expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:New11.java
|
||||
PsiNewExpression:new String[0
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:New12.java
|
||||
PsiNewExpression:new int[1][2]
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:int('int')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
@@ -0,0 +1,19 @@
|
||||
PsiJavaFile:New13.java
|
||||
PsiNewExpression:new int[1][][
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:int('int')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:New14.java
|
||||
PsiNewExpression:Q.new A()
|
||||
PsiReferenceExpression:Q
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:Q('Q')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:New2.java
|
||||
PsiNewExpression:new A[]
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiErrorElement:Array initializer expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:New3.java
|
||||
PsiNewExpression:new A[][
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
@@ -0,0 +1,19 @@
|
||||
PsiJavaFile:New4.java
|
||||
PsiNewExpression:new A[][]{null}
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiArrayInitializerExpression:{null}
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:New5.java
|
||||
PsiNewExpression:new A[1]
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,7 @@
|
||||
PsiJavaFile:New6.java
|
||||
PsiNewExpression:new
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:New7.java
|
||||
PsiNewExpression:new A
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:'(' or '[' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:New8.java
|
||||
PsiNewExpression:new A[
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:A
|
||||
PsiIdentifier:A('A')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:New9.java
|
||||
PsiNewExpression:new int
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:int('int')
|
||||
PsiErrorElement:'[' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:NewInExprList.java
|
||||
PsiMethodCallExpression:call(new)
|
||||
PsiReferenceExpression:call
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:call('call')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiNewExpression:new
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:Not0.java
|
||||
PsiPrefixExpression:!!a
|
||||
PsiJavaToken:EXCL('!')
|
||||
PsiPrefixExpression:!a
|
||||
PsiJavaToken:EXCL('!')
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
@@ -0,0 +1,5 @@
|
||||
PsiJavaFile:Not1.java
|
||||
PsiPrefixExpression:!
|
||||
PsiJavaToken:EXCL('!')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,21 @@
|
||||
PsiJavaFile:Or0.java
|
||||
PsiBinaryExpression:a | b | c
|
||||
PsiBinaryExpression:a | b
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OR('|')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:b
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:b('b')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OR('|')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:c
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:c('c')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:Or1.java
|
||||
PsiBinaryExpression:a |
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:OR('|')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,8 @@
|
||||
PsiJavaFile:Parenth0.java
|
||||
PsiParenthesizedExpression:(c)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiReferenceExpression:c
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:c('c')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:Parenth1.java
|
||||
PsiPostfixExpression:(this).f--
|
||||
PsiReferenceExpression:(this).f
|
||||
PsiParenthesizedExpression:(this)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiThisExpression:this
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:f('f')
|
||||
PsiJavaToken:MINUSMINUS('--')
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:PinesInReferenceExpression0.java
|
||||
PsiMethodCallExpression:Collections.<String>sort(null)
|
||||
PsiReferenceExpression:Collections.<String>sort
|
||||
PsiReferenceExpression:Collections
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:Collections('Collections')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiIdentifier:sort('sort')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:PinesInReferenceExpression1.java
|
||||
PsiMethodCallExpression:this.<String>sort(null)
|
||||
PsiReferenceExpression:this.<String>sort
|
||||
PsiThisExpression:this
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:this('this')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiIdentifier:sort('sort')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:null
|
||||
PsiJavaToken:NULL_KEYWORD('null')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,6 @@
|
||||
PsiJavaFile:PrimitiveClassObjectAccess.java
|
||||
PsiClassObjectAccessExpression:int.class
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:class('class')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:QualifiedSuperMethodCall0.java
|
||||
PsiMethodCallExpression:new D().super(0)
|
||||
PsiReferenceExpression:new D().super
|
||||
PsiNewExpression:new D()
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:D
|
||||
PsiIdentifier:D('D')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:super('super')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:QualifiedSuperMethodCall1.java
|
||||
PsiMethodCallExpression:d.super(0)
|
||||
PsiReferenceExpression:d.super
|
||||
PsiReferenceExpression:d
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:d('d')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:super('super')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:ShiftRight.java
|
||||
PsiAssignmentExpression:x >>= 2
|
||||
PsiReferenceExpression:x
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:x('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:GTGTEQ('>>=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:SuperMethodCallTypeParameterList.java
|
||||
PsiMethodCallExpression:super()
|
||||
PsiReferenceExpression:super
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:super('super')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -0,0 +1,5 @@
|
||||
PsiJavaFile:Reference0.java
|
||||
PsiJavaCodeReferenceElement:a
|
||||
PsiIdentifier:a('a')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:Reference1.java
|
||||
PsiJavaCodeReferenceElement:a.
|
||||
PsiJavaCodeReferenceElement:a
|
||||
PsiIdentifier:a('a')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:Reference2.java
|
||||
PsiJavaCodeReferenceElement:a.b
|
||||
PsiJavaCodeReferenceElement:a
|
||||
PsiIdentifier:a('a')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiIdentifier:b('b')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,3 @@
|
||||
PsiJavaFile:Type0.java
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:Type1.java
|
||||
PsiTypeElement:a.b
|
||||
PsiJavaCodeReferenceElement:a.b
|
||||
PsiJavaCodeReferenceElement:a
|
||||
PsiIdentifier:a('a')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiIdentifier:b('b')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
@@ -0,0 +1,6 @@
|
||||
PsiJavaFile:Type2.java
|
||||
PsiTypeElement:int[]
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:Type3.java
|
||||
PsiTypeElement:int[]
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,24 @@
|
||||
PsiJavaFile:Type4.java
|
||||
PsiTypeElement:Map<String,List<String>>
|
||||
PsiJavaCodeReferenceElement:Map<String,List<String>>
|
||||
PsiIdentifier:Map('Map')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiTypeElement:List<String>
|
||||
PsiJavaCodeReferenceElement:List<String>
|
||||
PsiIdentifier:List('List')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,8 @@
|
||||
PsiJavaFile:TypeParams0.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:TypeParams1.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeParameter:U
|
||||
PsiIdentifier:U('U')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:TypeParams2.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:TypeParams3.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected identifier
|
||||
PsiIdentifier:hack('hack')
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,12 @@
|
||||
PsiJavaFile:TypeParams4.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiIdentifier:hack('hack')
|
||||
@@ -0,0 +1,27 @@
|
||||
PsiJavaFile:TypeParams5.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:AND('&')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:Y<Z>
|
||||
PsiIdentifier:Y('Y')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:Z
|
||||
PsiJavaCodeReferenceElement:Z
|
||||
PsiIdentifier:Z('Z')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:TypeParams6.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiIdentifier:supers('supers')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:X('X')
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:TypeParams7.java
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeParameter:Y
|
||||
PsiIdentifier:Y('Y')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.intellij;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.impl.PsiBuilderImpl;
|
||||
import com.intellij.lang.java.parser.JavaParserUtil;
|
||||
import com.intellij.lexer.JavaLexer;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -13,4 +19,12 @@ public class JavaTestUtil {
|
||||
public static String getJavaTestDataPath() {
|
||||
return PathManagerEx.getTestDataPath();
|
||||
}
|
||||
|
||||
public static PsiBuilder getJavaBuilder(final String source) {
|
||||
final LanguageLevel languageLevel = LanguageLevel.HIGHEST;
|
||||
final JavaLexer lexer = new JavaLexer(languageLevel);
|
||||
final PsiBuilder builder = new PsiBuilderImpl(lexer, JavaTokenType.WHITESPACE_BIT_SET, JavaTokenType.COMMENT_BIT_SET, source);
|
||||
JavaParserUtil.setLanguageLevel(builder, languageLevel);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.testFramework.IdeaTestCase;
|
||||
import com.intellij.testFramework.ParsingTestCase;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.intellij.JavaTestUtil.getJavaBuilder;
|
||||
|
||||
|
||||
public abstract class JavaParsingTestCase extends ParsingTestCase {
|
||||
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
|
||||
public JavaParsingTestCase(@NonNls final String dataPath) {
|
||||
super(dataPath, "java");
|
||||
IdeaTestCase.initPlatformPrefix();
|
||||
}
|
||||
|
||||
protected interface Parser {
|
||||
void parse(PsiBuilder builder);
|
||||
}
|
||||
|
||||
protected void doParserTest(final String text, final Parser parser) {
|
||||
final String name = getTestName(false);
|
||||
|
||||
final PsiBuilder builder = getJavaBuilder(text);
|
||||
final PsiBuilder.Marker root = builder.mark();
|
||||
|
||||
parser.parse(builder);
|
||||
|
||||
if (builder.getTokenType() != null) {
|
||||
final PsiBuilder.Marker unparsed = builder.mark();
|
||||
while (builder.getTokenType() != null) builder.advanceLexer();
|
||||
unparsed.error("Unparsed tokens");
|
||||
}
|
||||
|
||||
root.done(JavaElementType.JAVA_FILE);
|
||||
|
||||
final String raw = DebugUtil.treeToString(builder.getTreeBuilt(), false);
|
||||
final String tree = raw.replaceFirst("com.intellij.psi.util.PsiUtilBase\\S+", "PsiJavaFile:" + name + ".java");
|
||||
try {
|
||||
checkResult(name + ".txt", tree);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser.partial;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.java.parser.DeclarationParser;
|
||||
import com.intellij.lang.java.parser.JavaParsingTestCase;
|
||||
|
||||
|
||||
public class AnnotationParserTest extends JavaParsingTestCase {
|
||||
public AnnotationParserTest() {
|
||||
super("parser-partial/annotations");
|
||||
}
|
||||
|
||||
public void testMarker() { doParserTest("@Preliminary"); }
|
||||
public void testSimple0() { doParserTest("@Copyright(\"bla-bla-bla\")"); }
|
||||
public void testSimple1() { doParserTest("@Copyright(treatedAsValue)"); }
|
||||
public void testComplex() { doParserTest("@Author(first=\"Eugene\", second=\"Wampirchik\")"); }
|
||||
public void testMultiple() { doParserTest("@Preliminary @Other(name=value)"); }
|
||||
public void testArray() { doParserTest("@Endorsers({\"Children\", \"Unscrupulous dentists\"})"); }
|
||||
public void testNested() { doParserTest("@Author(@Name(first=\"Eugene\", second=\"Wampirchik\"))"); }
|
||||
public void testQualifiedAnnotation() { doParserTest("@org.jetbrains.annotations.Nullable"); }
|
||||
|
||||
public void testParameterizedAnnotation () { doParserTest("@Nullable<T>"); }
|
||||
public void testFirstNameMissed() { doParserTest("@Anno(value1, param2=value2)"); }
|
||||
|
||||
private void doParserTest(final String text) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
DeclarationParser.parseAnnotations(builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser.partial;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.java.parser.ExpressionParser;
|
||||
import com.intellij.lang.java.parser.JavaParsingTestCase;
|
||||
|
||||
|
||||
public class ExpressionParserTest extends JavaParsingTestCase {
|
||||
public ExpressionParserTest() {
|
||||
super("parser-partial/expressions");
|
||||
}
|
||||
|
||||
public void testAssignment0() { doParserTest("a = 0"); }
|
||||
public void testAssignment1() { doParserTest("a ="); }
|
||||
|
||||
public void testCond0() { doParserTest("cond ? true : false"); }
|
||||
public void testCond1() { doParserTest("cond ?"); }
|
||||
public void testCond2() { doParserTest("cond ? true"); }
|
||||
public void testCond3() { doParserTest("cond ? true :"); }
|
||||
|
||||
public void testCondOr0() { doParserTest("a || b || c"); }
|
||||
public void testCondOr1() { doParserTest("a ||"); }
|
||||
|
||||
public void testOr0() { doParserTest("a | b | c"); }
|
||||
public void testOr1() { doParserTest("a |"); }
|
||||
|
||||
public void testInstanceOf0() { doParserTest("a instanceof String"); }
|
||||
public void testInstanceOf1() { doParserTest("a instanceof"); }
|
||||
|
||||
public void testNot0() { doParserTest("!!a"); }
|
||||
public void testNot1() { doParserTest("!"); }
|
||||
|
||||
public void testCast() { doParserTest("(Type)var"); }
|
||||
|
||||
public void testParenth0() { doParserTest("(c)"); }
|
||||
public void testParenth1() { doParserTest("(this).f--"); }
|
||||
|
||||
public void testNewInExprList() { doParserTest("call(new)"); }
|
||||
|
||||
public void testNew0() { doParserTest("new A()"); }
|
||||
public void testNew1() { doParserTest("new A[1][]"); }
|
||||
public void testNew2() { doParserTest("new A[]"); }
|
||||
public void testNew3() { doParserTest("new A[][1]"); }
|
||||
public void testNew4() { doParserTest("new A[][]{null}"); }
|
||||
public void testNew5() { doParserTest("new A[1]{null}"); }
|
||||
public void testNew6() { doParserTest("new"); }
|
||||
public void testNew7() { doParserTest("new A"); }
|
||||
public void testNew8() { doParserTest("new A["); }
|
||||
public void testNew9() { doParserTest("new int"); }
|
||||
public void testNew10() { doParserTest("new int()"); }
|
||||
public void testNew11() { doParserTest("new String[0"); }
|
||||
public void testNew12() { doParserTest("new int[1][2]"); }
|
||||
public void testNew13() { doParserTest("new int[1][][2]"); }
|
||||
public void testNew14() { doParserTest("Q.new A()"); }
|
||||
|
||||
public void testExprList0() { doParserTest("f(1,2)"); }
|
||||
public void testExprList1() { doParserTest("f("); }
|
||||
public void testExprList2() { doParserTest("f(1"); }
|
||||
public void testExprList3() { doParserTest("f(1,"); }
|
||||
public void testExprList4() { doParserTest("f(1,)"); }
|
||||
public void testExprList5() { doParserTest("f(1,,2)"); }
|
||||
public void testExprList6() { doParserTest("f(,2)"); }
|
||||
|
||||
public void testArrayInitializer0() { doParserTest("{ }"); }
|
||||
public void testArrayInitializer1() { doParserTest("{ 1 }"); }
|
||||
public void testArrayInitializer2() { doParserTest("{ 1, }"); }
|
||||
public void testArrayInitializer3() { doParserTest("{ 1,2 }"); }
|
||||
public void testArrayInitializer4() { doParserTest("{ 1 2 }"); }
|
||||
public void testArrayInitializer5() { doParserTest("{ { }"); }
|
||||
public void testArrayInitializer6() { doParserTest("{ , }"); }
|
||||
public void testArrayInitializer7() { doParserTest("{ , , 7 }"); }
|
||||
|
||||
public void testPinesInReferenceExpression0() { doParserTest("Collections.<String>sort(null)"); }
|
||||
public void testPinesInReferenceExpression1() { doParserTest("this.<String>sort(null)"); }
|
||||
|
||||
public void testGE() { doParserTest("x >>>= 8 >> 2"); }
|
||||
|
||||
public void testIncompleteCast() { doParserTest("f((ArrayList<String>) )"); }
|
||||
public void testShiftRight() { doParserTest("x >>= 2"); }
|
||||
|
||||
public void testIllegalWildcard() { doParserTest("this.<?>foo()"); }
|
||||
|
||||
public void testQualifiedSuperMethodCall0() { doParserTest("new D().super(0)"); }
|
||||
public void testQualifiedSuperMethodCall1() { doParserTest("d.super(0)"); }
|
||||
public void testSuperMethodCallTypeParameterList() { doParserTest("super()"); }
|
||||
public void testPrimitiveClassObjectAccess() { doParserTest("int.class"); }
|
||||
|
||||
private void doParserTest(final String text) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ExpressionParser.parse(builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang.java.parser.partial;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.java.parser.JavaParsingTestCase;
|
||||
import com.intellij.lang.java.parser.ReferenceParser;
|
||||
|
||||
|
||||
public class ReferenceParserTest extends JavaParsingTestCase {
|
||||
public ReferenceParserTest() {
|
||||
super("parser-partial/references");
|
||||
}
|
||||
|
||||
public void testReference0() { doRefParserTest("a", false); }
|
||||
public void testReference1() { doRefParserTest("a.", true); }
|
||||
public void testReference2() { doRefParserTest("a.b", false); }
|
||||
|
||||
public void testType0() { doTypeParserTest("int", false); }
|
||||
public void testType1() { doTypeParserTest("a.b", false); }
|
||||
public void testType2() { doTypeParserTest("int[]", false); }
|
||||
public void testType3() { doTypeParserTest("int[][", false); }
|
||||
public void testType4() { doTypeParserTest("Map<String,List<String>>", false); }
|
||||
|
||||
public void testTypeParams0() { doTypeParamsParserTest("<T>"); }
|
||||
public void testTypeParams1() { doTypeParamsParserTest("<T, U>"); }
|
||||
public void testTypeParams2() { doTypeParamsParserTest("<T"); }
|
||||
public void testTypeParams3() { doTypeParamsParserTest("<T hack>"); }
|
||||
public void testTypeParams4() { doTypeParamsParserTest("<T hack"); }
|
||||
public void testTypeParams5() { doTypeParamsParserTest("<T extends X & Y<Z>>"); }
|
||||
public void testTypeParams6() { doTypeParamsParserTest("<T supers X>"); }
|
||||
public void testTypeParams7() { doTypeParamsParserTest("<T extends X, Y>"); }
|
||||
|
||||
private void doRefParserTest(final String text, final boolean incomplete) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseJavaCodeReference(builder, incomplete, false, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doTypeParserTest(final String text, final boolean incomplete) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseType(builder, incomplete, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void doTypeParamsParserTest(final String text) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseTypeParameters(builder);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,19 @@ import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
public class IJavaElementType extends IElementType {
|
||||
private final boolean myLeftBound;
|
||||
|
||||
public IJavaElementType(@NonNls String debugName) {
|
||||
this(debugName, false);
|
||||
}
|
||||
|
||||
public IJavaElementType(@NonNls final String debugName, final boolean leftBound) {
|
||||
super(debugName, StdFileTypes.JAVA != null ? StdFileTypes.JAVA.getLanguage() : null);
|
||||
myLeftBound = leftBound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeftBound() {
|
||||
return myLeftBound;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.lang;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
public class PsiBuilderUtil {
|
||||
private PsiBuilderUtil() { }
|
||||
|
||||
/**
|
||||
* Returns type of next token.
|
||||
*
|
||||
* @param builder PSI builder to operate on.
|
||||
* @return type of next token or null, if the builder is at the end of token stream
|
||||
*/
|
||||
@Nullable
|
||||
public static IElementType nextTokenType(final PsiBuilder builder) {
|
||||
if (builder.getTokenType() == null) return null;
|
||||
final PsiBuilder.Marker sp = builder.mark();
|
||||
builder.advanceLexer();
|
||||
final IElementType result = builder.getTokenType();
|
||||
sp.rollbackTo();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if tokens in token stream form expected sequence.
|
||||
*
|
||||
* @param builder PSI builder to operate on.
|
||||
* @param tokenTypes expected elements.
|
||||
* @return true if tokens form expected sequence, false otherwise
|
||||
*/
|
||||
public static boolean lookAhead(final PsiBuilder builder, final IElementType... tokenTypes) {
|
||||
if (tokenTypes.length == 0) return true;
|
||||
|
||||
if (!tokenTypes[0].equals(builder.getTokenType())) return false;
|
||||
|
||||
if (tokenTypes.length == 1) return true;
|
||||
|
||||
final PsiBuilder.Marker rb = builder.mark();
|
||||
builder.advanceLexer();
|
||||
int i = 1;
|
||||
while (!builder.eof() && i < tokenTypes.length && tokenTypes[i].equals(builder.getTokenType())) {
|
||||
builder.advanceLexer();
|
||||
i++;
|
||||
}
|
||||
rb.rollbackTo();
|
||||
return i == tokenTypes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances lexer by given number of tokens (but not beyond the end of token stream).
|
||||
*
|
||||
* @param builder PSI builder to operate on.
|
||||
* @param count number of tokens to skip.
|
||||
*/
|
||||
public static void advance(final PsiBuilder builder, final int count) {
|
||||
for (int i=0; i<count && !builder.eof(); i++) {
|
||||
builder.getTokenType();
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances lexer if current token is of expected type, does nothing otherwise.
|
||||
*
|
||||
* @param builder PSI builder to operate on.
|
||||
* @param expectedType expected token.
|
||||
* @return true if token matches, false otherwise.
|
||||
*/
|
||||
public static boolean expect(final PsiBuilder builder, final IElementType expectedType) {
|
||||
if (builder.getTokenType() == expectedType) {
|
||||
builder.advanceLexer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances lexer if current token is of expected type, does nothing otherwise.
|
||||
*
|
||||
* @param builder PSI builder to operate on.
|
||||
* @param expectedTypes expected token types.
|
||||
* @return true if token matches, false otherwise.
|
||||
*/
|
||||
public static boolean expect(final PsiBuilder builder, final TokenSet expectedTypes) {
|
||||
if (expectedTypes.contains(builder.getTokenType())) {
|
||||
builder.advanceLexer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release group of allocated markers.
|
||||
*
|
||||
* @param markers markers to drop.
|
||||
*/
|
||||
public static void drop(final PsiBuilder.Marker... markers) {
|
||||
for (PsiBuilder.Marker marker : markers) {
|
||||
marker.drop();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user