| /* |
| * Copyright 2000-2014 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.psi.impl.source.tree; |
| |
| import com.intellij.lang.*; |
| import com.intellij.lang.java.JavaLanguage; |
| import com.intellij.lang.java.JavaParserDefinition; |
| import com.intellij.lang.java.parser.JavaParser; |
| import com.intellij.lang.java.parser.JavaParserUtil; |
| import com.intellij.lang.java.parser.ReferenceParser; |
| import com.intellij.lexer.Lexer; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.pom.java.LanguageLevel; |
| import com.intellij.psi.JavaTokenType; |
| import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; |
| import com.intellij.psi.impl.source.*; |
| import com.intellij.psi.impl.source.tree.java.*; |
| import com.intellij.psi.tree.*; |
| import com.intellij.psi.tree.java.IJavaElementType; |
| import com.intellij.util.ReflectionUtil; |
| import com.intellij.util.diff.FlyweightCapableTreeStructure; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| import sun.reflect.ConstructorAccessor; |
| |
| import java.lang.reflect.Constructor; |
| |
| public interface JavaElementType { |
| class JavaCompositeElementType extends IJavaElementType implements ICompositeElementType { |
| private final ConstructorAccessor myConstructor; |
| |
| private JavaCompositeElementType(@NonNls final String debugName, final Class<? extends ASTNode> nodeClass) { |
| this(debugName, nodeClass, false); |
| } |
| |
| private JavaCompositeElementType(@NonNls final String debugName, final Class<? extends ASTNode> nodeClass, final boolean leftBound) { |
| super(debugName, leftBound); |
| Constructor<? extends ASTNode> constructor = ReflectionUtil.getDefaultConstructor(nodeClass); |
| myConstructor = ReflectionUtil.getConstructorAccessor(constructor); |
| } |
| |
| @NotNull |
| @Override |
| public ASTNode createCompositeNode() { |
| return ReflectionUtil.createInstanceViaConstructorAccessor(myConstructor); |
| } |
| } |
| |
| IElementType CLASS = JavaStubElementTypes.CLASS; |
| IElementType ANONYMOUS_CLASS = JavaStubElementTypes.ANONYMOUS_CLASS; |
| IElementType ENUM_CONSTANT_INITIALIZER = JavaStubElementTypes.ENUM_CONSTANT_INITIALIZER; |
| IElementType TYPE_PARAMETER_LIST = JavaStubElementTypes.TYPE_PARAMETER_LIST; |
| IElementType TYPE_PARAMETER = JavaStubElementTypes.TYPE_PARAMETER; |
| IElementType IMPORT_LIST = JavaStubElementTypes.IMPORT_LIST; |
| IElementType IMPORT_STATEMENT = JavaStubElementTypes.IMPORT_STATEMENT; |
| IElementType IMPORT_STATIC_STATEMENT = JavaStubElementTypes.IMPORT_STATIC_STATEMENT; |
| IElementType MODIFIER_LIST = JavaStubElementTypes.MODIFIER_LIST; |
| IElementType ANNOTATION = JavaStubElementTypes.ANNOTATION; |
| IElementType NAME_VALUE_PAIR = JavaStubElementTypes.NAME_VALUE_PAIR; |
| IElementType ANNOTATION_PARAMETER_LIST = JavaStubElementTypes.ANNOTATION_PARAMETER_LIST; |
| IElementType EXTENDS_LIST = JavaStubElementTypes.EXTENDS_LIST; |
| IElementType IMPLEMENTS_LIST = JavaStubElementTypes.IMPLEMENTS_LIST; |
| IElementType FIELD = JavaStubElementTypes.FIELD; |
| IElementType ENUM_CONSTANT = JavaStubElementTypes.ENUM_CONSTANT; |
| IElementType METHOD = JavaStubElementTypes.METHOD; |
| IElementType ANNOTATION_METHOD = JavaStubElementTypes.ANNOTATION_METHOD; |
| IElementType CLASS_INITIALIZER = JavaStubElementTypes.CLASS_INITIALIZER; |
| IElementType PARAMETER = JavaStubElementTypes.PARAMETER; |
| IElementType RECEIVER_PARAMETER = JavaStubElementTypes.RECEIVER_PARAMETER; |
| IElementType PARAMETER_LIST = JavaStubElementTypes.PARAMETER_LIST; |
| IElementType EXTENDS_BOUND_LIST = JavaStubElementTypes.EXTENDS_BOUND_LIST; |
| IElementType THROWS_LIST = JavaStubElementTypes.THROWS_LIST; |
| |
| IElementType LITERAL_EXPRESSION = new JavaCompositeElementType("LITERAL_EXPRESSION", PsiLiteralExpressionImpl.class); |
| IElementType IMPORT_STATIC_REFERENCE = new JavaCompositeElementType("IMPORT_STATIC_REFERENCE", PsiImportStaticReferenceElementImpl.class); |
| IElementType TYPE = new JavaCompositeElementType("TYPE", PsiTypeElementImpl.class); |
| IElementType DIAMOND_TYPE = new JavaCompositeElementType("DIAMOND_TYPE", PsiDiamondTypeElementImpl.class); |
| IElementType REFERENCE_PARAMETER_LIST = new JavaCompositeElementType("REFERENCE_PARAMETER_LIST", PsiReferenceParameterListImpl.class, true); |
| IElementType JAVA_CODE_REFERENCE = new JavaCompositeElementType("JAVA_CODE_REFERENCE", PsiJavaCodeReferenceElementImpl.class); |
| IElementType PACKAGE_STATEMENT = new JavaCompositeElementType("PACKAGE_STATEMENT", PsiPackageStatementImpl.class); |
| IElementType LOCAL_VARIABLE = new JavaCompositeElementType("LOCAL_VARIABLE", PsiLocalVariableImpl.class); |
| IElementType REFERENCE_EXPRESSION = new JavaCompositeElementType("REFERENCE_EXPRESSION", PsiReferenceExpressionImpl.class); |
| IElementType THIS_EXPRESSION = new JavaCompositeElementType("THIS_EXPRESSION", PsiThisExpressionImpl.class); |
| IElementType SUPER_EXPRESSION = new JavaCompositeElementType("SUPER_EXPRESSION", PsiSuperExpressionImpl.class); |
| IElementType PARENTH_EXPRESSION = new JavaCompositeElementType("PARENTH_EXPRESSION", PsiParenthesizedExpressionImpl.class); |
| IElementType METHOD_CALL_EXPRESSION = new JavaCompositeElementType("METHOD_CALL_EXPRESSION", PsiMethodCallExpressionImpl.class); |
| IElementType TYPE_CAST_EXPRESSION = new JavaCompositeElementType("TYPE_CAST_EXPRESSION", PsiTypeCastExpressionImpl.class); |
| IElementType PREFIX_EXPRESSION = new JavaCompositeElementType("PREFIX_EXPRESSION", PsiPrefixExpressionImpl.class); |
| IElementType POSTFIX_EXPRESSION = new JavaCompositeElementType("POSTFIX_EXPRESSION", PsiPostfixExpressionImpl.class); |
| IElementType BINARY_EXPRESSION = new JavaCompositeElementType("BINARY_EXPRESSION", PsiBinaryExpressionImpl.class); |
| IElementType POLYADIC_EXPRESSION = new JavaCompositeElementType("POLYADIC_EXPRESSION", PsiPolyadicExpressionImpl.class); |
| IElementType CONDITIONAL_EXPRESSION = new JavaCompositeElementType("CONDITIONAL_EXPRESSION", PsiConditionalExpressionImpl.class); |
| IElementType ASSIGNMENT_EXPRESSION = new JavaCompositeElementType("ASSIGNMENT_EXPRESSION", PsiAssignmentExpressionImpl.class); |
| IElementType NEW_EXPRESSION = new JavaCompositeElementType("NEW_EXPRESSION", PsiNewExpressionImpl.class); |
| IElementType ARRAY_ACCESS_EXPRESSION = new JavaCompositeElementType("ARRAY_ACCESS_EXPRESSION", PsiArrayAccessExpressionImpl.class); |
| IElementType ARRAY_INITIALIZER_EXPRESSION = new JavaCompositeElementType("ARRAY_INITIALIZER_EXPRESSION", PsiArrayInitializerExpressionImpl.class); |
| IElementType INSTANCE_OF_EXPRESSION = new JavaCompositeElementType("INSTANCE_OF_EXPRESSION", PsiInstanceOfExpressionImpl.class); |
| IElementType CLASS_OBJECT_ACCESS_EXPRESSION = new JavaCompositeElementType("CLASS_OBJECT_ACCESS_EXPRESSION", PsiClassObjectAccessExpressionImpl.class); |
| IElementType EMPTY_EXPRESSION = new JavaCompositeElementType("EMPTY_EXPRESSION", PsiEmptyExpressionImpl.class, true); |
| IElementType METHOD_REF_EXPRESSION = new JavaCompositeElementType("METHOD_REF_EXPRESSION", PsiMethodReferenceExpressionImpl.class); |
| IElementType LAMBDA_EXPRESSION = new JavaCompositeElementType("LAMBDA_EXPRESSION", PsiLambdaExpressionImpl.class); |
| IElementType EXPRESSION_LIST = new JavaCompositeElementType("EXPRESSION_LIST", PsiExpressionListImpl.class, true); |
| IElementType EMPTY_STATEMENT = new JavaCompositeElementType("EMPTY_STATEMENT", PsiEmptyStatementImpl.class); |
| IElementType BLOCK_STATEMENT = new JavaCompositeElementType("BLOCK_STATEMENT", PsiBlockStatementImpl.class); |
| IElementType EXPRESSION_STATEMENT = new JavaCompositeElementType("EXPRESSION_STATEMENT", PsiExpressionStatementImpl.class); |
| IElementType EXPRESSION_LIST_STATEMENT = new JavaCompositeElementType("EXPRESSION_LIST_STATEMENT", PsiExpressionListStatementImpl.class); |
| IElementType DECLARATION_STATEMENT = new JavaCompositeElementType("DECLARATION_STATEMENT", PsiDeclarationStatementImpl.class); |
| IElementType IF_STATEMENT = new JavaCompositeElementType("IF_STATEMENT", PsiIfStatementImpl.class); |
| IElementType WHILE_STATEMENT = new JavaCompositeElementType("WHILE_STATEMENT", PsiWhileStatementImpl.class); |
| IElementType FOR_STATEMENT = new JavaCompositeElementType("FOR_STATEMENT", PsiForStatementImpl.class); |
| IElementType FOREACH_STATEMENT = new JavaCompositeElementType("FOREACH_STATEMENT", PsiForeachStatementImpl.class); |
| IElementType DO_WHILE_STATEMENT = new JavaCompositeElementType("DO_WHILE_STATEMENT", PsiDoWhileStatementImpl.class); |
| IElementType SWITCH_STATEMENT = new JavaCompositeElementType("SWITCH_STATEMENT", PsiSwitchStatementImpl.class); |
| IElementType SWITCH_LABEL_STATEMENT = new JavaCompositeElementType("SWITCH_LABEL_STATEMENT", PsiSwitchLabelStatementImpl.class); |
| IElementType BREAK_STATEMENT = new JavaCompositeElementType("BREAK_STATEMENT", PsiBreakStatementImpl.class); |
| IElementType CONTINUE_STATEMENT = new JavaCompositeElementType("CONTINUE_STATEMENT", PsiContinueStatementImpl.class); |
| IElementType RETURN_STATEMENT = new JavaCompositeElementType("RETURN_STATEMENT", PsiReturnStatementImpl.class); |
| IElementType THROW_STATEMENT = new JavaCompositeElementType("THROW_STATEMENT", PsiThrowStatementImpl.class); |
| IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class); |
| IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class); |
| IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class); |
| IElementType RESOURCE_VARIABLE = new JavaCompositeElementType("RESOURCE_VARIABLE", PsiResourceVariableImpl.class); |
| IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); |
| IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class); |
| IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class); |
| IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class); |
| |
| class ICodeBlockElementType extends IErrorCounterReparseableElementType implements ICompositeElementType, ILightLazyParseableElementType { |
| private ICodeBlockElementType() { |
| super("CODE_BLOCK", JavaLanguage.INSTANCE); |
| } |
| |
| @Override |
| public ASTNode createNode(final CharSequence text) { |
| return new PsiCodeBlockImpl(text); |
| } |
| |
| @NotNull |
| @Override |
| public ASTNode createCompositeNode() { |
| return new PsiCodeBlockImpl(null); |
| } |
| |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon); |
| JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true); |
| return builder.getTreeBuilt().getFirstChildNode(); |
| } |
| |
| @Override |
| public FlyweightCapableTreeStructure<LighterASTNode> parseContents(final LighterLazyParseableNode chameleon) { |
| final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon); |
| JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true); |
| return builder.getLightTree(); |
| } |
| |
| @Override |
| public int getErrorsCount(final CharSequence seq, Language fileLanguage, final Project project) { |
| Lexer lexer = JavaParserDefinition.createLexer(LanguageLevel.HIGHEST); |
| |
| lexer.start(seq); |
| if (lexer.getTokenType() != JavaTokenType.LBRACE) return IErrorCounterReparseableElementType.FATAL_ERROR; |
| lexer.advance(); |
| int balance = 1; |
| while (true) { |
| IElementType type = lexer.getTokenType(); |
| if (type == null) break; |
| if (balance == 0) return IErrorCounterReparseableElementType.FATAL_ERROR; |
| if (type == JavaTokenType.LBRACE) { |
| balance++; |
| } |
| else if (type == JavaTokenType.RBRACE) { |
| balance--; |
| } |
| lexer.advance(); |
| } |
| return balance; |
| } |
| } |
| ILazyParseableElementType CODE_BLOCK = new ICodeBlockElementType(); |
| |
| IElementType STATEMENTS = new ICodeFragmentElementType("STATEMENTS", JavaLanguage.INSTANCE) { |
| private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { |
| @Override |
| public void parse(final PsiBuilder builder) { |
| JavaParser.INSTANCE.getStatementParser().parseStatements(builder); |
| } |
| }; |
| |
| @Nullable |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| return JavaParserUtil.parseFragment(chameleon, myParser); |
| } |
| }; |
| |
| IElementType EXPRESSION_TEXT = new ICodeFragmentElementType("EXPRESSION_TEXT", JavaLanguage.INSTANCE) { |
| private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { |
| @Override |
| public void parse(final PsiBuilder builder) { |
| JavaParser.INSTANCE.getExpressionParser().parse(builder); |
| } |
| }; |
| |
| @Nullable |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| return JavaParserUtil.parseFragment(chameleon, myParser); |
| } |
| }; |
| |
| IElementType REFERENCE_TEXT = new ICodeFragmentElementType("REFERENCE_TEXT", JavaLanguage.INSTANCE) { |
| private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { |
| @Override |
| public void parse(final PsiBuilder builder) { |
| JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, false, true, false, false); |
| } |
| }; |
| |
| @Nullable |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| return JavaParserUtil.parseFragment(chameleon, myParser); |
| } |
| }; |
| |
| IElementType TYPE_TEXT = new ICodeFragmentElementType("TYPE_TEXT", JavaLanguage.INSTANCE) { |
| private final JavaParserUtil.ParserWrapper myParser = new JavaParserUtil.ParserWrapper() { |
| @Override |
| public void parse(final PsiBuilder builder) { |
| JavaParser.INSTANCE.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.ELLIPSIS | |
| ReferenceParser.WILDCARD | ReferenceParser.DISJUNCTIONS); |
| } |
| }; |
| |
| @Nullable |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| return JavaParserUtil.parseFragment(chameleon, myParser); |
| } |
| }; |
| |
| class JavaDummyElementType extends ILazyParseableElementType implements ICompositeElementType { |
| private JavaDummyElementType() { |
| super("DUMMY_ELEMENT", JavaLanguage.INSTANCE); |
| } |
| |
| @NotNull |
| @Override |
| public ASTNode createCompositeNode() { |
| return new CompositePsiElement(this) { }; |
| } |
| |
| @Nullable |
| @Override |
| public ASTNode parseContents(final ASTNode chameleon) { |
| assert chameleon instanceof JavaDummyElement : chameleon; |
| final JavaDummyElement dummyElement = (JavaDummyElement)chameleon; |
| return JavaParserUtil.parseFragment(chameleon, dummyElement.getParser(), dummyElement.consumeAll(), dummyElement.getLanguageLevel()); |
| } |
| } |
| IElementType DUMMY_ELEMENT = new JavaDummyElementType(); |
| } |