Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2013-09-10 15:43:16 +04:00
4 changed files with 91 additions and 55 deletions
@@ -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();
@@ -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();
@@ -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<String, Boolean> cachedValue =
CachedValuesManager.getManager(element.getProject()).getCachedValue(element, new CachedValueProvider<Map<String, Boolean>>() {
@Nullable
@Override
public Result<Map<String, Boolean>> compute() {
return new Result<Map<String, Boolean>>(Collections.synchronizedMap(new HashMap<String, Boolean>()), 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;
@@ -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;