diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 6914e84e9395..6b76e26d4025 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -159,7 +159,7 @@ public class GenericsHighlightUtil { if (typeParameterListOwner instanceof PsiClass) { QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createChangeClassSignatureFromUsageFix((PsiClass)typeParameterListOwner, referenceParameterList)); } - registerVariableParameterizedTypeFixes(highlightInfo, (PsiVariable)variable, referenceParameterList); + registerVariableParameterizedTypeFixes(highlightInfo, (PsiVariable)variable, referenceParameterList, javaSdkVersion); } } } @@ -1295,7 +1295,8 @@ public class GenericsHighlightUtil { public static void registerVariableParameterizedTypeFixes(HighlightInfo highlightInfo, @NotNull PsiVariable variable, - @NotNull PsiReferenceParameterList parameterList) { + @NotNull PsiReferenceParameterList parameterList, + @NotNull JavaSdkVersion version) { PsiType type = variable.getType(); if (!(type instanceof PsiClassType)) return; @@ -1307,7 +1308,6 @@ public class GenericsHighlightUtil { PsiShortNamesCache shortNamesCache = PsiShortNamesCache.getInstance(parameterList.getProject()); PsiClass[] classes = shortNamesCache.getClassesByName(shortName, GlobalSearchScope.allScope(manager.getProject())); PsiElementFactory factory = facade.getElementFactory(); - JavaSdkVersion version = JavaVersionService.getInstance().getJavaSdkVersion(parameterList); for (PsiClass aClass : classes) { if (checkReferenceTypeArgumentList(aClass, parameterList, PsiSubstitutor.EMPTY, false, version) == null) { PsiType[] actualTypeParameters = parameterList.getTypeArguments(); 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 1de2634c27c8..2ac053285b78 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 @@ -692,49 +692,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict); if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType || actualParameterTypes[functionalInterfaceIdx] instanceof PsiMethodReferenceType) { if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) { - - final TypeKind typeKind = getKind(actualParameterTypes[functionalInterfaceIdx]); - Specifics moreSpecific1 = Specifics.NEITHER; - if (typeKind != TypeKind.NONE_DETERMINED) { - final boolean isPrimitive = typeKind == TypeKind.PRIMITIVE; - if (interfaceReturnType instanceof PsiPrimitiveType) { - if (interfaceReturnType1 instanceof PsiPrimitiveType && - TypeConversionUtil.isAssignable(interfaceReturnType, interfaceReturnType1)) { - moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST; - } else { - moreSpecific1 = isPrimitive ? Specifics.FIRST : Specifics.SECOND; - } - } else if (interfaceReturnType1 instanceof PsiPrimitiveType) { - moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST; - } - } - + Specifics moreSpecific1 = comparePrimitives(actualParameterTypes[functionalInterfaceIdx], interfaceReturnType, interfaceReturnType1); if (moreSpecific1 == Specifics.NEITHER && (interfaceReturnType != PsiType.VOID && interfaceReturnType1 != PsiType.VOID)) { - final PsiSubstitutor siteSubstitutor1 = ((MethodCandidateInfo)method).getSiteSubstitutor(); - final PsiSubstitutor siteSubstitutor2 = ((MethodCandidateInfo)conflict).getSiteSubstitutor(); - - final PsiTypeParameter[] typeParameters1 = methodElement.getTypeParameters(); - final PsiTypeParameter[] typeParameters2 = conflictElement.getTypeParameters(); - - final PsiType[] types1AtSite = {interfaceReturnType1}; - final PsiType[] types2AtSite = {interfaceReturnType}; - - final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, methodElement, siteSubstitutor1, types2AtSite, types1AtSite, languageLevel); - final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, conflictElement, siteSubstitutor2, types1AtSite, types2AtSite,languageLevel); - - final boolean applicable12 = TypeConversionUtil.isAssignable(interfaceReturnType1, methodSubstitutor1.substitute(interfaceReturnType)); - final boolean applicable21 = TypeConversionUtil.isAssignable(interfaceReturnType, methodSubstitutor2.substitute(interfaceReturnType1)); - - - if (applicable12 || applicable21) { - if (!applicable21) { - moreSpecific1 = Specifics.FIRST; - } - - if (!applicable12) { - moreSpecific1 = Specifics.SECOND; - } - } + moreSpecific1 = compareConflicts((MethodCandidateInfo)method, (MethodCandidateInfo)conflict, + methodElement, conflictElement, + interfaceReturnType, interfaceReturnType1, languageLevel); } if (moreSpecific != Specifics.NEITHER && moreSpecific != moreSpecific1) { @@ -751,6 +713,62 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return moreSpecific; } + private static Specifics compareConflicts(MethodCandidateInfo method, + MethodCandidateInfo conflict, + PsiMethod methodElement, + PsiMethod conflictElement, + PsiType interfaceReturnType, + PsiType interfaceReturnType1, + LanguageLevel languageLevel) { + final PsiSubstitutor siteSubstitutor1 = method.getSiteSubstitutor(); + final PsiSubstitutor siteSubstitutor2 = conflict.getSiteSubstitutor(); + + final PsiTypeParameter[] typeParameters1 = methodElement.getTypeParameters(); + final PsiTypeParameter[] typeParameters2 = conflictElement.getTypeParameters(); + + final PsiType[] types1AtSite = {interfaceReturnType1}; + final PsiType[] types2AtSite = {interfaceReturnType}; + + final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, methodElement, siteSubstitutor1, types2AtSite, types1AtSite, languageLevel); + final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, conflictElement, siteSubstitutor2, types1AtSite, types2AtSite,languageLevel); + + final boolean applicable12 = TypeConversionUtil.isAssignable(interfaceReturnType1, methodSubstitutor1.substitute(interfaceReturnType)); + final boolean applicable21 = TypeConversionUtil.isAssignable(interfaceReturnType, methodSubstitutor2.substitute(interfaceReturnType1)); + + + if (applicable12 || applicable21) { + if (!applicable21) { + return Specifics.FIRST; + } + + if (!applicable12) { + return Specifics.SECOND; + } + } + return Specifics.NEITHER; + } + + private static Specifics comparePrimitives(PsiType type, + PsiType interfaceReturnType, + PsiType interfaceReturnType1) { + final TypeKind typeKind = getKind(type); + Specifics moreSpecific1 = Specifics.NEITHER; + if (typeKind != TypeKind.NONE_DETERMINED) { + final boolean isPrimitive = typeKind == TypeKind.PRIMITIVE; + if (interfaceReturnType instanceof PsiPrimitiveType) { + if (interfaceReturnType1 instanceof PsiPrimitiveType && + TypeConversionUtil.isAssignable(interfaceReturnType, interfaceReturnType1)) { + moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST; + } else { + moreSpecific1 = isPrimitive ? Specifics.FIRST : Specifics.SECOND; + } + } else if (interfaceReturnType1 instanceof PsiPrimitiveType) { + moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST; + } + } + return moreSpecific1; + } + @Nullable private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) { final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java index 93fb1d39159a..ddc5692cb1aa 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ImportUtils.java @@ -19,17 +19,14 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleSettingsFacade; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.ClassUtil; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.*; import com.siyeh.HardcodedMethodConstants; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class ImportUtils { @@ -548,10 +545,26 @@ public class ImportUtils { /** * @return true, if the element contains a reference to a different class than fullyQualifiedName but which has the same class name */ - public static boolean containsConflictingReference(PsiElement element, String fullyQualifiedName) { + public static boolean containsConflictingReference(PsiFile element, String fullyQualifiedName) { + final Map cachedValue = + CachedValuesManager.getManager(element.getProject()).getCachedValue(element, new CachedValueProvider>() { + @Nullable + @Override + public Result> compute() { + return new Result>(Collections.synchronizedMap(new HashMap()), PsiModificationTracker.MODIFICATION_COUNT); + } + }); + Boolean conflictingRef = cachedValue.get(fullyQualifiedName); + if (conflictingRef != null) { + return conflictingRef.booleanValue(); + } + final ConflictingClassReferenceVisitor visitor = new ConflictingClassReferenceVisitor(fullyQualifiedName); element.accept(visitor); - return visitor.isConflictingReferenceFound(); + conflictingRef = visitor.isConflictingReferenceFound(); + cachedValue.put(fullyQualifiedName, conflictingRef); + + return conflictingRef.booleanValue(); } private static class ConflictingClassReferenceVisitor extends JavaRecursiveElementVisitor { @@ -565,12 +578,18 @@ public class ImportUtils { this.fullyQualifiedName = fullyQualifiedName; } + @Override + public void visitElement(PsiElement element) { + if (referenceFound) return; + super.visitElement(element); + } + @Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) { - super.visitReferenceElement(reference); if (referenceFound) { return; } + super.visitReferenceElement(reference); if (reference.getQualifier() != null || reference.getParameterList() != null) return; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index a9b44ac06699..07cb79af2d9d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -229,8 +229,7 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { collectInnerClassNames(reference, references); } Collections.reverse(references); - for (int i = 0, size = references.size(); i < size; i++) { - final PsiJavaCodeReferenceElement aReference = references.get(i); + for (final PsiJavaCodeReferenceElement aReference : references) { final PsiElement referenceTarget = aReference.resolve(); if (!(referenceTarget instanceof PsiClass)) { continue;