diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-04-01 14:41:51 -0700 |
commit | 2bd2b7c2623d4266384e890271869efc044aabff (patch) | |
tree | 0b31f50e55975b6354ed458314e17b4441bb4e17 /java/java-psi-impl/src/com | |
parent | 1d526b16d476792ca7ce47616d55833115e8d6ab (diff) | |
download | idea-2bd2b7c2623d4266384e890271869efc044aabff.tar.gz |
Snapshot ee98b298267d0e09d2cd2f0731b6480a56dd48e7 from master branch of git://git.jetbrains.org/idea/community.git
Change-Id: I4515f72af131fdea9fc6905a4dc0fe9532409a81
Diffstat (limited to 'java/java-psi-impl/src/com')
41 files changed, 756 insertions, 771 deletions
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java index 4d96915af333..4b244364416f 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java @@ -298,28 +298,9 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations MostlySingularMultiMap<String, AnnotationData> fileData = getDataFromFile(file); - Collection<AnnotationData> data = (Collection<AnnotationData>)fileData.get(externalName); - for (AnnotationData ad : data) { - if (result.contains(ad)) { - // there can be compatible annotations in different files - if (Comparing.equal(ad.virtualFile, file.getVirtualFile())) { - LOG.error("Duplicate signature:\n" + externalName + "; in " + file); - } - } - else { - result.add(ad); - } - } + addAnnotations(result, externalName, file, fileData); if (oldExternalName != null && !externalName.equals(oldExternalName)) { - Collection<AnnotationData> oldCollection = (Collection<AnnotationData>)fileData.get(oldExternalName); - for (AnnotationData ad : oldCollection) { - if (result.contains(ad)) { - LOG.error("Duplicate signature o:\n" + oldExternalName + "; in " + toVirtualFiles(files)); - } - else { - result.add(ad); - } - } + addAnnotations(result, oldExternalName, file, fileData); } } if (result.isEmpty()) { @@ -329,13 +310,22 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations return result; } - static List<VirtualFile> toVirtualFiles(List<PsiFile> files) { - return ContainerUtil.map(files, new Function<PsiFile, VirtualFile>() { - @Override - public VirtualFile fun(PsiFile file) { - return file.getVirtualFile(); + private static void addAnnotations(@NotNull List<AnnotationData> result, + @NotNull String externalName, + @NotNull PsiFile file, + @NotNull MostlySingularMultiMap<String, AnnotationData> fileData) { + Iterable<AnnotationData> data = fileData.get(externalName); + for (AnnotationData ad : data) { + if (result.contains(ad)) { + // there can be compatible annotations in different files + if (Comparing.equal(ad.virtualFile, file.getVirtualFile())) { + LOG.error("Duplicate signature: '" + externalName + "'; in " + file.getVirtualFile()); + } } - }); + else { + result.add(ad); + } + } } @Override diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java index f78ee83b570a..1aa0ac222946 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -25,6 +25,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.NullableFunction; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -421,21 +422,20 @@ public class ExceptionUtil { } @NotNull - public static List<PsiClassType> getUnhandledExceptions(final PsiThrowStatement throwStatement, @Nullable final PsiElement topElement) { - final PsiExpression exception = throwStatement.getException(); - final List<PsiType> types = getPreciseThrowTypes(exception); - return ContainerUtil.mapNotNull(types, new NullableFunction<PsiType, PsiClassType>() { - @Override - public PsiClassType fun(PsiType type) { - if (type instanceof PsiClassType) { - final PsiClassType classType = (PsiClassType)type; + public static List<PsiClassType> getUnhandledExceptions(PsiThrowStatement throwStatement, @Nullable PsiElement topElement) { + List<PsiClassType> unhandled = new SmartList<PsiClassType>(); + for (PsiType type : getPreciseThrowTypes(throwStatement.getException())) { + List<PsiType> types = type instanceof PsiDisjunctionType ? ((PsiDisjunctionType)type).getDisjunctions() : Collections.singletonList(type); + for (PsiType subType : types) { + if (subType instanceof PsiClassType) { + PsiClassType classType = (PsiClassType)subType; if (!isUncheckedException(classType) && !isHandled(throwStatement, classType, topElement)) { - return classType; + unhandled.add(classType); } } - return null; } - }); + } + return unhandled; } @NotNull diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java index 35e24fa88bd2..52e9ab691092 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java @@ -4,6 +4,7 @@ import com.intellij.codeInsight.MemberImplementorExplorer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.util.MethodSignature; @@ -63,9 +64,9 @@ public class OverrideImplementExploreUtil { } Map<MethodSignature, PsiMethod> map = hisClass.isInterface() || method.hasModifierProperty(PsiModifier.ABSTRACT) ? abstracts : concretes; - PsiMethod other = map.get(signature); - if (other == null || preferLeftForImplement(method, other)) { - map.put(signature, method); + fillMap(signature, method, map); + if (isDefaultMethod(aClass, method)) { + fillMap(signature, method, concretes); } } @@ -92,6 +93,18 @@ public class OverrideImplementExploreUtil { return result; } + private static boolean isDefaultMethod(PsiClass aClass, PsiMethod method) { + return method.hasModifierProperty(PsiModifier.DEFAULT) && + PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8); + } + + private static void fillMap(HierarchicalMethodSignature signature, PsiMethod method, Map<MethodSignature, PsiMethod> map) { + final PsiMethod other = map.get(signature); + if (other == null || preferLeftForImplement(method, other)) { + map.put(signature, method); + } + } + public static void collectMethodsToImplement(PsiClass aClass, Map<MethodSignature, PsiMethod> abstracts, Map<MethodSignature, PsiMethod> finals, @@ -103,7 +116,8 @@ public class OverrideImplementExploreUtil { PsiMethod concrete = concretes.get(signature); if (concrete == null || PsiUtil.getAccessLevel(concrete.getModifierList()) < PsiUtil.getAccessLevel(abstractOne.getModifierList()) - || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true)) { + || !abstractOne.getContainingClass().isInterface() && abstractOne.getContainingClass().isInheritor(concrete.getContainingClass(), true) + || isDefaultMethod(aClass, abstractOne)) { if (finals.get(signature) == null) { PsiSubstitutor subst = correctSubstitutor(abstractOne, signature.getSubstitutor()); CandidateInfo info = new CandidateInfo(abstractOne, subst); diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 8722c92feb8e..54e23dd156b3 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -402,29 +402,26 @@ public class DeclarationParser { return Pair.create(modList, isEmpty); } - private PsiBuilder.Marker parseMethodFromLeftParenth(final PsiBuilder builder, final PsiBuilder.Marker declaration, - final boolean anno, final boolean constructor) { + private PsiBuilder.Marker parseMethodFromLeftParenth(PsiBuilder builder, PsiBuilder.Marker declaration, boolean anno, boolean constructor) { parseParameterList(builder); - eatBrackets(builder, constructor, "expected.semicolon"); + eatBrackets(builder, constructor ? "expected.semicolon" : null); myParser.getReferenceParser().parseReferenceList(builder, JavaTokenType.THROWS_KEYWORD, JavaElementType.THROWS_LIST, JavaTokenType.COMMA); - final boolean hasDefault = expect(builder, JavaTokenType.DEFAULT_KEYWORD); - if (hasDefault && anno) { + if (anno && expect(builder, JavaTokenType.DEFAULT_KEYWORD)) { parseAnnotationValue(builder); } - final IElementType tokenType = builder.getTokenType(); - final boolean hasError = tokenType != JavaTokenType.SEMICOLON && tokenType != JavaTokenType.LBRACE; - if (hasError) { - final PsiBuilder.Marker error = builder.mark(); + IElementType tokenType = builder.getTokenType(); + if (tokenType != JavaTokenType.SEMICOLON && tokenType != JavaTokenType.LBRACE) { + PsiBuilder.Marker error = builder.mark(); // heuristic: going to next line obviously means method signature is over, starting new method (actually, another one completion hack) - final CharSequence text = builder.getOriginalText(); + CharSequence text = builder.getOriginalText(); Loop: while (true) { for (int i = builder.getCurrentOffset() - 1; i >= 0; i--) { - final char ch = text.charAt(i); + char ch = text.charAt(i); if (ch == '\n') break Loop; else if (ch != ' ' && ch != '\t') break; } @@ -433,11 +430,10 @@ public class DeclarationParser { error.error(JavaErrorMessages.message("expected.lbrace.or.semicolon")); } - if (hasDefault && !anno && !hasError && builder.getTokenType() != JavaTokenType.LBRACE) { - error(builder, JavaErrorMessages.message("expected.lbrace")); - } - if (!expect(builder, JavaTokenType.SEMICOLON) && builder.getTokenType() == JavaTokenType.LBRACE) { - myParser.getStatementParser().parseCodeBlock(builder); + if (!expect(builder, JavaTokenType.SEMICOLON)) { + if (builder.getTokenType() == JavaTokenType.LBRACE) { + myParser.getStatementParser().parseCodeBlock(builder); + } } done(declaration, anno ? JavaElementType.ANNOTATION_METHOD : JavaElementType.METHOD); @@ -445,24 +441,24 @@ public class DeclarationParser { } @NotNull - public PsiBuilder.Marker parseParameterList(final PsiBuilder builder) { - return parseElementList(builder, ListType.NORMAL); + public PsiBuilder.Marker parseParameterList(PsiBuilder builder) { + return parseElementList(builder, ListType.METHOD); } @NotNull - public PsiBuilder.Marker parseResourceList(final PsiBuilder builder) { + public PsiBuilder.Marker parseResourceList(PsiBuilder builder) { return parseElementList(builder, ListType.RESOURCE); } @NotNull - public PsiBuilder.Marker parseLambdaParameterList(final PsiBuilder builder, final boolean typed) { + public PsiBuilder.Marker parseLambdaParameterList(PsiBuilder builder, boolean typed) { return parseElementList(builder, typed ? ListType.LAMBDA_TYPED : ListType.LAMBDA_UNTYPED); } - private enum ListType { NORMAL, RESOURCE, LAMBDA_TYPED, LAMBDA_UNTYPED } + private enum ListType {METHOD, RESOURCE, LAMBDA_TYPED, LAMBDA_UNTYPED} @NotNull - private PsiBuilder.Marker parseElementList(final PsiBuilder builder, final ListType type) { + private PsiBuilder.Marker parseElementList(PsiBuilder builder, ListType type) { final boolean lambda = (type == ListType.LAMBDA_TYPED || type == ListType.LAMBDA_UNTYPED); final boolean resources = (type == ListType.RESOURCE); final PsiBuilder.Marker elementList = builder.mark(); @@ -563,29 +559,25 @@ public class DeclarationParser { } @Nullable - public PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) { + public PsiBuilder.Marker parseParameter(PsiBuilder builder, boolean ellipsis, boolean disjunctiveType) { return parseListElement(builder, true, ellipsis, disjunctiveType, false); } @Nullable - public PsiBuilder.Marker parseResource(final PsiBuilder builder) { + public PsiBuilder.Marker parseResource(PsiBuilder builder) { return parseListElement(builder, true, false, false, true); } @Nullable - public PsiBuilder.Marker parseLambdaParameter(final PsiBuilder builder, final boolean typed) { + public PsiBuilder.Marker parseLambdaParameter(PsiBuilder builder, boolean typed) { return parseListElement(builder, typed, true, false, false); } @Nullable - private PsiBuilder.Marker parseListElement(final PsiBuilder builder, - final boolean typed, - final boolean ellipsis, - final boolean disjunctiveType, - final boolean resource) { - final PsiBuilder.Marker param = builder.mark(); + private PsiBuilder.Marker parseListElement(PsiBuilder builder, boolean typed, boolean ellipsis, boolean disjunctiveType, boolean resource) { + PsiBuilder.Marker param = builder.mark(); - final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder); + Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder); ReferenceParser.TypeInfo typeInfo = null; if (typed) { @@ -608,7 +600,7 @@ public class DeclarationParser { if (expect(builder, JavaTokenType.IDENTIFIER)) { if (!resource) { - eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, "expected.rparen"); + eatBrackets(builder, typeInfo != null && typeInfo.isVarArg ? "expected.rparen" : null); done(param, JavaElementType.PARAMETER); return param; } @@ -630,8 +622,7 @@ public class DeclarationParser { } @Nullable - private PsiBuilder.Marker parseFieldOrLocalVariable(final PsiBuilder builder, final PsiBuilder.Marker declaration, - final int declarationStart, final Context context) { + private PsiBuilder.Marker parseFieldOrLocalVariable(PsiBuilder builder, PsiBuilder.Marker declaration, int declarationStart, Context context) { final IElementType varType; if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) { varType = JavaElementType.FIELD; @@ -653,7 +644,7 @@ public class DeclarationParser { while (true) { shouldRollback = true; - if (!eatBrackets(builder, false, null)) { + if (!eatBrackets(builder, null)) { unclosed = true; } @@ -715,26 +706,33 @@ public class DeclarationParser { return declaration; } - private static boolean eatBrackets(final PsiBuilder builder, final boolean isError, - @Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) { - if (builder.getTokenType() != JavaTokenType.LBRACKET) return true; + private boolean eatBrackets(PsiBuilder builder, @Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) { + IElementType tokenType = builder.getTokenType(); + if (tokenType != JavaTokenType.LBRACKET && tokenType != JavaTokenType.AT) return true; - final PsiBuilder.Marker marker = isError ? builder.mark() : null; + PsiBuilder.Marker marker = errorKey != null ? builder.mark() : null; - boolean result = true; - while (expect(builder, JavaTokenType.LBRACKET)) { + int count = 0; + while (true) { + parseAnnotations(builder); + if (!expect(builder, JavaTokenType.LBRACKET)) { + break; + } + ++count; if (!expect(builder, JavaTokenType.RBRACKET)) { - if (!isError) error(builder, JavaErrorMessages.message("expected.rbracket")); - result = false; break; } + ++count; } - if (marker != null && errorKey != null) { + boolean paired = count % 2 == 0; + if (marker != null) { marker.error(JavaErrorMessages.message(errorKey)); } - - return result; + else if (!paired) { + error(builder, JavaErrorMessages.message("expected.rbracket")); + } + return paired; } @Nullable diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index e703c93d4a3c..34dd67d8ea1c 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -332,7 +332,12 @@ public class ExpressionParser { final int dotOffset = builder.getCurrentOffset(); builder.advanceLexer(); - final IElementType dotTokenType = builder.getTokenType(); + IElementType dotTokenType = builder.getTokenType(); + if (dotTokenType == JavaTokenType.AT) { + myParser.getDeclarationParser().parseAnnotations(builder); + dotTokenType = builder.getTokenType(); + } + if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { if (breakPoint == BreakPoint.P1 && builder.getCurrentOffset() == breakOffset) { error(builder, JavaErrorMessages.message("expected.identifier")); @@ -691,9 +696,12 @@ public class ExpressionParser { myParser.getReferenceParser().parseReferenceParameterList(builder, false, true); PsiBuilder.Marker refOrType; - + PsiBuilder.Marker anno = myParser.getDeclarationParser().parseAnnotations(builder); IElementType tokenType = builder.getTokenType(); - if (tokenType == JavaTokenType.IDENTIFIER || tokenType == JavaTokenType.AT) { + if (tokenType == JavaTokenType.IDENTIFIER) { + if (anno != null) { + anno.rollbackTo(); + } refOrType = myParser.getReferenceParser().parseJavaCodeReference(builder, true, true, true, true); if (refOrType == null) { error(builder, JavaErrorMessages.message("expected.identifier")); diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 6e72f6017d2e..42a41d51c6fb 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -74,7 +74,8 @@ public class ReferenceParser { while (builder.getTokenType() == operator) { builder.advanceLexer(); - if (builder.getTokenType() != JavaTokenType.IDENTIFIER) { + IElementType tokenType = builder.getTokenType(); + if (tokenType != JavaTokenType.IDENTIFIER && tokenType != JavaTokenType.AT) { error(builder, JavaErrorMessages.message("expected.identifier")); } parseTypeInfo(builder, flags, false); @@ -269,7 +270,7 @@ public class ReferenceParser { return false; } - final int flags = set(set(EAT_LAST_DOT, WILDCARD, wildcard), DIAMONDS, diamonds); + int flags = set(set(EAT_LAST_DOT, WILDCARD, wildcard), DIAMONDS, diamonds); boolean isOk = true; while (true) { if (parseTypeInfo(builder, flags, true) == null) { @@ -289,6 +290,7 @@ public class ReferenceParser { isOk = false; break; } + flags = set(flags, DIAMONDS, false); } list.done(JavaElementType.REFERENCE_PARAMETER_LIST); diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java index dec7b71f5438..b14a37dfb4f3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.psi; +import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; @@ -128,25 +129,31 @@ public class PsiDiamondTypeImpl extends PsiDiamondType { if (psiClass == null) return DiamondInferenceResult.NULL_RESULT; final PsiExpressionList argumentList = newExpression.getArgumentList(); if (argumentList == null) return DiamondInferenceResult.NULL_RESULT; - final Ref<PsiMethod> staticFactory = new Ref<PsiMethod>(); - final PsiSubstitutor inferredSubstitutor = ourDiamondGuard.doPreventingRecursion(newExpression, true, new Computable<PsiSubstitutor>() { + final Ref<PsiMethod> staticFactoryRef = new Ref<PsiMethod>(); + final PsiSubstitutor inferredSubstitutor = ourDiamondGuard.doPreventingRecursion(newExpression, false, new Computable<PsiSubstitutor>() { @Override public PsiSubstitutor compute() { final PsiMethod constructor = findConstructor(psiClass, newExpression); PsiTypeParameter[] params = getAllTypeParams(constructor, psiClass); - staticFactory.set(generateStaticFactory(constructor, psiClass, params)); - if (staticFactory.get() == null) { + final PsiMethod staticFactory = generateStaticFactory(constructor, psiClass, params); + if (staticFactory == null) { return null; } + staticFactoryRef.set(staticFactory); - return inferTypeParametersForStaticFactory(staticFactory.get(), newExpression, context); + return inferTypeParametersForStaticFactory(staticFactory, newExpression, context); } }); if (inferredSubstitutor == null) { return DiamondInferenceResult.NULL_RESULT; } - final PsiTypeParameter[] parameters = staticFactory.get().getTypeParameters(); + final PsiMethod staticFactory = staticFactoryRef.get(); + if (staticFactory == null) { + LOG.error(inferredSubstitutor); + return DiamondInferenceResult.NULL_RESULT; + } + final PsiTypeParameter[] parameters = staticFactory.getTypeParameters(); final PsiTypeParameter[] classParameters = psiClass.getTypeParameters(); final PsiJavaCodeReferenceElement classOrAnonymousClassReference = newExpression.getClassOrAnonymousClassReference(); LOG.assertTrue(classOrAnonymousClassReference != null); @@ -210,7 +217,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType { buf.append(StringUtil.join(params, new Function<PsiTypeParameter, String>() { @Override public String fun(PsiTypeParameter psiTypeParameter) { - final String extendsList = psiTypeParameter.getExtendsList().getText(); + final String extendsList = psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE) ? psiTypeParameter.getExtendsList().getText() : null; return psiTypeParameter.getName() + (StringUtil.isEmpty(extendsList) ? "" : " " + extendsList); } }, ", ")); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 8387b8cc35d0..7cc2bd234c35 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -480,10 +480,15 @@ public class PsiClassImplUtil { if (list != null) { for (final Pair<PsiMember, PsiSubstitutor> candidate : list) { PsiMember candidateField = candidate.getFirst(); - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(candidateField.getContainingClass(), candidate.getSecond(), aClass, + PsiClass containingClass = candidateField.getContainingClass(); + if (containingClass == null) { + LOG.error("No class for field " + candidateField.getName() + " of " + candidateField.getClass()); + continue; + } + PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(containingClass, candidate.getSecond(), aClass, substitutor, factory, languageLevel); - processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, candidateField.getContainingClass()); + processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, containingClass); if (!processor.execute(candidateField, state.put(PsiSubstitutor.KEY, finalSubstitutor))) return false; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java index d8c271f1818e..f7a6d2ed0b24 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -89,24 +89,22 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps @NotNull @Override - public PsiClassType createType(@NotNull final PsiClass resolve, @NotNull final PsiSubstitutor substitutor) { + public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor) { return new PsiImmediateClassType(resolve, substitutor); } @NotNull @Override - public PsiClassType createType(@NotNull final PsiClass resolve, - @NotNull final PsiSubstitutor substitutor, - @NotNull final LanguageLevel languageLevel) { + public PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) { return new PsiImmediateClassType(resolve, substitutor, languageLevel); } @NotNull @Override - public PsiClassType createType(@NotNull final PsiClass resolve, - @NotNull final PsiSubstitutor substitutor, - @NotNull final LanguageLevel languageLevel, - @NotNull final PsiAnnotation[] annotations) { + public PsiClassType createType(@NotNull PsiClass resolve, + @NotNull PsiSubstitutor substitutor, + @Nullable LanguageLevel languageLevel, + @NotNull PsiAnnotation[] annotations) { return new PsiImmediateClassType(resolve, substitutor, languageLevel, annotations); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index 7975019df445..c1db5cd259a7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -46,18 +46,38 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IncorrectOperationException; import com.intellij.util.PairFunction; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Set; + +import static com.intellij.psi.PsiAnnotation.TargetType; public class PsiImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiImplUtil"); - private PsiImplUtil() { - } + private static final Set<TargetType> DEFAULT_TARGETS = Collections.unmodifiableSet(ContainerUtil.newHashSet( + TargetType.PACKAGE, TargetType.TYPE, TargetType.ANNOTATION_TYPE, + TargetType.FIELD, TargetType.METHOD, TargetType.CONSTRUCTOR, + TargetType.PARAMETER, TargetType.LOCAL_VARIABLE)); + + private static final TargetType[] PACKAGE_TARGETS = {TargetType.PACKAGE}; + private static final TargetType[] TYPE_USE_TARGETS = {TargetType.TYPE_USE}; + private static final TargetType[] ANNOTATION_TARGETS = {TargetType.ANNOTATION_TYPE, TargetType.TYPE, TargetType.TYPE_USE}; + private static final TargetType[] TYPE_TARGETS = {TargetType.TYPE, TargetType.TYPE_USE}; + private static final TargetType[] TYPE_PARAMETER_TARGETS = {TargetType.TYPE_PARAMETER, TargetType.TYPE_USE}; + private static final TargetType[] CONSTRUCTOR_TARGETS = {TargetType.CONSTRUCTOR, TargetType.TYPE_USE}; + private static final TargetType[] METHOD_TARGETS = {TargetType.METHOD, TargetType.TYPE_USE}; + private static final TargetType[] FIELD_TARGETS = {TargetType.FIELD, TargetType.TYPE_USE}; + private static final TargetType[] PARAMETER_TARGETS = {TargetType.PARAMETER, TargetType.TYPE_USE}; + private static final TargetType[] LOCAL_VARIABLE_TARGETS ={TargetType.LOCAL_VARIABLE, TargetType.TYPE_USE}; + + private PsiImplUtil() { } @NotNull public static PsiMethod[] getConstructors(@NotNull PsiClass aClass) { @@ -142,7 +162,7 @@ public class PsiImplUtil { int i; for (i = parameters.length - 1; i >= 0; i--) { PsiParameter paramInList = parameters[i]; - if (name.equals(paramInList.getName())) { + if (Comparing.equal(name, paramInList.getName())) { suspect = paramInList; break; } @@ -298,24 +318,155 @@ public class PsiImplUtil { return new PsiImmediateClassType(classClass, substitutor); } - @Nullable public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner modifierList, @NotNull String qualifiedName) { - PsiAnnotation[] annotations = modifierList.getAnnotations(); + @Nullable + public static PsiAnnotation findAnnotation(@NotNull PsiAnnotationOwner annotationOwner, @NotNull String qualifiedName) { + PsiAnnotation[] annotations = annotationOwner.getAnnotations(); if (annotations.length == 0) { return null; } - final String shortName = StringUtil.getShortName(qualifiedName); + String shortName = StringUtil.getShortName(qualifiedName); for (PsiAnnotation annotation : annotations) { - final PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); + PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement(); if (referenceElement != null && shortName.equals(referenceElement.getReferenceName())) { - if (qualifiedName.equals(annotation.getQualifiedName())) return annotation; + if (qualifiedName.equals(annotation.getQualifiedName())) { + return annotation; + } + } + } + + return null; + } + + @Nullable + public static TargetType findApplicableTarget(@NotNull PsiAnnotation annotation, @NotNull TargetType... types) { + if (types.length != 0) { + PsiJavaCodeReferenceElement ref = annotation.getNameReferenceElement(); + if (ref != null) { + PsiElement annotationType = ref.resolve(); + if (annotationType instanceof PsiClass) { + return findApplicableTarget((PsiClass)annotationType, types); + } + } + } + + return TargetType.UNKNOWN; + } + + @Nullable + public static TargetType findApplicableTarget(@NotNull PsiClass annotationType, @NotNull TargetType... types) { + if (types.length != 0) { + Set<TargetType> targets = getAnnotationTargets(annotationType); + if (targets != null) { + for (TargetType type : types) { + if (type != TargetType.UNKNOWN && targets.contains(type)) { + return type; + } + } + return null; + } + } + + return TargetType.UNKNOWN; + } + + // todo[r.sh] cache? + @Nullable + private static Set<TargetType> getAnnotationTargets(PsiClass annotationType) { + if (!annotationType.isAnnotationType()) return null; + PsiModifierList modifierList = annotationType.getModifierList(); + if (modifierList == null) return null; + PsiAnnotation target = modifierList.findAnnotation(CommonClassNames.TARGET_ANNOTATION_FQ_NAME); + if (target == null) return DEFAULT_TARGETS; // if omitted it is applicable to all but Java 8 TYPE_USE/TYPE_PARAMETERS targets + + PsiAnnotationMemberValue value = target.findAttributeValue(null); + if (value instanceof PsiReference) { + TargetType targetType = translateTargetRef((PsiReference)value); + if (targetType != null) { + return Collections.singleton(targetType); + } + } + else if (value instanceof PsiArrayInitializerMemberValue) { + Set <TargetType> targets = ContainerUtil.newHashSet(); + for (PsiAnnotationMemberValue initializer : ((PsiArrayInitializerMemberValue)value).getInitializers()) { + if (initializer instanceof PsiReference) { + TargetType targetType = translateTargetRef((PsiReference)initializer); + if (targetType != null) { + targets.add(targetType); + } + } } + return targets; } return null; } @Nullable + private static TargetType translateTargetRef(PsiReference reference) { + PsiElement field = reference.resolve(); + if (field instanceof PsiEnumConstant) { + String name = ((PsiEnumConstant)field).getName(); + try { + return TargetType.valueOf(name); + } + catch (IllegalArgumentException e) { + LOG.warn("Unknown target: " + name); + } + } + return null; + } + + @NotNull + public static TargetType[] getTargetsForLocation(@Nullable PsiAnnotationOwner owner) { + if (owner == null) { + return TargetType.EMPTY_ARRAY; + } + + if (owner instanceof PsiType || owner instanceof PsiTypeElement) { + return TYPE_USE_TARGETS; + } + + if (owner instanceof PsiTypeParameter) { + return TYPE_PARAMETER_TARGETS; + } + + if (owner instanceof PsiModifierList) { + PsiElement element = ((PsiModifierList)owner).getParent(); + if (element instanceof PsiPackageStatement) { + return PACKAGE_TARGETS; + } + if (element instanceof PsiClass) { + if (((PsiClass)element).isAnnotationType()) { + return ANNOTATION_TARGETS; + } + else { + return TYPE_TARGETS; + } + } + if (element instanceof PsiMethod) { + if (((PsiMethod)element).isConstructor()) { + return CONSTRUCTOR_TARGETS; + } + else { + return METHOD_TARGETS; + } + } + if (element instanceof PsiField) { + return FIELD_TARGETS; + } + if (element instanceof PsiParameter) { + return PARAMETER_TARGETS; + } + if (element instanceof PsiLocalVariable) { + return LOCAL_VARIABLE_TARGETS; + } + } + + return TargetType.EMPTY_ARRAY; + } + + @Nullable public static ASTNode findDocComment(@NotNull CompositeElement element) { TreeElement node = element.getFirstChildNode(); while (node != null && (isWhitespaceOrComment(node) && !(node.getPsi() instanceof PsiDocComment))) { @@ -566,4 +717,34 @@ public class PsiImplUtil { public static PsiElement handleMirror(PsiElement element) { return element instanceof PsiMirrorElement ? ((PsiMirrorElement)element).getPrototype() : element; } + + @Nullable + public static PsiModifierList findNeighbourModifierList(@NotNull PsiJavaCodeReferenceElement ref) { + PsiElement parent = PsiTreeUtil.skipParentsOfType(ref, PsiJavaCodeReferenceElement.class); + if (parent instanceof PsiTypeElement) { + PsiElement grandParent = parent.getParent(); + if (grandParent instanceof PsiModifierListOwner) { + return ((PsiModifierListOwner)grandParent).getModifierList(); + } + } + + return null; + } + + public static void addTypeUseAnnotationsFromModifierList(@NotNull PsiElement member, @NotNull List<PsiAnnotation> annotations) { + if (member instanceof PsiModifierListOwner) { + PsiModifierList modifierList = ((PsiModifierListOwner)member).getModifierList(); + if (modifierList != null) { + addTypeUseAnnotations(modifierList, annotations); + } + } + } + + public static void addTypeUseAnnotations(@NotNull PsiModifierList modifierList, @NotNull List<PsiAnnotation> annotations) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (findApplicableTarget(annotation, TargetType.TYPE_USE) == TargetType.TYPE_USE) { + annotations.add(annotation); + } + } + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/cache/ModifierFlags.java b/java/java-psi-impl/src/com/intellij/psi/impl/cache/ModifierFlags.java index 62c051427569..1b72ac983e9b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/cache/ModifierFlags.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/cache/ModifierFlags.java @@ -38,10 +38,9 @@ public final class ModifierFlags { public static final int STRICTFP_MASK = 0x0800; public static final int PACKAGE_LOCAL_MASK = 0x1000; - public static final TObjectIntHashMap<String> NAME_TO_MODIFIER_FLAG_MAP; - public static final TObjectIntHashMap<IElementType> KEYWORD_TO_MODIFIER_FLAG_MAP; + public static final TObjectIntHashMap<String> NAME_TO_MODIFIER_FLAG_MAP = new TObjectIntHashMap<String>(); + public static final TObjectIntHashMap<IElementType> KEYWORD_TO_MODIFIER_FLAG_MAP = new TObjectIntHashMap<IElementType>(); static { - NAME_TO_MODIFIER_FLAG_MAP = new TObjectIntHashMap<String>(); NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.PUBLIC, PUBLIC_MASK); NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.PRIVATE, PRIVATE_MASK); NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.PROTECTED, PROTECTED_MASK); @@ -56,7 +55,6 @@ public final class ModifierFlags { NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.STRICTFP, STRICTFP_MASK); NAME_TO_MODIFIER_FLAG_MAP.put(PsiModifier.PACKAGE_LOCAL, PACKAGE_LOCAL_MASK); - KEYWORD_TO_MODIFIER_FLAG_MAP = new TObjectIntHashMap<IElementType>(); KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.PUBLIC_KEYWORD, PUBLIC_MASK); KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.PRIVATE_KEYWORD, PRIVATE_MASK); KEYWORD_TO_MODIFIER_FLAG_MAP.put(JavaTokenType.PROTECTED_KEYWORD, PROTECTED_MASK); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/cache/RecordUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/cache/RecordUtil.java index a311b48a80dd..e0c09866c813 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/cache/RecordUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/cache/RecordUtil.java @@ -18,9 +18,10 @@ package com.intellij.psi.impl.cache; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; import com.intellij.lang.LighterASTTokenNode; -import com.intellij.psi.*; +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiModifierList; import com.intellij.psi.impl.java.stubs.*; -import com.intellij.psi.impl.java.stubs.impl.PsiMethodStubImpl; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.LightTreeUtil; import com.intellij.psi.stubs.PsiFileStub; @@ -110,12 +111,7 @@ public class RecordUtil { else if (parent instanceof PsiMethodStub) { if (grandParent instanceof PsiClassStub && ((PsiClassStub)grandParent).isInterface()) { packed |= ModifierFlags.PUBLIC_MASK; - if (parent instanceof PsiMethodStubImpl && ((PsiMethodStubImpl)parent).hasExtensionMethodMark()) { - packed |= ModifierFlags.DEFENDER_MASK; - } - else { - packed |= ModifierFlags.ABSTRACT_MASK; - } + packed |= ModifierFlags.ABSTRACT_MASK; } } else if (parent instanceof PsiFieldStub) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java index 0b4dc267bf66..d9d3b0612133 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/cache/TypeInfo.java @@ -17,96 +17,102 @@ package com.intellij.psi.impl.cache; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.CommonClassNames; import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiNameHelper; +import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiAnnotationStub; import com.intellij.psi.impl.java.stubs.PsiClassStub; +import com.intellij.psi.impl.java.stubs.PsiModifierListStub; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.LightTreeUtil; +import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import com.intellij.psi.tree.IElementType; -import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.StringRef; -import gnu.trove.TIntObjectHashMap; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import static com.intellij.psi.PsiAnnotation.TargetType; import static com.intellij.util.BitUtil.isSet; /** * @author max */ public class TypeInfo { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.cache.TypeInfo"); - - private static final TIntObjectHashMap<String> ourIndexFrequentType = new TIntObjectHashMap<String>(); - private static final TObjectIntHashMap<String> ourFrequentTypeIndex = new TObjectIntHashMap<String>(); - - private static void registerFrequentType(String typeText) { - int index = ourFrequentTypeIndex.size() + 1; - assert index > 0 && index < 15 : "reserved: " + index + " (" + typeText + ")"; - ourFrequentTypeIndex.put(typeText, index); - ourIndexFrequentType.put(index, typeText); - } + private static final String[] ourIndexFrequentType; + private static final TObjectIntHashMap<String> ourFrequentTypeIndex; static { - registerFrequentType("boolean"); - registerFrequentType("byte"); - registerFrequentType("char"); - registerFrequentType("double"); - registerFrequentType("float"); - registerFrequentType("int"); - registerFrequentType("long"); - registerFrequentType("null"); - registerFrequentType("short"); - registerFrequentType("void"); - registerFrequentType("Object"); - registerFrequentType(CommonClassNames.JAVA_LANG_OBJECT); - registerFrequentType("String"); - registerFrequentType(CommonClassNames.JAVA_LANG_STRING); + ourIndexFrequentType = new String[]{ + "", + "boolean", + "byte", + "char", + "double", + "float", + "int", + "long", + "null", + "short", + "void", + CommonClassNames.JAVA_LANG_OBJECT_SHORT, CommonClassNames.JAVA_LANG_OBJECT, + CommonClassNames.JAVA_LANG_STRING_SHORT, CommonClassNames.JAVA_LANG_STRING + }; + + ourFrequentTypeIndex = new TObjectIntHashMap<String>(); + for (int i = 0; i < ourIndexFrequentType.length; i++) { + String type = ourIndexFrequentType[i]; + ourFrequentTypeIndex.put(type, i); + } } - private static final int NULL_FLAGS = 0x0F; - private static final int FREQUENT_INDEX_MASK = 0x0F; - private static final int HAS_ANNOTATIONS = 0x10; - private static final int HAS_ARRAY_COUNT = 0x20; - private static final int HAS_ELLIPSIS = 0x40; + private static final int FREQUENT_INDEX_MASK = 0x03F; + private static final int HAS_ARRAY_COUNT = 0x40; + private static final int HAS_ELLIPSIS = 0x80; - private static final TypeInfo NULL = new TypeInfo(null, (byte)0, false, Collections.<PsiAnnotationStub>emptyList()); + private static final TypeInfo NULL = new TypeInfo((StringRef)null, (byte)0, false, ContainerUtil.<PsiAnnotationStub>emptyList()); public final StringRef text; public final byte arrayCount; public final boolean isEllipsis; + private final List<PsiAnnotationStub> myAnnotationStubs; - public TypeInfo(StringRef _text, byte _arrayCount, boolean ellipsis, @NotNull List<PsiAnnotationStub> annotationStubs) { - text = _text; - arrayCount = _arrayCount; - isEllipsis = ellipsis; - myAnnotationStubs = annotationStubs; + public TypeInfo(String text, byte arrayCount, boolean ellipsis, @NotNull List<PsiAnnotationStub> annotationStubs) { + this(StringRef.fromString(text == null ? null : internFrequentType(text)), arrayCount, ellipsis, annotationStubs); } - public TypeInfo(@NotNull TypeInfo typeInfo) { - text = typeInfo.text; - arrayCount = typeInfo.arrayCount; - isEllipsis = typeInfo.isEllipsis; - myAnnotationStubs = new SmartList<PsiAnnotationStub>(typeInfo.myAnnotationStubs); + private TypeInfo(StringRef text, byte arrayCount, boolean isEllipsis, @NotNull List<PsiAnnotationStub> annotationStubs) { + this.text = text; + this.arrayCount = arrayCount; + this.isEllipsis = isEllipsis; + myAnnotationStubs = annotationStubs; } - public void addAnnotation(PsiAnnotationStub annotation) { - myAnnotationStubs.add(annotation); + @NotNull + public TypeInfo applyAnnotations(@NotNull StubBase<?> owner) { + PsiModifierListStub modifierList = (PsiModifierListStub)owner.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST); + if (modifierList == null) return this; + + List<PsiAnnotationStub> annotationStubs = ContainerUtil.newArrayList(); + for (StubElement child : modifierList.getChildrenStubs()) { + if (!(child instanceof PsiAnnotationStub)) continue; + PsiAnnotationStub annotationStub = (PsiAnnotationStub)child; + if (PsiImplUtil.findApplicableTarget(annotationStub.getPsiElement(), TargetType.TYPE_USE) == TargetType.TYPE_USE) { + annotationStubs.add(annotationStub); + } + } + return new TypeInfo(text, arrayCount, isEllipsis, annotationStubs); } @NotNull @@ -135,7 +141,7 @@ public class TypeInfo { @NotNull public static TypeInfo create(@NotNull LighterAST tree, @NotNull LighterASTNode element, StubElement parentStub) { String text; - int arrayCount = 0; + byte arrayCount = 0; boolean isEllipsis = false; if (element.getTokenType() == JavaElementType.ENUM_CONSTANT) { @@ -166,7 +172,7 @@ public class TypeInfo { assert typeElement != null : element + " in " + parentStub; - isEllipsis = (LightTreeUtil.firstChildOfType(tree, typeElement, JavaTokenType.ELLIPSIS) != null); + isEllipsis = LightTreeUtil.firstChildOfType(tree, typeElement, JavaTokenType.ELLIPSIS) != null; while (true) { LighterASTNode nested = LightTreeUtil.firstChildOfType(tree, typeElement, JavaElementType.TYPE); @@ -178,9 +184,7 @@ public class TypeInfo { text = LightTreeUtil.toFilteredString(tree, typeElement, null); } - List<PsiAnnotationStub> annotations = Collections.emptyList(); // todo[r.sh] JDK 8 type annotations - - return new TypeInfo(StringRef.fromString(text), (byte)arrayCount, isEllipsis, annotations); + return new TypeInfo(text, arrayCount, isEllipsis, ContainerUtil.<PsiAnnotationStub>emptyList()); } @NotNull @@ -193,9 +197,7 @@ public class TypeInfo { typeText = typeText.substring(0, typeText.length() - 2); } - StringRef text = StringRef.fromString(typeText); - - return new TypeInfo(text, arrayCount, isEllipsis, Collections.<PsiAnnotationStub>emptyList()); + return new TypeInfo(typeText, arrayCount, isEllipsis, ContainerUtil.<PsiAnnotationStub>emptyList()); } @NotNull @@ -210,66 +212,40 @@ public class TypeInfo { } @NotNull - public static TypeInfo readTYPE(@NotNull StubInputStream record, StubElement parentStub) throws IOException { + public static TypeInfo readTYPE(@NotNull StubInputStream record) throws IOException { int flags = 0xFF & record.readByte(); - if (flags == NULL_FLAGS) { + if (flags == FREQUENT_INDEX_MASK) { return NULL; } int frequentIndex = FREQUENT_INDEX_MASK & flags; - boolean hasAnnotations = isSet(flags, HAS_ANNOTATIONS); byte arrayCount = isSet(flags, HAS_ARRAY_COUNT) ? record.readByte() : 0; boolean hasEllipsis = isSet(flags, HAS_ELLIPSIS); - StringRef text = frequentIndex == 0 ? record.readName() : StringRef.fromString(ourIndexFrequentType.get(frequentIndex)); + StringRef text = frequentIndex == 0 ? record.readName() : StringRef.fromString(ourIndexFrequentType[frequentIndex]); - List<PsiAnnotationStub> annotationStubs; - if (hasAnnotations) { - int size = 0xFF & record.readByte(); - annotationStubs = new ArrayList<PsiAnnotationStub>(size); - for (int i = 0; i < size; i++) { - PsiAnnotationStub annotationStub = JavaStubElementTypes.ANNOTATION.deserialize(record, parentStub); - annotationStubs.add(annotationStub); - } - } - else { - annotationStubs = Collections.emptyList(); - } - - return new TypeInfo(text, arrayCount, hasEllipsis, annotationStubs); + return new TypeInfo(text, arrayCount, hasEllipsis, ContainerUtil.<PsiAnnotationStub>emptyList()); } public static void writeTYPE(@NotNull StubOutputStream dataStream, @NotNull TypeInfo typeInfo) throws IOException { if (typeInfo == NULL) { - dataStream.writeByte(NULL_FLAGS); + dataStream.writeByte(FREQUENT_INDEX_MASK); return; } - boolean hasEllipsis = typeInfo.isEllipsis; String text = typeInfo.text.getString(); byte arrayCount = typeInfo.arrayCount; int frequentIndex = ourFrequentTypeIndex.get(text); - List<PsiAnnotationStub> annotations = typeInfo.myAnnotationStubs; - boolean hasAnnotations = !annotations.isEmpty(); - int flags = (hasEllipsis ? HAS_ELLIPSIS : 0) | - (arrayCount != 0 ? HAS_ARRAY_COUNT : 0) | - (hasAnnotations ? HAS_ANNOTATIONS : 0) | - frequentIndex; - + int flags = (typeInfo.isEllipsis ? HAS_ELLIPSIS : 0) | (arrayCount != 0 ? HAS_ARRAY_COUNT : 0) | frequentIndex; dataStream.writeByte(flags); + if (arrayCount != 0) { dataStream.writeByte(arrayCount); } + if (frequentIndex == 0) { dataStream.writeName(text); } - if (hasAnnotations) { - LOG.assertTrue(annotations.size() < 256, annotations.size()); - dataStream.writeByte(annotations.size()); - for (PsiAnnotationStub annotation : annotations) { - dataStream.writeUTFFast(annotation.getText()); - } - } } @Nullable @@ -284,7 +260,7 @@ public class TypeInfo { StringBuilder buf = new StringBuilder(); for (PsiAnnotationStub stub : typeInfo.myAnnotationStubs) { - buf.append(stub.getText()).append(" "); + buf.append(stub.getText()).append(' '); } buf.append(typeInfo.text.getString()); @@ -299,4 +275,10 @@ public class TypeInfo { return buf.toString(); } + + @NotNull + private static String internFrequentType(@NotNull String type) { + int frequentIndex = ourFrequentTypeIndex.get(type); + return frequentIndex == 0 ? type : ourIndexFrequentType[frequentIndex]; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java index b9de2ddf6b94..f8877b9a787b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java @@ -364,13 +364,13 @@ public class StubBuildingVisitor<T> extends ClassVisitor { } @NotNull - private static TypeInfo fieldTypeViaDescription(final String desc) { + private static TypeInfo fieldTypeViaDescription(@NotNull String desc) { Type type = Type.getType(desc); final int dim = type.getSort() == Type.ARRAY ? type.getDimensions() : 0; if (dim > 0) { type = type.getElementType(); } - return new TypeInfo(StringRef.fromString(getTypeText(type)), (byte)dim, false, Collections.<PsiAnnotationStub>emptyList()); //todo read annos from .class file + return new TypeInfo(getTypeText(type), (byte)dim, false, Collections.<PsiAnnotationStub>emptyList()); //todo read annos from .class file } @Override @@ -755,13 +755,14 @@ public class StubBuildingVisitor<T> extends ClassVisitor { return getTypeText(Type.getObjectType(name)); } - private static String getTypeText(final Type type) { + @NotNull + private static String getTypeText(@NotNull Type type) { final String raw = type.getClassName(); // As the '$' char is a valid java identifier and is actively used by byte code generators, the problem is // which occurrences of this char should be replaced and which should not. // Heuristic: replace only those $ occurrences that are surrounded non-"$" chars // (most likely generated by javac to separate inner or anonymous class name) // Leading and trailing $ chars should be left unchanged. - return raw.contains("$")? REGEX_PATTERN.matcher(raw).replaceAll("\\.") : raw; + return raw.indexOf('$') >= 0 ? REGEX_PATTERN.matcher(raw).replaceAll("\\.") : raw; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaAnnotationElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaAnnotationElementType.java index 962e371793b3..e5c7e455b124 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaAnnotationElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaAnnotationElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -18,6 +18,7 @@ package com.intellij.psi.impl.java.stubs; import com.intellij.lang.ASTNode; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiNameHelper; import com.intellij.psi.impl.java.stubs.impl.PsiAnnotationStubImpl; @@ -48,42 +49,42 @@ public class JavaAnnotationElementType extends JavaStubElementType<PsiAnnotation } @Override - public PsiAnnotation createPsi(@NotNull final PsiAnnotationStub stub) { + public PsiAnnotation createPsi(@NotNull PsiAnnotationStub stub) { return getPsiFactory(stub).createAnnotation(stub); } @Override - public PsiAnnotation createPsi(@NotNull final ASTNode node) { + public PsiAnnotation createPsi(@NotNull ASTNode node) { return new PsiAnnotationImpl(node); - } + } @Override - public PsiAnnotationStub createStub(final LighterAST tree, final LighterASTNode node, final StubElement parentStub) { - final String text = LightTreeUtil.toFilteredString(tree, node, null); + public PsiAnnotationStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) { + String text = LightTreeUtil.toFilteredString(tree, node, null); return new PsiAnnotationStubImpl(parentStub, text); } @Override - public void serialize(final PsiAnnotationStub stub, final StubOutputStream dataStream) throws IOException { + public void serialize(PsiAnnotationStub stub, StubOutputStream dataStream) throws IOException { dataStream.writeUTFFast(stub.getText()); } @Override - public PsiAnnotationStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException { + public PsiAnnotationStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { return new PsiAnnotationStubImpl(parentStub, dataStream.readUTFFast()); } @Override - public void indexStub(final PsiAnnotationStub stub, final IndexSink sink) { - final String refText = getReferenceShortName(stub.getText()); - sink.occurrence(JavaStubIndexKeys.ANNOTATIONS, refText); + public void indexStub(PsiAnnotationStub stub, IndexSink sink) { + String shortName = getReferenceShortName(stub.getText()); + if (!StringUtil.isEmptyOrSpaces(shortName)) { + sink.occurrence(JavaStubIndexKeys.ANNOTATIONS, shortName); + } } private static String getReferenceShortName(String annotationText) { - final int index = annotationText.indexOf('('); //to get the text of reference itself - if (index >= 0) { - return PsiNameHelper.getShortClassName(annotationText.substring(0, index)); - } + int index = annotationText.indexOf('('); + if (index >= 0) annotationText = annotationText.substring(0, index); return PsiNameHelper.getShortClassName(annotationText); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java index ac54dad9be11..9b27c364b9c6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaClassReferenceListElementType.java @@ -26,7 +26,6 @@ import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys; import com.intellij.psi.impl.source.PsiReferenceListImpl; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.LightTreeUtil; -import com.intellij.psi.impl.source.tree.java.PsiTypeParameterExtendsBoundsListImpl; import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubInputStream; @@ -55,12 +54,7 @@ public abstract class JavaClassReferenceListElementType extends JavaStubElementT @Override public PsiReferenceList createPsi(@NotNull ASTNode node) { - if (node.getElementType() == JavaStubElementTypes.EXTENDS_BOUND_LIST) { - return new PsiTypeParameterExtendsBoundsListImpl(node); - } - else { - return new PsiReferenceListImpl(node); - } + return new PsiReferenceListImpl(node); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaFieldStubElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaFieldStubElementType.java index dee93f5db61d..86efe98490a5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaFieldStubElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaFieldStubElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -127,7 +127,7 @@ public abstract class JavaFieldStubElementType extends JavaStubElementType<PsiFi @Override public PsiFieldStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException { final StringRef name = dataStream.readName(); - final TypeInfo type = TypeInfo.readTYPE(dataStream, parentStub); + final TypeInfo type = TypeInfo.readTYPE(dataStream); final StringRef initializerText = dataStream.readName(); final byte flags = dataStream.readByte(); return new PsiFieldStubImpl(parentStub, name, type, initializerText, flags); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java index ba18473db823..bfaf99d8c22e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaMethodElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -73,7 +73,6 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho boolean isVarArgs = false; boolean isDeprecatedByComment = false; boolean hasDeprecatedAnnotation = false; - boolean isExtension = false; String defValueText = null; boolean expectingDef = false; @@ -103,24 +102,18 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho else if (type == JavaTokenType.DEFAULT_KEYWORD) { expectingDef = true; } - else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && type != JavaTokenType.SEMICOLON) { - if (type != JavaElementType.CODE_BLOCK) { - defValueText = LightTreeUtil.toFilteredString(tree, child, null); - } - else { - isExtension = true; - } + else if (expectingDef && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type) && + type != JavaTokenType.SEMICOLON && type != JavaElementType.CODE_BLOCK) { + defValueText = LightTreeUtil.toFilteredString(tree, child, null); break; } } - final TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); - final boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); - final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation); + TypeInfo typeInfo = isConstructor ? TypeInfo.createConstructorType() : TypeInfo.create(tree, node, parentStub); + boolean isAnno = (node.getTokenType() == JavaElementType.ANNOTATION_METHOD); + byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnno, isVarArgs, isDeprecatedByComment, hasDeprecatedAnnotation); - final PsiMethodStubImpl stub = new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText)); - stub.setExtensionMethodMark(isExtension); - return stub; + return new PsiMethodStubImpl(parentStub, StringRef.fromString(name), typeInfo, flags, StringRef.fromString(defValueText)); } @Override @@ -136,7 +129,7 @@ public abstract class JavaMethodElementType extends JavaStubElementType<PsiMetho @Override public PsiMethodStub deserialize(final StubInputStream dataStream, final StubElement parentStub) throws IOException { StringRef name = dataStream.readName(); - final TypeInfo type = TypeInfo.readTYPE(dataStream, parentStub); + final TypeInfo type = TypeInfo.readTYPE(dataStream); byte flags = dataStream.readByte(); final StringRef defaultMethodValue = PsiMethodStubImpl.isAnnotationMethod(flags) ? dataStream.readName() : null; return new PsiMethodStubImpl(parentStub, name, type, flags, defaultMethodValue); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaParameterElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaParameterElementType.java index f9ebdd67b767..d0e79dd68a58 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaParameterElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaParameterElementType.java @@ -76,7 +76,7 @@ public abstract class JavaParameterElementType extends JavaStubElementType<PsiPa @Override public PsiParameterStub deserialize(StubInputStream dataStream, StubElement parentStub) throws IOException { StringRef name = dataStream.readName(); - TypeInfo type = TypeInfo.readTYPE(dataStream, parentStub); + TypeInfo type = TypeInfo.readTYPE(dataStream); boolean isEllipsis = dataStream.readBoolean(); return new PsiParameterStubImpl(parentStub, name, type, isEllipsis); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java index d64f7afff81e..f3aa46edc64a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/SourceStubPsiFactory.java @@ -47,10 +47,6 @@ public class SourceStubPsiFactory extends StubPsiFactory { @Override public PsiReferenceList createClassReferenceList(PsiClassReferenceListStub stub) { - if (stub.getRole() == PsiReferenceList.Role.EXTENDS_BOUNDS_LIST) { - return new PsiTypeParameterExtendsBoundsListImpl(stub, JavaStubElementTypes.EXTENDS_BOUND_LIST); - } - return new PsiReferenceListImpl(stub, stub.getStubType()); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java index 0f677e127aee..3262f35b2d5c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java @@ -15,21 +15,18 @@ */ package com.intellij.psi.impl.java.stubs.impl; +import com.intellij.codeInsight.AnnotationUtil; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Pair; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiJavaParserFacade; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiAnnotationStub; +import com.intellij.psi.impl.source.CharTableImpl; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; import com.intellij.reference.SoftReference; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.io.StringRef; -import org.jetbrains.annotations.Nullable; - -import java.util.List; /** * @author max @@ -41,18 +38,16 @@ public class PsiAnnotationStubImpl extends StubBase<PsiAnnotation> implements Ps private SoftReference<PsiAnnotation> myParsedFromRepository; public PsiAnnotationStubImpl(final StubElement parent, final String text) { - this(parent, text, null); + super(parent, JavaStubElementTypes.ANNOTATION); + CharSequence interned = CharTableImpl.getStaticInterned(text); + myText = interned == null ? text : interned.toString(); } - public PsiAnnotationStubImpl(final StubElement parent, final String text, @Nullable List<Pair<String, String>> attributes) { - super(parent, JavaStubElementTypes.ANNOTATION); - myText = text; - if (attributes != null) { - PsiAnnotationParameterListStubImpl list = new PsiAnnotationParameterListStubImpl(this); - for (Pair<String, String> attribute : attributes) { - new PsiNameValuePairStubImpl(list, StringRef.fromString(attribute.first), StringRef.fromString(attribute.second)); - } - } + static { + CharTableImpl.addStringsFromClassToStatics(AnnotationUtil.class); + CharTableImpl.staticIntern("@NotNull"); + CharTableImpl.staticIntern("@Nullable"); + CharTableImpl.staticIntern("@Override"); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiFieldStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiFieldStubImpl.java index b4383c1c73a3..d4ef43b96632 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiFieldStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiFieldStubImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -18,10 +18,7 @@ package com.intellij.psi.impl.java.stubs.impl; import com.intellij.psi.PsiField; import com.intellij.psi.impl.cache.TypeInfo; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; -import com.intellij.psi.impl.java.stubs.PsiAnnotationStub; import com.intellij.psi.impl.java.stubs.PsiFieldStub; -import com.intellij.psi.impl.java.stubs.PsiModifierListStub; -import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; import com.intellij.psi.stubs.StubBase; import com.intellij.psi.stubs.StubElement; import com.intellij.util.io.StringRef; @@ -41,13 +38,12 @@ public class PsiFieldStubImpl extends StubBase<PsiField> implements PsiFieldStub private static final int DEPRECATED = 0x02; private static final int DEPRECATED_ANNOTATION = 0x04; - public PsiFieldStubImpl(final StubElement parent, final String name, @NotNull TypeInfo type, @Nullable String initializer, final byte flags) { + public PsiFieldStubImpl(StubElement parent, String name, @NotNull TypeInfo type, @Nullable String initializer, byte flags) { this(parent, StringRef.fromString(name), type, StringRef.fromString(initializer), flags); } - public PsiFieldStubImpl(final StubElement parent, final StringRef name, @NotNull TypeInfo type, final StringRef initializer, final byte flags) { + public PsiFieldStubImpl(StubElement parent, StringRef name, @NotNull TypeInfo type, @Nullable StringRef initializer, byte flags) { super(parent, isEnumConst(flags) ? JavaStubElementTypes.ENUM_CONSTANT : JavaStubElementTypes.FIELD); - myName = name; myType = type; myInitializer = initializer; @@ -57,24 +53,7 @@ public class PsiFieldStubImpl extends StubBase<PsiField> implements PsiFieldStub @Override @NotNull public TypeInfo getType(boolean doResolve) { - if (!doResolve) return myType; - - return addApplicableTypeAnnotationsFromChildModifierList(this, myType); - } - - public static TypeInfo addApplicableTypeAnnotationsFromChildModifierList(StubBase<?> aThis, TypeInfo type) { - PsiModifierListStub modifierList = (PsiModifierListStub)aThis.findChildStubByType(JavaStubElementTypes.MODIFIER_LIST); - if (modifierList == null) return type; - TypeInfo typeInfo = new TypeInfo(type); - for (StubElement child: modifierList.getChildrenStubs()){ - if (!(child instanceof PsiAnnotationStub)) continue; - PsiAnnotationStub annotationStub = (PsiAnnotationStub)child; - PsiAnnotationImpl annotation = (PsiAnnotationImpl)annotationStub.getPsiElement(); - if (PsiAnnotationImpl.isAnnotationApplicableTo(annotation, true, "TYPE_USE")) { - typeInfo.addAnnotation(annotationStub); - } - } - return typeInfo; + return doResolve ? myType.applyAnnotations(this) : myType; } @Override @@ -126,13 +105,11 @@ public class PsiFieldStubImpl extends StubBase<PsiField> implements PsiFieldStub if (isDeprecated() || hasDeprecatedAnnotation()) { builder.append("deprecated "); } - if (isEnumConstant()) { builder.append("enumconst "); } - TypeInfo type = getType(false); // this can be called from low-level code and we don't want resolve to mess with indexing - builder.append(getName()).append(':').append(TypeInfo.createTypeText(type)); + builder.append(myName).append(':').append(myType); if (myInitializer != null) { builder.append('=').append(myInitializer); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java index f5c6a4bb5591..1463355455c2 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -37,8 +37,6 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS private final byte myFlags; private final StringRef myName; private StringRef myDefaultValueText; - // todo[r.sh] drop this after transition period finished - private boolean myHasExtMethodMark = false; private static final int CONSTRUCTOR = 0x01; private static final int VARARGS = 0x02; @@ -46,24 +44,15 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS private static final int DEPRECATED = 0x08; private static final int DEPRECATED_ANNOTATION = 0x10; - public PsiMethodStubImpl(final StubElement parent, - final StringRef name, - final byte flags, - final StringRef defaultValueText) { + public PsiMethodStubImpl(StubElement parent, StringRef name, byte flags, StringRef defaultValueText) { super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD); - myFlags = flags; myName = name; myDefaultValueText = defaultValueText; } - public PsiMethodStubImpl(final StubElement parent, - final StringRef name, - final TypeInfo returnType, - final byte flags, - final StringRef defaultValueText) { + public PsiMethodStubImpl(StubElement parent, StringRef name, TypeInfo returnType, byte flags, StringRef defaultValueText) { super(parent, isAnnotationMethod(flags) ? JavaStubElementTypes.ANNOTATION_METHOD : JavaStubElementTypes.METHOD); - myReturnType = returnType; myFlags = flags; myName = name; @@ -74,14 +63,6 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS myReturnType = returnType; } - public void setExtensionMethodMark(boolean hasExtMethodMark) { - myHasExtMethodMark = hasExtMethodMark; - } - - public boolean hasExtensionMethodMark() { - return myHasExtMethodMark; - } - @Override public boolean isConstructor() { return (myFlags & CONSTRUCTOR) != 0; @@ -109,8 +90,7 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS @Override @NotNull public TypeInfo getReturnTypeText(boolean doResolve) { - if (!doResolve) return myReturnType; - return PsiFieldStubImpl.addApplicableTypeAnnotationsFromChildModifierList(this, myReturnType); + return doResolve ? myReturnType.applyAnnotations(this) : myReturnType; } @Override @@ -172,6 +152,7 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS public String toString() { StringBuilder builder = new StringBuilder(); builder.append("PsiMethodStub["); + if (isConstructor()) { builder.append("cons "); } @@ -185,9 +166,9 @@ public class PsiMethodStubImpl extends StubBase<PsiMethod> implements PsiMethodS builder.append("deprecated "); } - builder.append(getName()).append(":").append(TypeInfo.createTypeText(getReturnTypeText(false))); + builder.append(myName).append(":").append(myReturnType); - final String defaultValue = getDefaultValueText(); + String defaultValue = getDefaultValueText(); if (defaultValue != null) { builder.append(" default=").append(defaultValue); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterStubImpl.java index 2c66a4028e80..8c418e1a7386 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterStubImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterStubImpl.java @@ -60,7 +60,7 @@ public class PsiParameterStubImpl extends StubBase<PsiParameter> implements PsiP @Override @NotNull public TypeInfo getType(boolean doResolve) { - return doResolve ? PsiFieldStubImpl.addApplicableTypeAnnotationsFromChildModifierList(this, myType) : myType; + return doResolve ? myType.applyAnnotations(this) : myType; } @Override @@ -97,6 +97,6 @@ public class PsiParameterStubImpl extends StubBase<PsiParameter> implements PsiP @Override public String toString() { - return "PsiParameterStub[" + myName + ':' + TypeInfo.createTypeText(getType(false)) + ']'; + return "PsiParameterStub[" + myName + ':' + myType + ']'; } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java index f9c6a570601c..6045a907e1e4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/light/LightMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.light; +import com.intellij.lang.Language; import com.intellij.lang.java.JavaLanguage; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; @@ -42,7 +43,14 @@ public class LightMethod extends LightElement implements PsiMethod { private final PsiClass myContainingClass; public LightMethod(@NotNull PsiManager manager, @NotNull PsiMethod method, @NotNull PsiClass containingClass) { - super(manager, JavaLanguage.INSTANCE); + this(manager, method, containingClass, JavaLanguage.INSTANCE); + } + + public LightMethod(@NotNull PsiManager manager, + @NotNull PsiMethod method, + @NotNull PsiClass containingClass, + @NotNull Language language) { + super(manager, language); myMethod = method; myContainingClass = containingClass; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java index 192a57ade26c..a62915a9b013 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaFileElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -37,7 +37,7 @@ import java.io.IOException; * @author max */ public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> { - public static final int STUB_VERSION = 15; + public static final int STUB_VERSION = 16; public JavaFileElementType() { super("java.FILE", JavaLanguage.INSTANCE); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java index 69fb266024db..6eafa4f31a77 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -32,29 +32,27 @@ import java.util.List; */ public class PsiClassReferenceType extends PsiClassType { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiClassReferenceType"); + private final PsiJavaCodeReferenceElement myReference; - public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel languageLevel) { - super(languageLevel, extractAnnosFromReference(reference)); + public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel) { + this(reference, langLevel, collectAnnotations(reference)); + } + + public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel langLevel, @NotNull PsiAnnotation[] annotations) { + super(langLevel, annotations); myReference = reference; } - private static PsiAnnotation[] extractAnnosFromReference(PsiJavaCodeReferenceElement reference) { + private static PsiAnnotation[] collectAnnotations(PsiJavaCodeReferenceElement reference) { List<PsiAnnotation> result = null; - for(PsiElement child = reference.getFirstChild(); child != null; child = child.getNextSibling()){ + for (PsiElement child = reference.getFirstChild(); child != null; child = child.getNextSibling()) { if (child instanceof PsiAnnotation) { if (result == null) result = new SmartList<PsiAnnotation>(); result.add((PsiAnnotation)child); } } - - if (result == null) return PsiAnnotation.EMPTY_ARRAY; - return result.toArray(new PsiAnnotation[result.size()]); - } - - public PsiClassReferenceType(@NotNull PsiJavaCodeReferenceElement reference, LanguageLevel languageLevel, PsiAnnotation[] annotations) { - super(languageLevel,annotations); - myReference = reference; + return result == null ? PsiAnnotation.EMPTY_ARRAY : result.toArray(new PsiAnnotation[result.size()]); } @Override @@ -84,7 +82,7 @@ public class PsiClassReferenceType extends PsiClassType { @Override public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) { if (languageLevel.equals(myLanguageLevel)) return this; - return new PsiClassReferenceType(myReference,languageLevel,getAnnotations()); + return new PsiClassReferenceType(myReference, languageLevel, getAnnotations()); } @Override @@ -158,9 +156,9 @@ public class PsiClassReferenceType extends PsiClassType { } String qualifiedName = myReference.getQualifiedName(); String name = myReference.getReferenceName(); - if (name==null) name=""; + if (name == null) name = ""; LightClassReference reference = new LightClassReference(myReference.getManager(), name, qualifiedName, myReference.getResolveScope()); - return new PsiClassReferenceType(reference, null,getAnnotations()); + return new PsiClassReferenceType(reference, null, getAnnotations()); } @Override @@ -175,14 +173,14 @@ public class PsiClassReferenceType extends PsiClassType { } public PsiClassType createImmediateCopy() { - final ClassResolveResult resolveResult = resolveGenerics(); - if (resolveResult.getElement() == null) return this; - return new PsiImmediateClassType(resolveResult.getElement(), resolveResult.getSubstitutor()); + ClassResolveResult resolveResult = resolveGenerics(); + PsiClass element = resolveResult.getElement(); + return element != null ? new PsiImmediateClassType(element, resolveResult.getSubstitutor()) : this; } @Override public String getPresentableText() { - return getAnnotationsTextPrefix() + PsiNameHelper.getPresentableText(myReference); + return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference); } @Override @@ -192,7 +190,7 @@ public class PsiClassReferenceType extends PsiClassType { @Override public String getInternalCanonicalText() { - return getAnnotationsTextPrefix() + getCanonicalText(); + return getAnnotationsTextPrefix(true, false, true) + getCanonicalText(); } @NotNull diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java index d815bab4235f..a5aed9804c40 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -21,6 +21,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -74,15 +75,18 @@ public class PsiImmediateClassType extends PsiClassType { }; public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor) { - this (aClass, substitutor, null); + this(aClass, substitutor, null, PsiAnnotation.EMPTY_ARRAY); } - public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, final LanguageLevel languageLevel) { - this(aClass, substitutor,languageLevel, PsiAnnotation.EMPTY_ARRAY); + public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel) { + this(aClass, substitutor, languageLevel, PsiAnnotation.EMPTY_ARRAY); } - public PsiImmediateClassType(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, LanguageLevel languageLevel, @NotNull PsiAnnotation[] annotations) { - super(languageLevel,annotations); + public PsiImmediateClassType(@NotNull PsiClass aClass, + @NotNull PsiSubstitutor substitutor, + @Nullable LanguageLevel languageLevel, + @NotNull PsiAnnotation[] annotations) { + super(languageLevel, annotations); myClass = aClass; myManager = aClass.getManager(); mySubstitutor = substitutor; @@ -131,7 +135,7 @@ public class PsiImmediateClassType extends PsiClassType { @Override public String getPresentableText() { if (myPresentableText == null) { - final StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder(); buildText(myClass, mySubstitutor, buffer, false, false); myPresentableText = buffer.toString(); } @@ -142,7 +146,7 @@ public class PsiImmediateClassType extends PsiClassType { public String getCanonicalText() { if (myCanonicalText == null) { assert mySubstitutor.isValid(); - final StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder(); buildText(myClass, mySubstitutor, buffer, true, false); myCanonicalText = buffer.toString(); } @@ -152,7 +156,7 @@ public class PsiImmediateClassType extends PsiClassType { @Override public String getInternalCanonicalText() { if (myInternalCanonicalText == null) { - final StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder(); buildText(myClass, mySubstitutor, buffer, true, true); myInternalCanonicalText = buffer.toString(); } @@ -173,6 +177,11 @@ public class PsiImmediateClassType extends PsiClassType { } return; } + + if (canonical == internal) { + buffer.append(getAnnotationsTextPrefix(internal, false, true)); + } + PsiClass enclosingClass = null; if (!aClass.hasModifierProperty(PsiModifier.STATIC)) { final PsiElement parent = aClass.getParent(); @@ -180,7 +189,6 @@ public class PsiImmediateClassType extends PsiClassType { enclosingClass = (PsiClass)parent; } } - buffer.append(getAnnotationsTextPrefix()); if (enclosingClass != null) { buildText(enclosingClass, substitutor, buffer, canonical, false); buffer.append('.'); @@ -203,7 +211,7 @@ public class PsiImmediateClassType extends PsiClassType { buffer.append(name); } - final PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); + PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); if (typeParameters.length > 0) { StringBuilder pineBuffer = new StringBuilder(); pineBuffer.append('<'); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 5cd2b0c2c810..e5cd665e9f57 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -49,6 +49,8 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement implements PsiJavaCodeReferenceElement, SourceJavaCodeReference { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl"); @@ -193,56 +195,42 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } @Override - public void deleteChildInternal(@NotNull final ASTNode child) { + public void deleteChildInternal(@NotNull ASTNode child) { if (getChildRole(child) == ChildRole.QUALIFIER) { - ASTNode dot = findChildByRole(ChildRole.DOT); + ASTNode dot = findChildByType(JavaTokenType.DOT, child); assert dot != null : this; deleteChildRange(child.getPsi(), dot.getPsi()); + + List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiAnnotation.class); + setAnnotations(annotations); + + return; } - else { - super.deleteChildInternal(child); - } + + super.deleteChildInternal(child); } @Override public final ASTNode findChildByRole(final int role) { LOG.assertTrue(ChildRole.isUnique(role)); - switch (role) { - default: - return null; - case ChildRole.REFERENCE_NAME: - if (getLastChildNode().getElementType() == JavaTokenType.IDENTIFIER) { - return getLastChildNode(); - } - else { - if (getLastChildNode().getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST) { - ASTNode current = getLastChildNode().getTreePrev(); - while (current != null && (current.getPsi() instanceof PsiWhiteSpace || current.getPsi() instanceof PsiComment)) { - current = current.getTreePrev(); - } - if (current != null && current.getElementType() == JavaTokenType.IDENTIFIER) { - return current; - } - } - return null; - } + switch (role) { + case ChildRole.REFERENCE_NAME: + return TreeUtil.findChildBackward(this, JavaTokenType.IDENTIFIER); - case ChildRole.REFERENCE_PARAMETER_LIST: - if (getLastChildNode().getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST) { - return getLastChildNode(); + case ChildRole.REFERENCE_PARAMETER_LIST: { + TreeElement lastChild = getLastChildNode(); + return lastChild.getElementType() == JavaElementType.REFERENCE_PARAMETER_LIST ? lastChild : null; } - return null; case ChildRole.QUALIFIER: - if (getFirstChildNode().getElementType() == JavaElementType.JAVA_CODE_REFERENCE) { - return getFirstChildNode(); - } - return null; + return findChildByType(JavaElementType.JAVA_CODE_REFERENCE); case ChildRole.DOT: - return findChildByType(JavaTokenType.DOT); + return findChildByType(JavaTokenType.DOT); } + + return null; } @Override @@ -380,7 +368,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme Project project = manager.getProject(); final ResolveCache resolveCache = ResolveCache.getInstance(project); - final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode,file); + final ResolveResult[] results = resolveCache.resolveWithCaching(this, OurGenericsResolver.INSTANCE, true, incompleteCode, file); return results.length == 0 ? JavaResolveResult.EMPTY_ARRAY : (JavaResolveResult[])results; } @@ -485,7 +473,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } - LOG.assertTrue(false, this); + LOG.error(this); return JavaResolveResult.EMPTY_ARRAY; } @@ -552,38 +540,74 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme } } - private static IncorrectOperationException cannotBindError(final PsiElement element) { - return new IncorrectOperationException("Cannot bind to "+element); + private static IncorrectOperationException cannotBindError(PsiElement element) { + return new IncorrectOperationException("Cannot bind to " + element); } - private PsiElement bindToClass(final PsiClass aClass) throws IncorrectOperationException { + private PsiElement bindToClass(PsiClass aClass) throws IncorrectOperationException { String qName = aClass.getQualifiedName(); - final boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(getProject()).useFQClassNames() && isFullyQualified(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); + boolean preserveQualification = JavaCodeStyleSettingsFacade.getInstance(getProject()).useFQClassNames() && isFullyQualified(); + JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); if (qName == null) { qName = aClass.getName(); - final PsiClass psiClass = facade.getResolveHelper().resolveReferencedClass(qName, this); + PsiClass psiClass = facade.getResolveHelper().resolveReferencedClass(qName, this); if (!getManager().areElementsEquivalent(psiClass, aClass)) { throw cannotBindError(aClass); } } - else { - if (facade.findClass(qName, getResolveScope()) == null && !preserveQualification) { - return this; - } + else if (facade.findClass(qName, getResolveScope()) == null && !preserveQualification) { + return this; } - final PsiReferenceParameterList parameterList = getParameterList(); - String text = parameterList == null ? qName : qName + parameterList.getText(); + List<PsiAnnotation> annotations = getAnnotations(); + String text = qName; + PsiReferenceParameterList parameterList = getParameterList(); + if (parameterList != null) { + text += parameterList.getText(); + } PsiJavaCodeReferenceElement ref = facade.getParserFacade().createReferenceFromText(text, getParent()); getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode()); - if (!preserveQualification /*&& (TreeUtil.findParent(ref, ElementType.DOC_COMMENT) == null)*/) { - final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(aClass.getProject()); + ((PsiJavaCodeReferenceElementImpl)ref).setAnnotations(annotations); + + if (!preserveQualification) { + JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(aClass.getProject()); ref = (PsiJavaCodeReferenceElement)codeStyleManager.shortenClassReferences(ref, JavaCodeStyleManager.UNCOMPLETE_CODE); } + return ref; } + private List<PsiAnnotation> getAnnotations() { + List<PsiAnnotation> annotations = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiAnnotation.class); + + if (!isQualified()) { + PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(this); + if (modifierList != null) PsiImplUtil.addTypeUseAnnotations(modifierList, annotations); + } + + return annotations; + } + + private void setAnnotations(List<PsiAnnotation> annotations) { + if (annotations.isEmpty()) return; + + PsiElement newParent = this; + PsiElement anchor = SourceTreeToPsiMap.treeElementToPsi(findChildByType(JavaTokenType.DOT)); + if (anchor == null) { + PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(this); + if (modifierList != null) { + newParent = modifierList; + } + } + + for (PsiAnnotation annotation : annotations) { + if (annotation.getParent() != newParent) { + newParent.addAfter(annotation, anchor); + annotation.delete(); + } + } + } + private boolean isFullyQualified() { switch (getKind()) { case CLASS_OR_PACKAGE_NAME_KIND: @@ -712,7 +736,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme @Override public boolean isQualified() { - return getChildRole(getFirstChildNode()) != ChildRole.REFERENCE_NAME; + return getQualifier() != null; } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index 9e8145fa25a3..7378569f99f0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -28,17 +28,13 @@ import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.Factory; import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; @@ -134,12 +130,9 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub> return false; } if (type == JavaTokenType.ABSTRACT_KEYWORD) { - return !(getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) != null || findExtensionMethodMarker((PsiMethod)parent) != null); + return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null; } } - if (type == JavaTokenType.DEFAULT_KEYWORD && findExtensionMethodMarker((PsiMethod)parent) != null) { - return true; - } } else if (parent instanceof PsiField) { if (parent instanceof PsiEnumConstant) { @@ -179,16 +172,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub> return getNode().findChildByType(type) != null; } - @Nullable - public static PsiJavaToken findExtensionMethodMarker(@Nullable PsiMethod method) { - // todo[r.sh] drop this after transition period finished - if (method == null) return null; - final PsiCodeBlock body = method.getBody(); - if (body == null) return null; - final PsiElement previous = PsiTreeUtil.skipSiblingsBackward(body, PsiComment.class, PsiWhiteSpace.class); - return previous instanceof PsiJavaToken && PsiUtil.isJavaToken(previous, JavaTokenType.DEFAULT_KEYWORD) ? (PsiJavaToken)previous : null; - } - @Override public boolean hasExplicitModifier(@NotNull String name) { final CompositeElement tree = (CompositeElement)getNode(); @@ -234,7 +217,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub> } else if (parent instanceof PsiMethod && grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) { if (type == JavaTokenType.PUBLIC_KEYWORD || type == JavaTokenType.ABSTRACT_KEYWORD) return; - if (type == JavaTokenType.DEFAULT_KEYWORD && findExtensionMethodMarker((PsiMethod)parent) != null) return; } else if (parent instanceof PsiClass && grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) { if (type == JavaTokenType.PUBLIC_KEYWORD) return; @@ -257,13 +239,6 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub> if (child != null) { SourceTreeToPsiMap.treeToPsiNotNull(child).delete(); } - - if (type == JavaTokenType.DEFAULT_KEYWORD && parent instanceof PsiMethod) { - final PsiJavaToken marker = findExtensionMethodMarker((PsiMethod)parent); - if (marker != null) { - marker.delete(); - } - } } } @@ -283,11 +258,12 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub> @Override @NotNull public PsiAnnotation[] getApplicableAnnotations() { - final String[] fields = PsiAnnotationImpl.getApplicableElementTypeFields(this); + final PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(this); List<PsiAnnotation> filtered = ContainerUtil.findAll(getAnnotations(), new Condition<PsiAnnotation>() { @Override public boolean value(PsiAnnotation annotation) { - return PsiAnnotationImpl.isAnnotationApplicableTo(annotation, true, fields); + PsiAnnotation.TargetType target = PsiImplUtil.findApplicableTarget(annotation, targets); + return target != null && target != PsiAnnotation.TargetType.UNKNOWN; } }); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java index 2eff5acd41ed..2b8fcbb0a629 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiReferenceListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -22,37 +22,38 @@ import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; -public final class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassReferenceListStub> implements PsiReferenceList { +/** + * @author max + */ +public class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassReferenceListStub> implements PsiReferenceList { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiReferenceListImpl"); - private static final TokenSet REFERENCE_BIT_SET = TokenSet.create(Constants.JAVA_CODE_REFERENCE); - public PsiReferenceListImpl(final PsiClassReferenceListStub stub, final IStubElementType nodeType) { + public PsiReferenceListImpl(PsiClassReferenceListStub stub, IStubElementType nodeType) { super(stub, nodeType); } - public PsiReferenceListImpl(final ASTNode node) { + public PsiReferenceListImpl(ASTNode node) { super(node); } @Override @NotNull public PsiJavaCodeReferenceElement[] getReferenceElements() { - return calcTreeElement().getChildrenAsPsiElements(REFERENCE_BIT_SET, PsiJavaCodeReferenceElement.ARRAY_FACTORY); + return calcTreeElement().getChildrenAsPsiElements(JavaElementType.JAVA_CODE_REFERENCE, PsiJavaCodeReferenceElement.ARRAY_FACTORY); } @Override @NotNull public PsiClassType[] getReferencedTypes() { - final PsiClassReferenceListStub stub = getStub(); + PsiClassReferenceListStub stub = getStub(); if (stub != null) { return stub.getReferencedTypes(); } - final PsiJavaCodeReferenceElement[] refs = getReferenceElements(); - final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + PsiJavaCodeReferenceElement[] refs = getReferenceElements(); + PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); PsiClassType[] types = new PsiClassType[refs.length]; for (int i = 0; i < types.length; i++) { types[i] = factory.createType(refs[i]); @@ -63,24 +64,22 @@ public final class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassRefer @Override public Role getRole() { - final IElementType tt = getElementType(); - - if (tt == JavaElementType.EXTENDS_LIST) { + IElementType type = getElementType(); + if (type == JavaElementType.EXTENDS_LIST) { return Role.EXTENDS_LIST; } - else if (tt == JavaElementType.IMPLEMENTS_LIST) { + else if (type == JavaElementType.IMPLEMENTS_LIST) { return Role.IMPLEMENTS_LIST; } - else if (tt == JavaElementType.THROWS_LIST) { + else if (type == JavaElementType.THROWS_LIST) { return Role.THROWS_LIST; } - else if (tt == JavaElementType.EXTENDS_BOUND_LIST) { + else if (type == JavaElementType.EXTENDS_BOUND_LIST) { return Role.EXTENDS_BOUNDS_LIST; } - else { - LOG.error("Unknown element type:" + tt); - return null; - } + + LOG.error("Unknown element type:" + type); + return null; } @Override @@ -94,6 +93,7 @@ public final class PsiReferenceListImpl extends JavaStubPsiElement<PsiClassRefer } public String toString() { - return "PsiReferenceList"; + return getElementType() == JavaElementType.EXTENDS_BOUND_LIST ? "PsiElement(EXTENDS_BOUND_LIST)" + : "PsiReferenceList"; // todo[r.sh] fix test data } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index b4086db18569..b8ba65024fa3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -23,7 +23,6 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.*; -import com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -90,7 +89,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl while (element != null) { IElementType elementType = element.getElementType(); if (element.getTreeNext() == null && ElementType.PRIMITIVE_TYPE_BIT_SET.contains(elementType)) { - addTypeUseAnnotationsFromModifierList(getParent(), typeAnnotations); + PsiImplUtil.addTypeUseAnnotationsFromModifierList(getParent(), typeAnnotations); final PsiAnnotation[] array = toAnnotationsArray(typeAnnotations); cachedType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createPrimitiveType(element.getText(), array); } @@ -116,7 +115,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl } } else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { - addTypeUseAnnotationsFromModifierList(getParent(), typeAnnotations); + PsiImplUtil.addTypeUseAnnotationsFromModifierList(getParent(), typeAnnotations); final PsiAnnotation[] array = toAnnotationsArray(typeAnnotations); final PsiJavaCodeReferenceElement reference = SourceTreeToPsiMap.treeToPsiNotNull(element); cachedType = new PsiClassReferenceType(reference, null, array); @@ -156,17 +155,6 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl return size == 0 ? PsiAnnotation.EMPTY_ARRAY : typeAnnotations.toArray(new PsiAnnotation[size]); } - public static void addTypeUseAnnotationsFromModifierList(PsiElement member, List<PsiAnnotation> typeAnnotations) { - if (!(member instanceof PsiModifierListOwner)) return; - PsiModifierList list = ((PsiModifierListOwner)member).getModifierList(); - PsiAnnotation[] gluedAnnotations = list == null ? PsiAnnotation.EMPTY_ARRAY : list.getAnnotations(); - for (PsiAnnotation anno : gluedAnnotations) { - if (PsiAnnotationImpl.isAnnotationApplicableTo(anno, true, "TYPE_USE")) { - typeAnnotations.add(anno); - } - } - } - public PsiType getDetachedType(@NotNull PsiElement context) { SoftReference<PsiType> cached = myCachedDetachedType; PsiType type = cached == null ? null : cached.get(); @@ -313,7 +301,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl PsiAnnotation[] annotations = getAnnotations(); ArrayList<PsiAnnotation> list = new ArrayList<PsiAnnotation>(Arrays.asList(annotations)); - addTypeUseAnnotationsFromModifierList(getParent(), list); + PsiImplUtil.addTypeUseAnnotationsFromModifierList(getParent(), list); return toAnnotationsArray(list); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java index fae1b5252a07..ee65e9231c4a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ProcessCandidateParameterTypeInferencePolicy.java @@ -71,7 +71,7 @@ public class ProcessCandidateParameterTypeInferencePolicy extends DefaultParamet protected PsiSubstitutor getSubstitutor(PsiCallExpression contextCall, PsiExpression[] expressions, int i, JavaResolveResult result) { if (result instanceof MethodCandidateInfo) { List<PsiExpression> leftArgs = getExpressions(expressions, i); - return ((MethodCandidateInfo)result).inferTypeArguments(this, leftArgs.toArray(new PsiExpression[leftArgs.size()])); + return ((MethodCandidateInfo)result).inferSubstitutorFromArgs(this, leftArgs.toArray(new PsiExpression[leftArgs.size()])); } else { return result.getSubstitutor(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java index b61fb3d147f5..8c134391c77b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/ElementType.java @@ -56,8 +56,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen ASSIGNMENT_EXPRESSION, NEW_EXPRESSION, ARRAY_ACCESS_EXPRESSION, ARRAY_INITIALIZER_EXPRESSION, INSTANCE_OF_EXPRESSION, CLASS_OBJECT_ACCESS_EXPRESSION, METHOD_REF_EXPRESSION, LAMBDA_EXPRESSION, EMPTY_EXPRESSION); - TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET, - TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER)); + TokenSet ANNOTATION_MEMBER_VALUE_BIT_SET = TokenSet.orSet(EXPRESSION_BIT_SET, TokenSet.create(ANNOTATION, ANNOTATION_ARRAY_INITIALIZER)); TokenSet ARRAY_DIMENSION_BIT_SET = TokenSet.create( REFERENCE_EXPRESSION, LITERAL_EXPRESSION, THIS_EXPRESSION, SUPER_EXPRESSION, PARENTH_EXPRESSION, METHOD_CALL_EXPRESSION, diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java index 917458d55f92..50b2f5b45647 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSharedImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -27,7 +27,12 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; public class JavaSharedImplUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaSharedImplUtil"); @@ -35,7 +40,6 @@ public class JavaSharedImplUtil { private JavaSharedImplUtil() { } public static PsiType getType(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) { - int cStyleArrayCount = countBrackets(anchor); PsiType type; if (typeElement instanceof PsiTypeElementImpl) { type = ((PsiTypeElementImpl)typeElement).getDetachedType(context); @@ -43,34 +47,61 @@ public class JavaSharedImplUtil { else { type = typeElement.getType(); } - for (int i = 0; i < cStyleArrayCount; i++) { - type = type.createArrayType(); + + List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor); + for (PsiAnnotation[] annotations : allAnnotations) { + type = type.createArrayType(annotations); } + return type; } public static PsiType getTypeNoResolve(@NotNull PsiTypeElement typeElement, @NotNull PsiElement anchor, @NotNull PsiElement context) { - int cStyleArrayCount = countBrackets(anchor); PsiType type = typeElement.getTypeNoResolve(context); - for (int i = 0; i < cStyleArrayCount; i++) { - type = type.createArrayType(); + + List<PsiAnnotation[]> allAnnotations = collectAnnotations(anchor); + for (PsiAnnotation[] annotations : allAnnotations) { + type = type.createArrayType(annotations); } + return type; } - private static int countBrackets(PsiElement anchor) { - int cStyleArrayCount = 0; - ASTNode name = SourceTreeToPsiMap.psiToTreeNotNull(anchor); - for (ASTNode child = name.getTreeNext(); child != null; child = child.getTreeNext()) { - IElementType i = child.getElementType(); + private static List<PsiAnnotation[]> collectAnnotations(PsiElement anchor) { + List<PsiAnnotation[]> annotations = new SmartList<PsiAnnotation[]>(); + + List<PsiAnnotation> current = null; + for (PsiElement child = anchor.getNextSibling(); child != null; child = child.getNextSibling()) { + if (child instanceof PsiAnnotation) { + if (current == null) current = new SmartList<PsiAnnotation>(); + current.add((PsiAnnotation)child); + continue; + } + + IElementType i = child.getNode().getElementType(); if (i == JavaTokenType.LBRACKET) { - cStyleArrayCount++; + annotations.add(ContainerUtil.toArray(current, PsiAnnotation.ARRAY_FACTORY)); + current = null; } else if (i != JavaTokenType.RBRACKET && !ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(i)) { break; } } - return cStyleArrayCount; + + return annotations; + } + + @Nullable + public static PsiType findAnnotatedSubtype(@Nullable PsiType type, @NotNull PsiAnnotation annotation) { + while (type instanceof PsiArrayType) { + for (PsiAnnotation a : type.getAnnotations()) { + if (a == annotation) { + return type; + } + } + type = ((PsiArrayType)type).getComponentType(); + } + return null; } public static void normalizeBrackets(PsiVariable variable) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java index 5ddaaa191c93..b597d09c81a5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiAnnotationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -16,7 +16,6 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; @@ -24,10 +23,10 @@ import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiAnnotationStub; import com.intellij.psi.impl.meta.MetaRegistry; import com.intellij.psi.impl.source.JavaStubPsiElement; +import com.intellij.psi.impl.source.PsiClassReferenceType; +import com.intellij.psi.impl.source.tree.JavaSharedImplUtil; import com.intellij.psi.meta.PsiMetaData; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; import com.intellij.util.PairFunction; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -37,8 +36,6 @@ import org.jetbrains.annotations.Nullable; * @author ven */ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> implements PsiAnnotation { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiAnnotationImpl"); - private static final PairFunction<Project, String, PsiAnnotation> ANNOTATION_CREATOR = new PairFunction<Project, String, PsiAnnotation>() { @Override public PsiAnnotation fun(Project project, String text) { @@ -56,16 +53,12 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp @Override public PsiJavaCodeReferenceElement getNameReferenceElement() { - final PsiAnnotationStub stub = getStub(); + PsiAnnotationStub stub = getStub(); if (stub != null) { return PsiTreeUtil.getRequiredChildOfType(stub.getPsiElement(), PsiJavaCodeReferenceElement.class); } - final Object result = PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class); - if (result != null && !(result instanceof PsiJavaCodeReferenceElement)) { - throw new AssertionError("getChildOfType returned rubbish: " + result); - } - return (PsiJavaCodeReferenceElement)result; + return PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class); } @Override @@ -122,149 +115,33 @@ public class PsiAnnotationImpl extends JavaStubPsiElement<PsiAnnotationStub> imp @Override public PsiAnnotationOwner getOwner() { PsiElement parent = getParent(); - if (!PsiUtil.isLanguageLevel8OrHigher(this)) { - return parent instanceof PsiModifierList ? (PsiAnnotationOwner)parent : null; - } - if (parent instanceof PsiTypeElement) { - return ((PsiTypeElement)parent).getOwner(this); - } - if (parent instanceof PsiTypeParameter) { + if (parent instanceof PsiAnnotationOwner) { return (PsiAnnotationOwner)parent; } - PsiElement member = parent.getParent(); - String[] elementTypeFields = getApplicableElementTypeFields(member); - if (elementTypeFields == null) return null; - if (parent instanceof PsiAnnotationOwner - && isAnnotationApplicableTo(this, true, elementTypeFields)) return (PsiAnnotationOwner)parent; - - PsiAnnotationOwner typeElement; - if (member instanceof PsiVariable) { - if (member instanceof PsiEnumConstant && parent instanceof PsiAnnotationOwner){ - return (PsiAnnotationOwner)parent; - } - typeElement = ((PsiVariable)member).getTypeElement(); - } - else if (member instanceof PsiMethod && !((PsiMethod)member).isConstructor()) { - typeElement = ((PsiMethod)member).getReturnTypeElement(); - } - else if (parent instanceof PsiAnnotationOwner) { - typeElement = (PsiAnnotationOwner)parent; - } - else { - typeElement = null; - } - return typeElement; - } - - public static boolean isAnnotationApplicableTo(PsiAnnotation annotation, boolean strict, String... elementTypeFields) { - if (elementTypeFields == null) return true; - PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement(); - if (nameRef == null) { - return !strict; - } - PsiElement resolved = nameRef.resolve(); - if (!(resolved instanceof PsiClass) || !((PsiClass)resolved).isAnnotationType()) { - return !strict; - } - PsiClass annotationType = (PsiClass)resolved; - return isAnnotationApplicable(strict, annotationType, elementTypeFields, annotation.getResolveScope()); - } - - public static boolean isAnnotationApplicable(boolean strict, - @NotNull PsiClass annotationType, - @Nullable String[] elementTypeFields, - GlobalSearchScope resolveScope) { - if (elementTypeFields == null) { - return !strict; - } - PsiAnnotation target = annotationType.getModifierList().findAnnotation(CommonClassNames.TARGET_ANNOTATION_FQ_NAME); - if (target == null) { - //todo hack: ambiguity in spec - return !strict; - //return !ArrayUtil.contains("TYPE_USE", elementTypeFields); + if (parent instanceof PsiNewExpression) { + return ((PsiNewExpression)parent).getOwner(this); } - PsiNameValuePair[] attributes = target.getParameterList().getAttributes(); - if (attributes.length == 0) { - return !strict; - } - LOG.assertTrue(elementTypeFields.length > 0); - PsiClass elementTypeClass = - JavaPsiFacade.getInstance(annotationType.getProject()).findClass("java.lang.annotation.ElementType", resolveScope); - if (elementTypeClass == null) { - //todo hack - return !strict; - //return !ArrayUtil.contains("TYPE_USE", elementTypeFields); + if (parent instanceof PsiMethod) { + PsiType type = ((PsiMethod)parent).getReturnType(); + return JavaSharedImplUtil.findAnnotatedSubtype(type, this); } - PsiAnnotationMemberValue value = null; - for (String fieldName : elementTypeFields) { - PsiField field = elementTypeClass.findFieldByName(fieldName, false); - if (field == null) { - continue; - } - if (value == null) { - value = attributes[0].getValue(); - } - if (value instanceof PsiArrayInitializerMemberValue) { - PsiAnnotationMemberValue[] initializers = ((PsiArrayInitializerMemberValue)value).getInitializers(); - for (PsiAnnotationMemberValue initializer : initializers) { - if (initializer instanceof PsiReference) { - if (((PsiReference)initializer).isReferenceTo(field)) { - return true; - } - } - } - } - else if (value instanceof PsiReference) { - if (((PsiReference)value).isReferenceTo(field)) { - return true; - } + if (parent instanceof PsiReferenceExpression) { + PsiElement ctx = parent.getParent(); + if (ctx instanceof PsiMethodReferenceExpression) { + return new PsiClassReferenceType((PsiJavaCodeReferenceElement)parent, null); } } - return false; - } - - @Nullable - public static String[] getApplicableElementTypeFields(PsiElement owner) { - if (owner instanceof PsiClass) { - PsiClass aClass = (PsiClass)owner; - if (aClass.isAnnotationType()) { - return new String[]{"ANNOTATION_TYPE", "TYPE"}; - } - else if (aClass instanceof PsiTypeParameter) { - return new String[]{"TYPE_PARAMETER"}; - } - else { - return new String[]{"TYPE"}; + else if (parent instanceof PsiJavaCodeReferenceElement) { + PsiElement ctx = PsiTreeUtil.skipParentsOfType(parent, PsiJavaCodeReferenceElement.class); + if (ctx instanceof PsiReferenceList || ctx instanceof PsiNewExpression || ctx instanceof PsiTypeElement) { + return new PsiClassReferenceType((PsiJavaCodeReferenceElement)parent, null); } } - if (owner instanceof PsiMethod) { - if (((PsiMethod)owner).isConstructor()) { - return new String[]{"CONSTRUCTOR"}; - } - else { - return new String[]{"METHOD"}; - } - } - if (owner instanceof PsiField) { - return new String[]{"FIELD"}; - } - if (owner instanceof PsiParameter) { - return new String[]{"PARAMETER"}; - } - if (owner instanceof PsiLocalVariable) { - return new String[]{"LOCAL_VARIABLE"}; - } - if (owner instanceof PsiPackageStatement) { - return new String[]{"PACKAGE"}; - } - if (owner instanceof PsiTypeElement) { - return new String[]{"TYPE_USE"}; - } return null; } -}
\ No newline at end of file +} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java index dc092a73346b..699e33476b48 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java @@ -17,6 +17,7 @@ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; @@ -194,7 +195,13 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements if (is15OrHigher) { final PsiSubstitutor substitutor = result.getSubstitutor(); PsiType substitutedReturnType = substitutor.substitute(ret); - if (PsiUtil.isRawSubstitutor(method, substitutor) && ret.equals(substitutedReturnType)) return TypeConversionUtil.erasure(ret); + if (substitutedReturnType == null) return TypeConversionUtil.erasure(ret); + if (PsiUtil.isRawSubstitutor(method, substitutor)) { + final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret); + if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) { + return returnTypeErasure; + } + } PsiType lowerBound = PsiType.NULL; if (substitutedReturnType instanceof PsiCapturedWildcardType) { lowerBound = ((PsiCapturedWildcardType)substitutedReturnType).getLowerBound(); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 810e541cb387..e092c9e3178e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -267,6 +267,9 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase final PsiElement element = getReferenceNameElement(); final boolean isConstructor = element instanceof PsiKeyword && PsiKeyword.NEW.equals(element.getText()); if (element instanceof PsiIdentifier || isConstructor) { + if (isConstructor && (containingClass.isEnum() || containingClass.hasModifierProperty(PsiModifier.ABSTRACT))) { + return JavaResolveResult.EMPTY_ARRAY; + } PsiType functionalInterfaceType = null; final Map<PsiMethodReferenceExpression,PsiType> map = PsiMethodReferenceUtil.ourRefs.get(); if (map != null) { @@ -289,9 +292,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase substitutor = LambdaUtil.inferFromReturnType(typeParameters, returnType, interfaceMethodReturnType, substitutor, languageLevel, PsiMethodReferenceExpressionImpl.this.getProject()); - if (containingClass.getConstructors().length == 0 && - !containingClass.isEnum() && - !containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) { + if (containingClass.getConstructors().length == 0) { ClassCandidateInfo candidateInfo = null; if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && signature.getParameterTypes().length == 0 || PsiMethodReferenceUtil.onArrayType(containingClass, signature)) { @@ -358,9 +359,9 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase final PsiType[] types = method.getSignature(PsiUtil.isRawSubstitutor(method, substitutor) ? PsiSubstitutor.EMPTY : substitutor).getParameterTypes(); final PsiType[] rightTypes = signature.getParameterTypes(); if (types.length < rightTypes.length) { - return PsiUtil.resolveGenericsClassInType(rightTypes[0]).getSubstitutor(); + return getSubstitutor(rightTypes[0]); } else if (types.length > rightTypes.length) { - return PsiUtil.resolveGenericsClassInType(types[0]).getSubstitutor(); + return getSubstitutor(types[0]); } for (int i = 0; i < rightTypes.length; i++) { @@ -380,6 +381,20 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase languageLevel, PsiMethodReferenceExpressionImpl.this.getProject()); } + private PsiSubstitutor getSubstitutor(PsiType type) { + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type); + PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor(); + if (type instanceof PsiClassType) { + final PsiClass psiClass = resolveResult.getElement(); + if (psiClass instanceof PsiTypeParameter) { + for (PsiClass aClass : psiClass.getSupers()) { + psiSubstitutor = psiSubstitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(aClass, (PsiClassType)type)); + } + } + } + return psiSubstitutor; + } + private class MethodReferenceConflictResolver implements PsiConflictResolver { private final PsiClass myContainingClass; private final PsiSubstitutor mySubstitutor; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java index 33d55ed03d56..dc8f0bb75f6e 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -30,11 +30,10 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNewExpression { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiNewExpressionImpl"); @@ -43,39 +42,57 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew } @Override - public PsiType getType(){ + public PsiType getType() { + return doGetType(null); + } + + @Override + public PsiType getOwner(@NotNull PsiAnnotation annotation) { + assert annotation.getParent() == this : annotation.getParent() + " != " + this; + return doGetType(annotation); + } + + @Nullable + private PsiType doGetType(@Nullable PsiAnnotation stopAt) { PsiType type = null; - List<PsiAnnotation> annotations = new SmartList<PsiAnnotation>(); - for(ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()){ + SmartList<PsiAnnotation> annotations = new SmartList<PsiAnnotation>(); + boolean stop = false; + + for (ASTNode child = getFirstChildNode(); child != null; child = child.getTreeNext()) { IElementType elementType = child.getElementType(); if (elementType == JavaElementType.ANNOTATION) { - annotations.add((PsiAnnotation)child.getPsi()); - continue; + PsiAnnotation annotation = (PsiAnnotation)child.getPsi(); + annotations.add(annotation); + if (annotation == stopAt) stop = true; } - if (elementType == JavaElementType.JAVA_CODE_REFERENCE){ - LOG.assertTrue(type == null); - type = new PsiClassReferenceType((PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(child), null); + else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) { + assert type == null : this; + type = new PsiClassReferenceType((PsiJavaCodeReferenceElement)child.getPsi(), null); + if (stop) return type; } - else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(elementType)){ - LOG.assertTrue(type == null); - PsiAnnotation[] annos = annotations.toArray(new PsiAnnotation[annotations.size()]); - type = JavaPsiFacade.getInstance(getProject()).getElementFactory().createPrimitiveType(child.getText(), annos); + else if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(elementType)) { + assert type == null : this; + PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); + type = factory.createPrimitiveType(child.getText(), ContainerUtil.copyAndClear(annotations, PsiAnnotation.ARRAY_FACTORY, true)); + if (stop) return type; } - else if (elementType == JavaTokenType.LBRACKET){ - LOG.assertTrue(type != null); - PsiAnnotation[] annos = annotations.toArray(new PsiAnnotation[annotations.size()]); - - type = type.createArrayType(annos); + else if (elementType == JavaTokenType.LBRACKET) { + assert type != null : this; + type = type.createArrayType(ContainerUtil.copyAndClear(annotations, PsiAnnotation.ARRAY_FACTORY, true)); + if (stop) return type; } - else if (elementType == JavaElementType.ANONYMOUS_CLASS){ - PsiAnnotation[] annos = annotations.toArray(new PsiAnnotation[annotations.size()]); + else if (elementType == JavaElementType.ANONYMOUS_CLASS) { PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - PsiClass aClass = (PsiClass)SourceTreeToPsiMap.treeElementToPsi(child); + PsiClass aClass = (PsiClass)child.getPsi(); PsiSubstitutor substitutor = aClass instanceof PsiTypeParameter ? PsiSubstitutor.EMPTY : factory.createRawSubstitutor(aClass); - type = factory.createType(aClass, substitutor, PsiUtil.getLanguageLevel(aClass),annos); + type = factory.createType(aClass, substitutor, PsiUtil.getLanguageLevel(aClass), + ContainerUtil.copyAndClear(annotations, PsiAnnotation.ARRAY_FACTORY, true)); + if (stop) return type; } } - return type; + + // stop == true means annotation is misplaced + return stop ? null : type; } @Override @@ -360,7 +377,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew } @Override - public void accept(@NotNull PsiElementVisitor visitor){ + public void accept(@NotNull PsiElementVisitor visitor) { if (visitor instanceof JavaElementVisitor) { ((JavaElementVisitor)visitor).visitNewExpression(this); } @@ -369,8 +386,7 @@ public class PsiNewExpressionImpl extends ExpressionPsiElement implements PsiNew } } - public String toString(){ + public String toString() { return "PsiNewExpression:" + getText(); } } - diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java deleted file mode 100644 index 8d03254b1cf2..000000000000 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTypeParameterExtendsBoundsListImpl.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2000-2012 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.java; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.*; -import com.intellij.psi.impl.java.stubs.PsiClassReferenceListStub; -import com.intellij.psi.impl.source.Constants; -import com.intellij.psi.impl.source.JavaStubPsiElement; -import com.intellij.psi.stubs.IStubElementType; -import org.jetbrains.annotations.NotNull; - -/** - * @author max - */ -public class PsiTypeParameterExtendsBoundsListImpl extends JavaStubPsiElement<PsiClassReferenceListStub> implements PsiReferenceList { - public PsiTypeParameterExtendsBoundsListImpl(final PsiClassReferenceListStub stub, final IStubElementType nodeType) { - super(stub, nodeType); - } - - public PsiTypeParameterExtendsBoundsListImpl(final ASTNode node) { - super(node); - } - - @Override - @NotNull - public PsiJavaCodeReferenceElement[] getReferenceElements() { - return calcTreeElement().getChildrenAsPsiElements(Constants.JAVA_CODE_REFERENCE_BIT_SET, PsiJavaCodeReferenceElement.ARRAY_FACTORY); - } - - @Override - @NotNull - public PsiClassType[] getReferencedTypes() { - final PsiClassReferenceListStub stub = getStub(); - if (stub != null) return stub.getReferencedTypes(); - - return createTypes(getReferenceElements()); - } - - @Override - public Role getRole() { - return Role.EXTENDS_BOUNDS_LIST; - } - - private PsiClassType[] createTypes(final PsiJavaCodeReferenceElement[] refs) { - final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory(); - PsiClassType[] types = new PsiClassType[refs.length]; - for (int i = 0; i < refs.length; i++) { - types[i] = factory.createType(refs[i]); - } - return types; - } - - @Override - public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JavaElementVisitor) { - ((JavaElementVisitor)visitor).visitReferenceList(this); - } - else { - visitor.visitElement(this); - } - } - - public String toString() { - return "PsiElement(EXTENDS_BOUND_LIST)"; - } -} diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index b8141babaa3f..0eace78fea45 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -107,6 +107,7 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ final PsiMethod method = (PsiMethod)conflict.getElement(); if (method != null) { final PsiParameter[] methodParameters = method.getParameterList().getParameters(); + if (methodParameters.length == 0) continue; final PsiParameter param = i < methodParameters.length ? methodParameters[i] : methodParameters[methodParameters.length - 1]; final PsiType paramType = param.getType(); if (!LambdaUtil.isAcceptable(lambdaExpression, conflict.getSubstitutor().substitute(paramType), true)) { |