IDEA-23612 Handle overriding builtin exceptions.

This commit is contained in:
peter
2015-05-16 08:27:59 +02:00
parent f63e653273
commit 1f496b41ca
3 changed files with 75 additions and 14 deletions
@@ -276,13 +276,15 @@ public class GenerateMembersUtil {
substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor);
substituteParameters(factory, codeStyleManager, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor, target);
copyDocComment(sourceMethod, resultMethod, factory);
final List<PsiClassType> thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes());
GlobalSearchScope scope = sourceMethod.getResolveScope();
final List<PsiClassType> thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes(),
scope);
if (target instanceof PsiClass) {
final PsiClass[] supers = ((PsiClass)target).getSupers();
for (PsiClass aSuper : supers) {
final PsiMethod psiMethod = aSuper.findMethodBySignature(sourceMethod, true);
if (psiMethod != null && psiMethod != sourceMethod) {
ExceptionUtil.retainExceptions(thrownTypes, ExceptionUtil.collectSubstituted(TypeConversionUtil.getSuperClassSubstitutor(aSuper, (PsiClass)target, PsiSubstitutor.EMPTY), psiMethod.getThrowsList().getReferencedTypes()));
ExceptionUtil.retainExceptions(thrownTypes, ExceptionUtil.collectSubstituted(TypeConversionUtil.getSuperClassSubstitutor(aSuper, (PsiClass)target, PsiSubstitutor.EMPTY), psiMethod.getThrowsList().getReferencedTypes(), scope));
}
}
}
@@ -22,12 +22,14 @@ import com.intellij.openapi.util.RecursionGuard;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
@@ -187,7 +189,7 @@ public class ExceptionUtil {
PsiMethod method = (PsiMethod)resolveResult.getElement();
if (method != null) {
addExceptions(result, getExceptionsByMethod(method, resolveResult.getSubstitutor()));
addExceptions(result, getExceptionsByMethod(method, resolveResult.getSubstitutor(), element));
}
addExceptions(result, getThrownExceptions(element.getChildren()));
@@ -196,12 +198,16 @@ public class ExceptionUtil {
}
@NotNull
private static List<PsiClassType> getExceptionsByMethod(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor) {
List<PsiClassType> result = ContainerUtil.newArrayList();
private static List<PsiClassType> getExceptionsByMethod(@NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor,
@NotNull PsiElement place) {
PsiClassType[] referenceTypes = method.getThrowsList().getReferencedTypes();
if (referenceTypes.length == 0) return Collections.emptyList();
GlobalSearchScope scope = place.getResolveScope();
List<PsiClassType> result = ContainerUtil.newArrayList();
for (PsiType type : referenceTypes) {
type = substitutor.substitute(type);
type = PsiClassImplUtil.correctType(substitutor.substitute(type), scope);
if (type instanceof PsiClassType) {
result.add((PsiClassType)type);
}
@@ -449,13 +455,14 @@ public class ExceptionUtil {
}
});
if (candidates.size() > 1) {
final List<PsiClassType> ex = collectSubstituted(substitutor, thrownExceptions);
GlobalSearchScope scope = methodCall.getResolveScope();
final List<PsiClassType> ex = collectSubstituted(substitutor, thrownExceptions, scope);
for (Pair<PsiMethod, PsiSubstitutor> pair : candidates) {
final PsiClassType[] exceptions = pair.first.getThrowsList().getReferencedTypes();
if (exceptions.length == 0) {
return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, PsiClassType.EMPTY_ARRAY);
}
retainExceptions(ex, collectSubstituted(pair.second, exceptions));
retainExceptions(ex, collectSubstituted(pair.second, exceptions, scope));
}
return getUnhandledExceptions(methodCall, topElement, PsiSubstitutor.EMPTY, ex.toArray(new PsiClassType[ex.size()]));
}
@@ -512,10 +519,10 @@ public class ExceptionUtil {
ex.addAll(replacement);
}
public static List<PsiClassType> collectSubstituted(PsiSubstitutor substitutor, PsiClassType[] thrownExceptions) {
public static List<PsiClassType> collectSubstituted(PsiSubstitutor substitutor, PsiClassType[] thrownExceptions, GlobalSearchScope scope) {
final List<PsiClassType> ex = new ArrayList<PsiClassType>();
for (PsiClassType thrownException : thrownExceptions) {
final PsiType psiType = substitutor.substitute(thrownException);
final PsiType psiType = PsiClassImplUtil.correctType(substitutor.substitute(thrownException), scope);
if (psiType instanceof PsiClassType) {
ex.add((PsiClassType)psiType);
}
@@ -527,7 +534,7 @@ public class ExceptionUtil {
public static List<PsiClassType> getCloserExceptions(@NotNull PsiResourceVariable resource) {
PsiMethod method = PsiUtil.getResourceCloserMethod(resource);
PsiSubstitutor substitutor = PsiUtil.resolveGenericsClassInType(resource.getType()).getSubstitutor();
return method != null ? getExceptionsByMethod(method, substitutor) : Collections.<PsiClassType>emptyList();
return method != null ? getExceptionsByMethod(method, substitutor, resource) : Collections.<PsiClassType>emptyList();
}
@NotNull
@@ -593,7 +600,7 @@ public class ExceptionUtil {
List<PsiClassType> result = ContainerUtil.newArrayList();
for (PsiClassType referencedType : referencedTypes) {
final PsiType type = GenericsUtil.eliminateWildcards(substitutor.substitute(referencedType), false);
final PsiType type = PsiClassImplUtil.correctType(GenericsUtil.eliminateWildcards(substitutor.substitute(referencedType), false), element.getResolveScope());
if (!(type instanceof PsiClassType)) continue;
PsiClassType classType = (PsiClassType)type;
PsiClass exceptionClass = ((PsiClassType)type).resolve();
@@ -14,11 +14,16 @@
* limitations under the License.
*/
package com.intellij.codeInsight
import com.intellij.openapi.module.JavaModuleType
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ModuleSourceOrderEntry
import com.intellij.openapi.roots.OrderEntry
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.util.Consumer
import com.intellij.util.containers.ContainerUtil
/**
* @author peter
*/
@@ -95,4 +100,51 @@ class Class3 {
ModuleRootModificationUtil.addDependency(myModule, mod1)
ModuleRootModificationUtil.addDependency(myModule, mod2)
}
public void testOverridingJdkExceptions() {
def dep = PsiTestUtil.addModule(project, JavaModuleType.moduleType, "dep", myFixture.tempDirFixture.findOrCreateDir("dep"))
ModuleRootModificationUtil.setModuleSdk(dep, ModuleRootManager.getInstance(myModule).sdk)
ModuleRootModificationUtil.updateModel(myModule, { model ->
model.addModuleOrderEntry(dep)
List<OrderEntry> entries = model.orderEntries as List
def srcEntry = ContainerUtil.findInstance(entries, ModuleSourceOrderEntry)
assert srcEntry
model.rearrangeOrderEntries(([srcEntry] + (entries - srcEntry)) as OrderEntry[])
} as Consumer)
myFixture.addFileToProject "java/lang/IllegalArgumentException.java", '''
package java.lang;
public class IllegalArgumentException extends Exception { }
'''
myFixture.addFileToProject 'dep/foo/Foo.java', '''
package foo;
public class Foo {
public static void libraryMethod() throws IllegalArgumentException {}
}
'''
myFixture.configureFromExistingVirtualFile(myFixture.addFileToProject('Bar.java', '''
class Bar {
void caught() {
try {
foo.Foo.libraryMethod();
} catch (IllegalArgumentException e) {}
}
void uncaught() {
<error descr="Unhandled exception: java.lang.IllegalArgumentException">foo.Foo.libraryMethod();</error>
}
}
''').virtualFile)
myFixture.checkHighlighting()
}
}