diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png index caf2b6292be6..af11f5f8ee39 100644 Binary files a/community-resources/src/idea_community_about.png and b/community-resources/src/idea_community_about.png differ diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png index 2a43165ee623..3bb7994bedda 100644 Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java new file mode 100644 index 000000000000..268e9c2fd5ac --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -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; + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java new file mode 100644 index 000000000000..b649997a7b72 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -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 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 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 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); + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavaParser.java b/java/java-impl/src/com/intellij/lang/java/parser/JavaParser.java new file mode 100644 index 000000000000..b06bf223d085 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavaParser.java @@ -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(); + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java new file mode 100644 index 000000000000..73937f311f81 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -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 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); + } +} diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java new file mode 100644 index 000000000000..8831468fabe3 --- /dev/null +++ b/java/java-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -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; + } +} diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java index c349bef30c79..058f529610ff 100644 --- a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java @@ -42,7 +42,7 @@ import java.io.IOException; public class JavaClassReferenceListElementType extends JavaStubElementType { public JavaClassReferenceListElementType(@NotNull @NonNls String id) { - super(id); + super(id, true); } public PsiReferenceList createPsi(final PsiClassReferenceListStub stub) { diff --git a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementType.java b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementType.java index 9bcab4f8d55b..bcf07816f068 100644 --- a/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementType.java +++ b/java/java-impl/src/com/intellij/psi/impl/java/stubs/JavaStubElementType.java @@ -29,8 +29,15 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; public abstract class JavaStubElementType extends IStubElementType { + 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 javaFiles) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { + PsiManager.getInstance(project).performActionWithFormatterDisabled(new Runnable() { public void run() { - PsiDocumentManager.getInstance(project).commitAllDocuments(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + PsiDocumentManager.getInstance(project).commitAllDocuments(); + } + }); } }); + final Set> redundants = new HashSet>(); final Runnable findRedundantImports = new Runnable() { public void run() { diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml index 6a5f10524cf3..d18da953d9a7 100644 --- a/java/java-tests/java-tests.iml +++ b/java/java-tests/java-tests.iml @@ -3,7 +3,7 @@ - + diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Array.txt b/java/java-tests/testData/psi/parser-partial/annotations/Array.txt new file mode 100644 index 000000000000..55252134c2fc --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Array.txt @@ -0,0 +1,20 @@ +PsiJavaFile:Array.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Endorsers + PsiIdentifier:Endorsers('Endorsers') + PsiReferenceParameterList + + 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(')') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Complex.txt b/java/java-tests/testData/psi/parser-partial/annotations/Complex.txt new file mode 100644 index 000000000000..5211c0a10ec1 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Complex.txt @@ -0,0 +1,22 @@ +PsiJavaFile:Complex.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Author + PsiIdentifier:Author('Author') + PsiReferenceParameterList + + 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(')') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/FirstNameMissed.txt b/java/java-tests/testData/psi/parser-partial/annotations/FirstNameMissed.txt new file mode 100644 index 000000000000..711c2fa63385 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/FirstNameMissed.txt @@ -0,0 +1,26 @@ +PsiJavaFile:FirstNameMissed.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Anno + PsiIdentifier:Anno('Anno') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiReferenceExpression:value1 + PsiReferenceParameterList + + PsiIdentifier:value1('value1') + PsiErrorElement:Annotation attribute must be of the form 'name=value' + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiNameValuePair + PsiIdentifier:param2('param2') + PsiJavaToken:EQ('=') + PsiReferenceExpression:value2 + PsiReferenceParameterList + + PsiIdentifier:value2('value2') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Marker.txt b/java/java-tests/testData/psi/parser-partial/annotations/Marker.txt new file mode 100644 index 000000000000..ca28bc4eb311 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Marker.txt @@ -0,0 +1,9 @@ +PsiJavaFile:Marker.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Preliminary + PsiIdentifier:Preliminary('Preliminary') + PsiReferenceParameterList + + PsiAnnotationParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Multiple.txt b/java/java-tests/testData/psi/parser-partial/annotations/Multiple.txt new file mode 100644 index 000000000000..5ef2baf465b6 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Multiple.txt @@ -0,0 +1,26 @@ +PsiJavaFile:Multiple.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Preliminary + PsiIdentifier:Preliminary('Preliminary') + PsiReferenceParameterList + + PsiAnnotationParameterList + + PsiWhiteSpace(' ') + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Other + PsiIdentifier:Other('Other') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiIdentifier:name('name') + PsiJavaToken:EQ('=') + PsiReferenceExpression:value + PsiReferenceParameterList + + PsiIdentifier:value('value') + PsiJavaToken:RPARENTH(')') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Nested.txt b/java/java-tests/testData/psi/parser-partial/annotations/Nested.txt new file mode 100644 index 000000000000..e8cfe4480a70 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Nested.txt @@ -0,0 +1,32 @@ +PsiJavaFile:Nested.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Author + PsiIdentifier:Author('Author') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Name + PsiIdentifier:Name('Name') + PsiReferenceParameterList + + 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(')') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/ParameterizedAnnotation.txt b/java/java-tests/testData/psi/parser-partial/annotations/ParameterizedAnnotation.txt new file mode 100644 index 000000000000..a1843135e0fa --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/ParameterizedAnnotation.txt @@ -0,0 +1,13 @@ +PsiJavaFile:ParameterizedAnnotation.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Nullable + PsiIdentifier:Nullable('Nullable') + PsiReferenceParameterList + + PsiAnnotationParameterList + + PsiErrorElement:Unparsed tokens + PsiJavaToken:LT('<') + PsiIdentifier:T('T') + PsiJavaToken:GT('>') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/QualifiedAnnotation.txt b/java/java-tests/testData/psi/parser-partial/annotations/QualifiedAnnotation.txt new file mode 100644 index 000000000000..d73ddfe716ef --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/QualifiedAnnotation.txt @@ -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 + + PsiJavaToken:DOT('.') + PsiIdentifier:jetbrains('jetbrains') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:annotations('annotations') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:Nullable('Nullable') + PsiReferenceParameterList + + PsiAnnotationParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Simple0.txt b/java/java-tests/testData/psi/parser-partial/annotations/Simple0.txt new file mode 100644 index 000000000000..486549bf98a5 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Simple0.txt @@ -0,0 +1,13 @@ +PsiJavaFile:Simple0.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Copyright + PsiIdentifier:Copyright('Copyright') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiLiteralExpression:"bla-bla-bla" + PsiJavaToken:STRING_LITERAL('"bla-bla-bla"') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/annotations/Simple1.txt b/java/java-tests/testData/psi/parser-partial/annotations/Simple1.txt new file mode 100644 index 000000000000..078d0698e0a5 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/Simple1.txt @@ -0,0 +1,15 @@ +PsiJavaFile:Simple1.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Copyright + PsiIdentifier:Copyright('Copyright') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiReferenceExpression:treatedAsValue + PsiReferenceParameterList + + PsiIdentifier:treatedAsValue('treatedAsValue') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer0.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer0.txt new file mode 100644 index 000000000000..508d0daa897e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer0.txt @@ -0,0 +1,5 @@ +PsiJavaFile:ArrayInitializer0.java + PsiArrayInitializerExpression:{ } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer1.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer1.txt new file mode 100644 index 000000000000..23a7143df03d --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer1.txt @@ -0,0 +1,8 @@ +PsiJavaFile:ArrayInitializer1.java + PsiArrayInitializerExpression:{ 1 } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer2.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer2.txt new file mode 100644 index 000000000000..35a40adbfcfe --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer2.txt @@ -0,0 +1,9 @@ +PsiJavaFile:ArrayInitializer2.java + PsiArrayInitializerExpression:{ 1, } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer3.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer3.txt new file mode 100644 index 000000000000..71af49d3934a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer3.txt @@ -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('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer4.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer4.txt new file mode 100644 index 000000000000..e8b34ebf48cc --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer4.txt @@ -0,0 +1,13 @@ +PsiJavaFile:ArrayInitializer4.java + PsiArrayInitializerExpression:{ 1 2 } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiErrorElement:',' expected + + PsiWhiteSpace(' ') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer5.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer5.txt new file mode 100644 index 000000000000..4613ecc1968b --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer5.txt @@ -0,0 +1,12 @@ +PsiJavaFile:ArrayInitializer5.java + PsiArrayInitializerExpression:{ { } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiArrayInitializerExpression:{ } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') + PsiErrorElement:',' expected + + PsiErrorElement:'}' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer6.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer6.txt new file mode 100644 index 000000000000..6dba1a6ae959 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer6.txt @@ -0,0 +1,7 @@ +PsiJavaFile:ArrayInitializer6.java + PsiArrayInitializerExpression:{ , } + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer7.txt b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer7.txt new file mode 100644 index 000000000000..c33132bf2ac7 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ArrayInitializer7.txt @@ -0,0 +1,16 @@ +PsiJavaFile:ArrayInitializer7.java + PsiArrayInitializerExpression:{ , , 7 } + PsiJavaToken:LBRACE('{') + PsiErrorElement:Expression expected + + PsiWhiteSpace(' ') + PsiJavaToken:COMMA(',') + PsiErrorElement:Expression expected + + PsiWhiteSpace(' ') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiLiteralExpression:7 + PsiJavaToken:INTEGER_LITERAL('7') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Assignment0.txt b/java/java-tests/testData/psi/parser-partial/expressions/Assignment0.txt new file mode 100644 index 000000000000..92a8e7022745 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Assignment0.txt @@ -0,0 +1,11 @@ +PsiJavaFile:Assignment0.java + PsiAssignmentExpression:a = 0 + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Assignment1.txt b/java/java-tests/testData/psi/parser-partial/expressions/Assignment1.txt new file mode 100644 index 000000000000..be4001ee9b29 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Assignment1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:Assignment1.java + PsiAssignmentExpression:a = + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Cast.txt b/java/java-tests/testData/psi/parser-partial/expressions/Cast.txt new file mode 100644 index 000000000000..8bcbe793d8b5 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Cast.txt @@ -0,0 +1,13 @@ +PsiJavaFile:Cast.java + PsiTypeCastExpression:(Type)var + PsiJavaToken:LPARENTH('(') + PsiTypeElement:Type + PsiJavaCodeReferenceElement:Type + PsiIdentifier:Type('Type') + PsiReferenceParameterList + + PsiJavaToken:RPARENTH(')') + PsiReferenceExpression:var + PsiReferenceParameterList + + PsiIdentifier:var('var') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Cond0.txt b/java/java-tests/testData/psi/parser-partial/expressions/Cond0.txt new file mode 100644 index 000000000000..291ac315d46f --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Cond0.txt @@ -0,0 +1,16 @@ +PsiJavaFile:Cond0.java + PsiConditionalExpression:cond ? true : false + PsiReferenceExpression:cond + PsiReferenceParameterList + + PsiIdentifier:cond('cond') + PsiWhiteSpace(' ') + PsiJavaToken:QUEST('?') + PsiWhiteSpace(' ') + PsiLiteralExpression:true + PsiJavaToken:TRUE_KEYWORD('true') + PsiWhiteSpace(' ') + PsiJavaToken:COLON(':') + PsiWhiteSpace(' ') + PsiLiteralExpression:false + PsiJavaToken:FALSE_KEYWORD('false') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Cond1.txt b/java/java-tests/testData/psi/parser-partial/expressions/Cond1.txt new file mode 100644 index 000000000000..544ddceb3a99 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Cond1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:Cond1.java + PsiConditionalExpression:cond ? + PsiReferenceExpression:cond + PsiReferenceParameterList + + PsiIdentifier:cond('cond') + PsiWhiteSpace(' ') + PsiJavaToken:QUEST('?') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Cond2.txt b/java/java-tests/testData/psi/parser-partial/expressions/Cond2.txt new file mode 100644 index 000000000000..95e7e6891135 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Cond2.txt @@ -0,0 +1,13 @@ +PsiJavaFile:Cond2.java + PsiConditionalExpression:cond ? true + PsiReferenceExpression:cond + PsiReferenceParameterList + + PsiIdentifier:cond('cond') + PsiWhiteSpace(' ') + PsiJavaToken:QUEST('?') + PsiWhiteSpace(' ') + PsiLiteralExpression:true + PsiJavaToken:TRUE_KEYWORD('true') + PsiErrorElement:':' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Cond3.txt b/java/java-tests/testData/psi/parser-partial/expressions/Cond3.txt new file mode 100644 index 000000000000..50f9d82cb193 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Cond3.txt @@ -0,0 +1,15 @@ +PsiJavaFile:Cond3.java + PsiConditionalExpression:cond ? true : + PsiReferenceExpression:cond + PsiReferenceParameterList + + PsiIdentifier:cond('cond') + PsiWhiteSpace(' ') + PsiJavaToken:QUEST('?') + PsiWhiteSpace(' ') + PsiLiteralExpression:true + PsiJavaToken:TRUE_KEYWORD('true') + PsiWhiteSpace(' ') + PsiJavaToken:COLON(':') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/CondOr0.txt b/java/java-tests/testData/psi/parser-partial/expressions/CondOr0.txt new file mode 100644 index 000000000000..a2405e24d608 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/CondOr0.txt @@ -0,0 +1,21 @@ +PsiJavaFile:CondOr0.java + PsiBinaryExpression:a || b || c + PsiBinaryExpression:a || b + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:OROR('||') + PsiWhiteSpace(' ') + PsiReferenceExpression:b + PsiReferenceParameterList + + PsiIdentifier:b('b') + PsiWhiteSpace(' ') + PsiJavaToken:OROR('||') + PsiWhiteSpace(' ') + PsiReferenceExpression:c + PsiReferenceParameterList + + PsiIdentifier:c('c') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/CondOr1.txt b/java/java-tests/testData/psi/parser-partial/expressions/CondOr1.txt new file mode 100644 index 000000000000..fd17bd9fa03a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/CondOr1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:CondOr1.java + PsiBinaryExpression:a || + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:OROR('||') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList0.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList0.txt new file mode 100644 index 000000000000..19dfe39e0c56 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList0.txt @@ -0,0 +1,14 @@ +PsiJavaFile:ExprList0.java + PsiMethodCallExpression:f(1,2) + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList1.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList1.txt new file mode 100644 index 000000000000..1b2716586119 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:ExprList1.java + PsiMethodCallExpression:f( + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiErrorElement:')' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList2.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList2.txt new file mode 100644 index 000000000000..ac5a13b7d835 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList2.txt @@ -0,0 +1,12 @@ +PsiJavaFile:ExprList2.java + PsiMethodCallExpression:f(1 + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiErrorElement:')' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList3.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList3.txt new file mode 100644 index 000000000000..8ab3cbda9229 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList3.txt @@ -0,0 +1,17 @@ +PsiJavaFile:ExprList3.java + PsiMethodCallExpression:f(1, + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiErrorElement:Expression expected + + PsiExpression(empty) + + PsiErrorElement:')' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList4.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList4.txt new file mode 100644 index 000000000000..0f1d533fe7ca --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList4.txt @@ -0,0 +1,16 @@ +PsiJavaFile:ExprList4.java + PsiMethodCallExpression:f(1,) + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiErrorElement:Expression expected + + PsiExpression(empty) + + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList5.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList5.txt new file mode 100644 index 000000000000..79db76b38550 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList5.txt @@ -0,0 +1,19 @@ +PsiJavaFile:ExprList5.java + PsiMethodCallExpression:f(1,,2) + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiErrorElement:Expression expected + + PsiExpression(empty) + + PsiJavaToken:COMMA(',') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ExprList6.txt b/java/java-tests/testData/psi/parser-partial/expressions/ExprList6.txt new file mode 100644 index 000000000000..4afa08249043 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ExprList6.txt @@ -0,0 +1,16 @@ +PsiJavaFile:ExprList6.java + PsiMethodCallExpression:f(,2) + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiErrorElement:Expression expected + + PsiExpression(empty) + + PsiJavaToken:COMMA(',') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/GE.txt b/java/java-tests/testData/psi/parser-partial/expressions/GE.txt new file mode 100644 index 000000000000..08e3dce501a2 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/GE.txt @@ -0,0 +1,17 @@ +PsiJavaFile:GE.java + PsiAssignmentExpression:x >>>= 8 >> 2 + PsiReferenceExpression:x + PsiReferenceParameterList + + 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') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/IllegalWildcard.txt b/java/java-tests/testData/psi/parser-partial/expressions/IllegalWildcard.txt new file mode 100644 index 000000000000..563280a61046 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/IllegalWildcard.txt @@ -0,0 +1,24 @@ +PsiJavaFile:IllegalWildcard.java + PsiConditionalExpression:this. + PsiKeyword:this('this') + PsiJavaToken:DOT('.') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiErrorElement:Identifier expected + + PsiErrorElement:'>' or ',' expected. + + PsiErrorElement:Identifier expected + + PsiJavaToken:QUEST('?') + PsiErrorElement:Expression expected + + PsiErrorElement:Unparsed tokens + PsiJavaToken:GT('>') + PsiIdentifier:foo('foo') + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/IncompleteCast.txt b/java/java-tests/testData/psi/parser-partial/expressions/IncompleteCast.txt new file mode 100644 index 000000000000..5346de194a8e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/IncompleteCast.txt @@ -0,0 +1,26 @@ +PsiJavaFile:IncompleteCast.java + PsiMethodCallExpression:f((ArrayList) ) + PsiReferenceExpression:f + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiTypeCastExpression:(ArrayList) + PsiJavaToken:LPARENTH('(') + PsiTypeElement:ArrayList + PsiJavaCodeReferenceElement:ArrayList + PsiIdentifier:ArrayList('ArrayList') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiJavaToken:RPARENTH(')') + PsiErrorElement:Expression expected + + PsiWhiteSpace(' ') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf0.txt b/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf0.txt new file mode 100644 index 000000000000..02bbba151d3d --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf0.txt @@ -0,0 +1,14 @@ +PsiJavaFile:InstanceOf0.java + PsiInstanceofExpression:a instanceof String + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiKeyword:instanceof('instanceof') + PsiWhiteSpace(' ') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf1.txt b/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf1.txt new file mode 100644 index 000000000000..42ac3f17063c --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/InstanceOf1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:InstanceOf1.java + PsiInstanceofExpression:a instanceof + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiKeyword:instanceof('instanceof') + PsiErrorElement:Type expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New0.txt b/java/java-tests/testData/psi/parser-partial/expressions/New0.txt new file mode 100644 index 000000000000..cef9e9cb681a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New0.txt @@ -0,0 +1,13 @@ +PsiJavaFile:New0.java + PsiNewExpression:new A() + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New1.txt b/java/java-tests/testData/psi/parser-partial/expressions/New1.txt new file mode 100644 index 000000000000..76aa9b7b6953 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New1.txt @@ -0,0 +1,16 @@ +PsiJavaFile:New1.java + PsiNewExpression:new A[1][] + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New10.txt b/java/java-tests/testData/psi/parser-partial/expressions/New10.txt new file mode 100644 index 000000000000..b7206584e9b9 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New10.txt @@ -0,0 +1,12 @@ +PsiJavaFile:New10.java + PsiNewExpression:new int + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiKeyword:int('int') + PsiErrorElement:'[' expected + + PsiErrorElement:Unparsed tokens + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New11.txt b/java/java-tests/testData/psi/parser-partial/expressions/New11.txt new file mode 100644 index 000000000000..59a4685b1156 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New11.txt @@ -0,0 +1,15 @@ +PsiJavaFile:New11.java + PsiNewExpression:new String[0 + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiErrorElement:']' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New12.txt b/java/java-tests/testData/psi/parser-partial/expressions/New12.txt new file mode 100644 index 000000000000..b0e669acdf98 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New12.txt @@ -0,0 +1,15 @@ +PsiJavaFile:New12.java + PsiNewExpression:new int[1][2] + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiKeyword:int('int') + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') + PsiJavaToken:RBRACKET(']') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New13.txt b/java/java-tests/testData/psi/parser-partial/expressions/New13.txt new file mode 100644 index 000000000000..c00cca26dbbe --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New13.txt @@ -0,0 +1,19 @@ +PsiJavaFile:New13.java + PsiNewExpression:new int[1][][ + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiKeyword:int('int') + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiErrorElement:']' expected + + PsiErrorElement:Unparsed tokens + PsiJavaToken:INTEGER_LITERAL('2') + PsiJavaToken:RBRACKET(']') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New14.txt b/java/java-tests/testData/psi/parser-partial/expressions/New14.txt new file mode 100644 index 000000000000..9761d7930429 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New14.txt @@ -0,0 +1,18 @@ +PsiJavaFile:New14.java + PsiNewExpression:Q.new A() + PsiReferenceExpression:Q + PsiReferenceParameterList + + PsiIdentifier:Q('Q') + PsiJavaToken:DOT('.') + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New2.txt b/java/java-tests/testData/psi/parser-partial/expressions/New2.txt new file mode 100644 index 000000000000..f5b075df64ec --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New2.txt @@ -0,0 +1,14 @@ +PsiJavaFile:New2.java + PsiNewExpression:new A[] + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiErrorElement:Array initializer expected + \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New3.txt b/java/java-tests/testData/psi/parser-partial/expressions/New3.txt new file mode 100644 index 000000000000..e545cdb78495 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New3.txt @@ -0,0 +1,18 @@ +PsiJavaFile:New3.java + PsiNewExpression:new A[][ + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiErrorElement:']' expected + + PsiErrorElement:Unparsed tokens + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:RBRACKET(']') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New4.txt b/java/java-tests/testData/psi/parser-partial/expressions/New4.txt new file mode 100644 index 000000000000..a2ff51e5f8a4 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New4.txt @@ -0,0 +1,19 @@ +PsiJavaFile:New4.java + PsiNewExpression:new A[][]{null} + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiArrayInitializerExpression:{null} + PsiJavaToken:LBRACE('{') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New5.txt b/java/java-tests/testData/psi/parser-partial/expressions/New5.txt new file mode 100644 index 000000000000..3770613b5644 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New5.txt @@ -0,0 +1,18 @@ +PsiJavaFile:New5.java + PsiNewExpression:new A[1] + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:RBRACKET(']') + PsiErrorElement:Unparsed tokens + PsiJavaToken:LBRACE('{') + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RBRACE('}') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New6.txt b/java/java-tests/testData/psi/parser-partial/expressions/New6.txt new file mode 100644 index 000000000000..d767c9089df7 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New6.txt @@ -0,0 +1,7 @@ +PsiJavaFile:New6.java + PsiNewExpression:new + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New7.txt b/java/java-tests/testData/psi/parser-partial/expressions/New7.txt new file mode 100644 index 000000000000..85e4bb39e591 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New7.txt @@ -0,0 +1,12 @@ +PsiJavaFile:New7.java + PsiNewExpression:new A + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiErrorElement:'(' or '[' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New8.txt b/java/java-tests/testData/psi/parser-partial/expressions/New8.txt new file mode 100644 index 000000000000..2a02fd4587b6 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New8.txt @@ -0,0 +1,13 @@ +PsiJavaFile:New8.java + PsiNewExpression:new A[ + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:A + PsiIdentifier:A('A') + PsiReferenceParameterList + + PsiJavaToken:LBRACKET('[') + PsiErrorElement:']' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/New9.txt b/java/java-tests/testData/psi/parser-partial/expressions/New9.txt new file mode 100644 index 000000000000..58ede5bb3fb3 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/New9.txt @@ -0,0 +1,9 @@ +PsiJavaFile:New9.java + PsiNewExpression:new int + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiKeyword:int('int') + PsiErrorElement:'[' expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/NewInExprList.txt b/java/java-tests/testData/psi/parser-partial/expressions/NewInExprList.txt new file mode 100644 index 000000000000..49b9fb676bfb --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/NewInExprList.txt @@ -0,0 +1,15 @@ +PsiJavaFile:NewInExprList.java + PsiMethodCallExpression:call(new) + PsiReferenceExpression:call + PsiReferenceParameterList + + PsiIdentifier:call('call') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiNewExpression:new + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiErrorElement:Identifier expected + + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Not0.txt b/java/java-tests/testData/psi/parser-partial/expressions/Not0.txt new file mode 100644 index 000000000000..6c6b6ca75c0a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Not0.txt @@ -0,0 +1,9 @@ +PsiJavaFile:Not0.java + PsiPrefixExpression:!!a + PsiJavaToken:EXCL('!') + PsiPrefixExpression:!a + PsiJavaToken:EXCL('!') + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Not1.txt b/java/java-tests/testData/psi/parser-partial/expressions/Not1.txt new file mode 100644 index 000000000000..cad5dba7b8f8 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Not1.txt @@ -0,0 +1,5 @@ +PsiJavaFile:Not1.java + PsiPrefixExpression:! + PsiJavaToken:EXCL('!') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Or0.txt b/java/java-tests/testData/psi/parser-partial/expressions/Or0.txt new file mode 100644 index 000000000000..20bd74839bdd --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Or0.txt @@ -0,0 +1,21 @@ +PsiJavaFile:Or0.java + PsiBinaryExpression:a | b | c + PsiBinaryExpression:a | b + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:OR('|') + PsiWhiteSpace(' ') + PsiReferenceExpression:b + PsiReferenceParameterList + + PsiIdentifier:b('b') + PsiWhiteSpace(' ') + PsiJavaToken:OR('|') + PsiWhiteSpace(' ') + PsiReferenceExpression:c + PsiReferenceParameterList + + PsiIdentifier:c('c') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Or1.txt b/java/java-tests/testData/psi/parser-partial/expressions/Or1.txt new file mode 100644 index 000000000000..68894eaa8560 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Or1.txt @@ -0,0 +1,10 @@ +PsiJavaFile:Or1.java + PsiBinaryExpression:a | + PsiReferenceExpression:a + PsiReferenceParameterList + + PsiIdentifier:a('a') + PsiWhiteSpace(' ') + PsiJavaToken:OR('|') + PsiErrorElement:Expression expected + diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Parenth0.txt b/java/java-tests/testData/psi/parser-partial/expressions/Parenth0.txt new file mode 100644 index 000000000000..33befc6c50dc --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Parenth0.txt @@ -0,0 +1,8 @@ +PsiJavaFile:Parenth0.java + PsiParenthesizedExpression:(c) + PsiJavaToken:LPARENTH('(') + PsiReferenceExpression:c + PsiReferenceParameterList + + PsiIdentifier:c('c') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/Parenth1.txt b/java/java-tests/testData/psi/parser-partial/expressions/Parenth1.txt new file mode 100644 index 000000000000..ceefc93b0d70 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/Parenth1.txt @@ -0,0 +1,15 @@ +PsiJavaFile:Parenth1.java + PsiPostfixExpression:(this).f-- + PsiReferenceExpression:(this).f + PsiParenthesizedExpression:(this) + PsiJavaToken:LPARENTH('(') + PsiThisExpression:this + PsiReferenceParameterList + + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiJavaToken:DOT('.') + PsiReferenceParameterList + + PsiIdentifier:f('f') + PsiJavaToken:MINUSMINUS('--') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression0.txt b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression0.txt new file mode 100644 index 000000000000..b824ee1429f6 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression0.txt @@ -0,0 +1,22 @@ +PsiJavaFile:PinesInReferenceExpression0.java + PsiMethodCallExpression:Collections.sort(null) + PsiReferenceExpression:Collections.sort + PsiReferenceExpression:Collections + PsiReferenceParameterList + + PsiIdentifier:Collections('Collections') + PsiJavaToken:DOT('.') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiIdentifier:sort('sort') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression1.txt b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression1.txt new file mode 100644 index 000000000000..5b821fd2d44e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression1.txt @@ -0,0 +1,22 @@ +PsiJavaFile:PinesInReferenceExpression1.java + PsiMethodCallExpression:this.sort(null) + PsiReferenceExpression:this.sort + PsiThisExpression:this + PsiReferenceParameterList + + PsiKeyword:this('this') + PsiJavaToken:DOT('.') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiIdentifier:sort('sort') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/PrimitiveClassObjectAccess.txt b/java/java-tests/testData/psi/parser-partial/expressions/PrimitiveClassObjectAccess.txt new file mode 100644 index 000000000000..d8bdbaffa257 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/PrimitiveClassObjectAccess.txt @@ -0,0 +1,6 @@ +PsiJavaFile:PrimitiveClassObjectAccess.java + PsiClassObjectAccessExpression:int.class + PsiTypeElement:int + PsiKeyword:int('int') + PsiJavaToken:DOT('.') + PsiKeyword:class('class') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt new file mode 100644 index 000000000000..6b22700580b1 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall0.txt @@ -0,0 +1,22 @@ +PsiJavaFile:QualifiedSuperMethodCall0.java + PsiMethodCallExpression:new D().super(0) + PsiReferenceExpression:new D().super + PsiNewExpression:new D() + PsiKeyword:new('new') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:D + PsiIdentifier:D('D') + PsiReferenceParameterList + + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiJavaToken:DOT('.') + PsiKeyword:super('super') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall1.txt b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall1.txt new file mode 100644 index 000000000000..c08eb71cc220 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/QualifiedSuperMethodCall1.txt @@ -0,0 +1,14 @@ +PsiJavaFile:QualifiedSuperMethodCall1.java + PsiMethodCallExpression:d.super(0) + PsiReferenceExpression:d.super + PsiReferenceExpression:d + PsiReferenceParameterList + + PsiIdentifier:d('d') + PsiJavaToken:DOT('.') + PsiKeyword:super('super') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/ShiftRight.txt b/java/java-tests/testData/psi/parser-partial/expressions/ShiftRight.txt new file mode 100644 index 000000000000..86d9fc6857f3 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/ShiftRight.txt @@ -0,0 +1,11 @@ +PsiJavaFile:ShiftRight.java + PsiAssignmentExpression:x >>= 2 + PsiReferenceExpression:x + PsiReferenceParameterList + + PsiIdentifier:x('x') + PsiWhiteSpace(' ') + PsiJavaToken:GTGTEQ('>>=') + PsiWhiteSpace(' ') + PsiLiteralExpression:2 + PsiJavaToken:INTEGER_LITERAL('2') diff --git a/java/java-tests/testData/psi/parser-partial/expressions/SuperMethodCallTypeParameterList.txt b/java/java-tests/testData/psi/parser-partial/expressions/SuperMethodCallTypeParameterList.txt new file mode 100644 index 000000000000..b17a757f1144 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/SuperMethodCallTypeParameterList.txt @@ -0,0 +1,9 @@ +PsiJavaFile:SuperMethodCallTypeParameterList.java + PsiMethodCallExpression:super() + PsiReferenceExpression:super + PsiReferenceParameterList + + PsiKeyword:super('super') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testData/psi/parser-partial/references/Reference0.txt b/java/java-tests/testData/psi/parser-partial/references/Reference0.txt new file mode 100644 index 000000000000..3768b9f7922e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Reference0.txt @@ -0,0 +1,5 @@ +PsiJavaFile:Reference0.java + PsiJavaCodeReferenceElement:a + PsiIdentifier:a('a') + PsiReferenceParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/references/Reference1.txt b/java/java-tests/testData/psi/parser-partial/references/Reference1.txt new file mode 100644 index 000000000000..9e9dbbe0ec86 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Reference1.txt @@ -0,0 +1,9 @@ +PsiJavaFile:Reference1.java + PsiJavaCodeReferenceElement:a. + PsiJavaCodeReferenceElement:a + PsiIdentifier:a('a') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiErrorElement:Identifier expected + diff --git a/java/java-tests/testData/psi/parser-partial/references/Reference2.txt b/java/java-tests/testData/psi/parser-partial/references/Reference2.txt new file mode 100644 index 000000000000..d32c5bc64609 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Reference2.txt @@ -0,0 +1,10 @@ +PsiJavaFile:Reference2.java + PsiJavaCodeReferenceElement:a.b + PsiJavaCodeReferenceElement:a + PsiIdentifier:a('a') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:b('b') + PsiReferenceParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/references/Type0.txt b/java/java-tests/testData/psi/parser-partial/references/Type0.txt new file mode 100644 index 000000000000..a9b9e8bde2ca --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Type0.txt @@ -0,0 +1,3 @@ +PsiJavaFile:Type0.java + PsiTypeElement:int + PsiKeyword:int('int') diff --git a/java/java-tests/testData/psi/parser-partial/references/Type1.txt b/java/java-tests/testData/psi/parser-partial/references/Type1.txt new file mode 100644 index 000000000000..286e9f1dfcc2 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Type1.txt @@ -0,0 +1,11 @@ +PsiJavaFile:Type1.java + PsiTypeElement:a.b + PsiJavaCodeReferenceElement:a.b + PsiJavaCodeReferenceElement:a + PsiIdentifier:a('a') + PsiReferenceParameterList + + PsiJavaToken:DOT('.') + PsiIdentifier:b('b') + PsiReferenceParameterList + diff --git a/java/java-tests/testData/psi/parser-partial/references/Type2.txt b/java/java-tests/testData/psi/parser-partial/references/Type2.txt new file mode 100644 index 000000000000..7234dbb0b59a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Type2.txt @@ -0,0 +1,6 @@ +PsiJavaFile:Type2.java + PsiTypeElement:int[] + PsiTypeElement:int + PsiKeyword:int('int') + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') diff --git a/java/java-tests/testData/psi/parser-partial/references/Type3.txt b/java/java-tests/testData/psi/parser-partial/references/Type3.txt new file mode 100644 index 000000000000..8f4c284f0e5f --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Type3.txt @@ -0,0 +1,9 @@ +PsiJavaFile:Type3.java + PsiTypeElement:int[] + PsiTypeElement:int + PsiKeyword:int('int') + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiJavaToken:LBRACKET('[') + PsiErrorElement:']' expected + diff --git a/java/java-tests/testData/psi/parser-partial/references/Type4.txt b/java/java-tests/testData/psi/parser-partial/references/Type4.txt new file mode 100644 index 000000000000..5159f57cc668 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/Type4.txt @@ -0,0 +1,24 @@ +PsiJavaFile:Type4.java + PsiTypeElement:Map> + PsiJavaCodeReferenceElement:Map> + PsiIdentifier:Map('Map') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:COMMA(',') + PsiTypeElement:List + PsiJavaCodeReferenceElement:List + PsiIdentifier:List('List') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiJavaToken:GT('>') diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams0.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams0.txt new file mode 100644 index 000000000000..508d8cd3fbae --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams0.txt @@ -0,0 +1,8 @@ +PsiJavaFile:TypeParams0.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams1.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams1.txt new file mode 100644 index 000000000000..0dd4209d39f4 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams1.txt @@ -0,0 +1,14 @@ +PsiJavaFile:TypeParams1.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiTypeParameter:U + PsiIdentifier:U('U') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams2.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams2.txt new file mode 100644 index 000000000000..16ac8bead2bf --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams2.txt @@ -0,0 +1,9 @@ +PsiJavaFile:TypeParams2.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiErrorElement:'>' expected. + \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams3.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams3.txt new file mode 100644 index 000000000000..b24e3661f7eb --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams3.txt @@ -0,0 +1,11 @@ +PsiJavaFile:TypeParams3.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected identifier + PsiIdentifier:hack('hack') + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams4.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams4.txt new file mode 100644 index 000000000000..3f60da4b3fcb --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams4.txt @@ -0,0 +1,12 @@ +PsiJavaFile:TypeParams4.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiErrorElement:'>' expected. + + PsiWhiteSpace(' ') + PsiErrorElement:Unparsed tokens + PsiIdentifier:hack('hack') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams5.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams5.txt new file mode 100644 index 000000000000..51d776e6a39e --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams5.txt @@ -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 + + PsiWhiteSpace(' ') + PsiJavaToken:AND('&') + PsiWhiteSpace(' ') + PsiJavaCodeReferenceElement:Y + PsiIdentifier:Y('Y') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:Z + PsiJavaCodeReferenceElement:Z + PsiIdentifier:Z('Z') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams6.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams6.txt new file mode 100644 index 000000000000..a5b46b98efd0 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams6.txt @@ -0,0 +1,15 @@ +PsiJavaFile:TypeParams6.java + PsiTypeParameterList + PsiJavaToken:LT('<') + PsiTypeParameter:T + PsiIdentifier:T('T') + PsiElement(EXTENDS_BOUND_LIST) + + PsiErrorElement:'>' expected. + + PsiWhiteSpace(' ') + PsiErrorElement:Unparsed tokens + PsiIdentifier:supers('supers') + PsiWhiteSpace(' ') + PsiIdentifier:X('X') + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/TypeParams7.txt b/java/java-tests/testData/psi/parser-partial/references/TypeParams7.txt new file mode 100644 index 000000000000..f3cf0196d19a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/TypeParams7.txt @@ -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 + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiTypeParameter:Y + PsiIdentifier:Y('Y') + PsiElement(EXTENDS_BOUND_LIST) + + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/JavaTestUtil.java b/java/java-tests/testSrc/com/intellij/JavaTestUtil.java index daf0b57289d8..7e9c239d60ab 100644 --- a/java/java-tests/testSrc/com/intellij/JavaTestUtil.java +++ b/java/java-tests/testSrc/com/intellij/JavaTestUtil.java @@ -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; + } } diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/JavaParsingTestCase.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/JavaParsingTestCase.java new file mode 100644 index 000000000000..15874f8244e2 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/JavaParsingTestCase.java @@ -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); + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java new file mode 100644 index 000000000000..f5dcb83f898c --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java @@ -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"); } + 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); + } + }); + } +} diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java new file mode 100644 index 000000000000..340c962ad87b --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java @@ -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.sort(null)"); } + public void testPinesInReferenceExpression1() { doParserTest("this.sort(null)"); } + + public void testGE() { doParserTest("x >>>= 8 >> 2"); } + + public void testIncompleteCast() { doParserTest("f((ArrayList) )"); } + 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); + } + }); + } +} diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java new file mode 100644 index 000000000000..da5651bf4eb9 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java @@ -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>", false); } + + public void testTypeParams0() { doTypeParamsParserTest(""); } + public void testTypeParams1() { doTypeParamsParserTest(""); } + public void testTypeParams2() { doTypeParamsParserTest(""); } + public void testTypeParams4() { doTypeParamsParserTest(">"); } + public void testTypeParams6() { doTypeParamsParserTest(""); } + public void testTypeParams7() { doTypeParamsParserTest(""); } + + 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); + } + }); + } +} diff --git a/java/openapi/src/com/intellij/psi/tree/java/IJavaElementType.java b/java/openapi/src/com/intellij/psi/tree/java/IJavaElementType.java index 7e2f0277cd7a..54e9d45167fb 100644 --- a/java/openapi/src/com/intellij/psi/tree/java/IJavaElementType.java +++ b/java/openapi/src/com/intellij/psi/tree/java/IJavaElementType.java @@ -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; } } \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/lang/PsiBuilderUtil.java b/platform/lang-api/src/com/intellij/lang/PsiBuilderUtil.java new file mode 100644 index 000000000000..279d061aee73 --- /dev/null +++ b/platform/lang-api/src/com/intellij/lang/PsiBuilderUtil.java @@ -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>() { + @Override + public List compute() { + return asFileList(myDataProxy.getElements()); + } + }); } return null; } @Nullable private String getDataAsText() { - List names = new ArrayList(); - for (PsiElement element : myDataProxy.getElements()) { - if (element instanceof PsiNamedElement) { - String name = ((PsiNamedElement) element).getName(); - if (name != null) { - names.add(name); + final List names = new ArrayList(); + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + for (PsiElement element : myDataProxy.getElements()) { + if (element instanceof PsiNamedElement) { + String name = ((PsiNamedElement) element).getName(); + if (name != null) { + names.add(name); + } + } } } - } + }); if (names.isEmpty()) { return null; } diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java index 38d26627d5e8..e7d9109ff31e 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateUtil.java @@ -29,6 +29,8 @@ import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.ClassLoaderUtil; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; @@ -232,6 +234,14 @@ public class FileTemplateUtil{ @NonNls @Nullable final String fileName, @Nullable Properties props, @NotNull final PsiDirectory directory) throws Exception { + return createFromTemplate(template, fileName, props, directory, null); + } + + public static PsiElement createFromTemplate(@NotNull final FileTemplate template, + @NonNls @Nullable final String fileName, + @Nullable Properties props, + @NotNull final PsiDirectory directory, + @Nullable ClassLoader classLoader) throws Exception { @NotNull final Project project = directory.getProject(); if (props == null) { props = FileTemplateManager.getInstance().getDefaultProperties(); @@ -256,7 +266,15 @@ public class FileTemplateUtil{ props.setProperty(FileTemplate.ATTRIBUTE_PACKAGE_NAME, FileTemplate.ATTRIBUTE_PACKAGE_NAME); } } - String mergedText = template.getText(props); + + final Properties props_ = props; + String mergedText = ClassLoaderUtil.runWithClassLoader(classLoader != null ? classLoader : FileTemplateUtil.class.getClassLoader(), + new ThrowableComputable() { + @Override + public String compute() throws IOException { + return template.getText(props_); + } + }); final String templateText = StringUtil.convertLineSeparators(mergedText); final Exception[] commandException = new Exception[1]; final PsiElement[] result = new PsiElement[1]; diff --git a/platform/util/src/com/intellij/openapi/util/ClassLoaderUtil.java b/platform/util/src/com/intellij/openapi/util/ClassLoaderUtil.java new file mode 100644 index 000000000000..73166f80a213 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/ClassLoaderUtil.java @@ -0,0 +1,69 @@ +/* + * 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.openapi.util; + +import com.intellij.util.ThrowableRunnable; + +public class ClassLoaderUtil { + private ClassLoaderUtil() { + } + + public static void runWithClassLoader(final ClassLoader classLoader, final Runnable runnable) { + final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + runnable.run(); + } + finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + + public static T runWithClassLoader(final ClassLoader classLoader, final Computable computable) { + final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + return computable.compute(); + } + finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + + public static void runWithClassLoader(final ClassLoader classLoader, final ThrowableRunnable runnable) + throws E { + final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + runnable.run(); + } + finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + + public static T runWithClassLoader(final ClassLoader classLoader, final ThrowableComputable computable) + throws E { + final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + return computable.compute(); + } + finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } +} diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java index 2d1f11c38d73..32d44782ca7f 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlFoldingBuilder.java @@ -66,17 +66,7 @@ public class XmlFoldingBuilder implements FoldingBuilder, DumbAware { if (rootTag != null) { foldings = new ArrayList(); - if (rootTag instanceof XmlTag) { - addElementsToFold(foldings, rootTag, document); - - // HTML tags in JSP - for (PsiElement sibling = rootTag.getNextSibling(); sibling != null; sibling = sibling.getNextSibling()) { - if (sibling instanceof XmlTag) addElementsToFold(foldings, (XmlElement)sibling, document); - } - } - else { - doAddForChildren(xmlDocument, foldings, document); - } + doAddForChildren(xmlDocument, foldings, document); } return foldings != null ? foldings.toArray(new FoldingDescriptor[foldings.size()]):FoldingDescriptor.EMPTY; @@ -100,7 +90,7 @@ public class XmlFoldingBuilder implements FoldingBuilder, DumbAware { else if (child instanceof XmlComment) { addToFold(foldings, child, document); } - else if (child instanceof XmlText) { + else if (child instanceof XmlText || child instanceof XmlProlog) { final PsiElement[] grandChildren = child.getChildren(); for (PsiElement grandChild : grandChildren) {