diff --git a/java/java-psi-api/src/com/intellij/psi/augment/TypeAnnotationModifier.java b/java/java-psi-api/src/com/intellij/psi/augment/TypeAnnotationModifier.java new file mode 100644 index 000000000000..56cf6abb0cd0 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/psi/augment/TypeAnnotationModifier.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2016 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.augment; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiType; +import com.intellij.psi.TypeAnnotationProvider; +import org.jetbrains.annotations.Nullable; + +public abstract class TypeAnnotationModifier { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.lang.psiTypeAnnotationModifier"); + + /** + * Type annotations are ignored during inference process. When they are present on types which are bounds of the inference variables, + * then the corresponding instantiations of inference variables would contain that type annotations. + * If different bounds contain contradicting type annotations or type annotations on types repeat target type annotations, + * it could be useful to ignore such annotations in the resulted instantiation. + + * @param inferenceVariableType target type + * @param boundType bound which annotations should be changed according to present annotations + * and annotations on target type + * @return provider based on modified annotations or null if no applicable annotations found + */ + @Nullable + public abstract TypeAnnotationProvider getTypeAnnotationProvider(PsiType inferenceVariableType, PsiClassType boundType); + +} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index fcf3a867857e..c53d97faf065 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -23,6 +23,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.light.LightTypeParameter; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; import gnu.trove.THashMap; import gnu.trove.TObjectHashingStrategy; @@ -120,6 +121,18 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { return glb instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)glb).getWildcard() : PsiWildcardType.createExtends(typeParameter.getManager(), glb); } + + /* + if (glb instanceof PsiCapturedWildcardType) { + PsiWildcardType wildcard = ((PsiCapturedWildcardType)glb).getWildcard(); + if (!wildcard.isSuper()) return wildcard; + } + + if (glb != null ) { + return PsiWildcardType.createExtends(typeParameter.getManager(), glb); + } + */ + } return substituted; } @@ -206,7 +219,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { } @Override - public PsiType visitClassType(PsiClassType classType) { + public PsiType visitClassType(final PsiClassType classType) { final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); final PsiClass aClass = resolveResult.getElement(); if (aClass == null) return classType; @@ -215,11 +228,18 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { if (aClass instanceof PsiTypeParameter) { final PsiTypeParameter typeParameter = (PsiTypeParameter)aClass; if (containsInMap(typeParameter)) { - PsiType result = substituteTypeParameter(typeParameter); + final PsiType result = substituteTypeParameter(typeParameter); if (result != null) { PsiUtil.ensureValidType(result); + return result.annotate(new TypeAnnotationProvider() { + @NotNull + @Override + public PsiAnnotation[] getAnnotations() { + return ArrayUtil.mergeArrays(result.getAnnotations(), classType.getAnnotations()); + } + }); } - return result; + return null; } return classType; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java index a87054821e91..138991abf9f0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.source.resolve.graphInference; import com.intellij.psi.*; +import com.intellij.psi.augment.TypeAnnotationModifier; import com.intellij.psi.impl.light.LightTypeParameter; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -71,6 +72,14 @@ public class InferenceVariable extends LightTypeParameter { public static void addBound(PsiType inferenceVariableType, PsiType boundType, InferenceBound inferenceBound, InferenceSession session) { final InferenceVariable variable = session.getInferenceVariable(inferenceVariableType); if (variable != null) { + for (TypeAnnotationModifier modifier : TypeAnnotationModifier.EP_NAME.getExtensions()) { + if (boundType instanceof PsiClassType) { + final TypeAnnotationProvider annotationProvider = modifier.getTypeAnnotationProvider(inferenceVariableType, (PsiClassType)boundType); + if (annotationProvider != null) { + boundType = boundType.annotate(annotationProvider); + } + } + } variable.addBound(boundType, inferenceBound, session.myIncorporationPhase); } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index eefa522bf50c..dc9dd6fbf534 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -299,6 +299,7 @@ +