IDEA-92588 (check for AutoCloseable on interface extraction)

This commit is contained in:
Roman Shevchenko
2012-10-10 10:35:51 +02:00
parent 37941c490f
commit 0dc1191c25
10 changed files with 155 additions and 8 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -46,6 +46,7 @@ import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -501,32 +502,50 @@ public abstract class TurnRefsToSuperProcessorBase extends BaseRefactoringProces
}
}
else {
LOG.assertTrue(false);
LOG.error("Unexpected scope: " + declScope);
}
}
else if (variable instanceof PsiResourceVariable) {
final PsiJavaParserFacade facade = JavaPsiFacade.getInstance(myProject).getParserFacade();
checkConstrainingType(type, facade.createTypeFromText(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, variable));
}
}
private void analyzeVarUsage(final PsiElement element) {
PsiType constrainingType = null;
final PsiElement parent = element.getParent();
if (parent instanceof PsiReturnStatement) {
final PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
assert method != null;
constrainingType = method.getReturnType();
} else if (parent instanceof PsiAssignmentExpression) {
}
else if (parent instanceof PsiAssignmentExpression) {
constrainingType = ((PsiAssignmentExpression)parent).getLExpression().getType();
} else if (parent instanceof PsiLocalVariable) {
}
//todo[ann] this works for AImpl->A but fails on List<AImpl> (see testForEach1() and testIDEADEV23807()).
//else if (parent instanceof PsiForeachStatement) {
// final PsiType exprType = ((PsiExpression)element).getType();
// if (!(exprType instanceof PsiArrayType)) {
// final PsiJavaParserFacade facade = JavaPsiFacade.getInstance(myProject).getParserFacade();
// constrainingType = facade.createTypeFromText(CommonClassNames.JAVA_LANG_ITERABLE, parent);
// }
//}
else if (parent instanceof PsiLocalVariable) {
constrainingType = ((PsiLocalVariable)parent).getType();
}
//TODO: I expect more cases here
checkConstrainingType(element, constrainingType);
}
private void checkConstrainingType(PsiElement element, @Nullable PsiType constrainingType) {
if (constrainingType instanceof PsiClassType) {
final PsiClass resolved = ((PsiClassType)constrainingType).resolve();
if (!myClass.equals(resolved)) {
if (resolved == null || !isSuperInheritor(resolved)) {
markNode(element);
}
if (resolved == null || !isSuperInheritor(resolved)) {
markNode(element);
}
}
}
}
@@ -0,0 +1,15 @@
class Test {
void test() throws Exception {
MyIterableImpl r = new MyIterableImpl();
for (String s : r) {
r.length();
}
}
interface MyIterable {
}
static class MyIterableImpl implements MyIterable, Iterable<String> {
public Iterator<String> iterator() { return null; }
}
}
@@ -0,0 +1,15 @@
class Test {
void test() throws Exception {
MyIterableImpl r = new MyIterableImpl();
for (String s : r) {
r.length();
}
}
interface MyIterable {
}
static class MyIterableImpl implements MyIterable, Iterable<String> {
public Iterator<String> iterator() { return null; }
}
}
@@ -0,0 +1,15 @@
class Test {
void test() throws Exception {
MyIterable r = new MyIterableImpl();
for (String s : r) {
r.length();
}
}
interface MyIterable extends Iterable<String> {
}
static class MyIterableImpl implements MyIterable {
public Iterator<String> iterator() { return null; }
}
}
@@ -0,0 +1,15 @@
class Test {
void test() throws Exception {
MyIterableImpl r = new MyIterableImpl();
for (String s : r) {
r.length();
}
}
interface MyIterable extends Iterable<String> {
}
static class MyIterableImpl implements MyIterable {
public Iterator<String> iterator() { return null; }
}
}
@@ -0,0 +1,16 @@
class Test {
void test() throws Exception {
try (MyResourceImpl r = new MyResourceImpl()) {
r.getName();
}
}
interface MyResource {
String getName();
}
static class MyResourceImpl implements MyResource, AutoCloseable {
public String getName() { return ""; }
public void close() throws Exception { }
}
}
@@ -0,0 +1,16 @@
class Test {
void test() throws Exception {
try (MyResourceImpl r = new MyResourceImpl()) {
r.getName();
}
}
interface MyResource {
String getName();
}
static class MyResourceImpl implements MyResource, AutoCloseable {
public String getName() { return ""; }
public void close() throws Exception { }
}
}
@@ -0,0 +1,16 @@
class Test {
void test() throws Exception {
try (MyResource r = new MyResourceImpl()) {
r.getName();
}
}
interface MyResource extends AutoCloseable {
String getName();
}
static class MyResourceImpl implements MyResource {
public String getName() { return ""; }
public void close() throws Exception { }
}
}
@@ -0,0 +1,16 @@
class Test {
void test() throws Exception {
try (MyResourceImpl r = new MyResourceImpl()) {
r.getName();
}
}
interface MyResource extends AutoCloseable {
String getName();
}
static class MyResourceImpl implements MyResource {
public String getName() { return ""; }
public void close() throws Exception { }
}
}
@@ -53,12 +53,16 @@ public class TurnRefsToSuperTest extends MultiFileTestCase {
public void testTypeArgumentsRH1() throws Exception { doTest("IImpl", "I", false); }
public void testAnonymousWithTypeArguments() throws Exception { doTest("Clazz", "IntF", false); }
public void testTypeArgumentsParam() throws Exception { doTest("Clazz", "IntF", false); }
public void testTryWithResources1() throws Exception { doTest("Test.MyResourceImpl", "Test.MyResource", false); }
public void testTryWithResources2() throws Exception { doTest("Test.MyResourceImpl", "Test.MyResource", false); }
//todo[ann] fix and uncomment
//public void testStaticCallArguments() throws Exception { doTest("Impl", "Int", false); }
//public void testListArgs() throws Exception { doTest("Impl", "Int", false); }
//public void testCovariantReturnTypes() throws Exception { doTest("Impl", "Int", false); }
//public void testNewExpr() throws Exception { doTest("Impl", "Int", false); }
//public void testForEach1() throws Exception { doTest("Test.MyIterableImpl", "Test.MyIterable", false); }
//public void testForEach2() throws Exception { doTest("Test.MyIterableImpl", "Test.MyIterable", false); }
private void doTest(@NonNls final String className, @NonNls final String superClassName, final boolean replaceInstanceOf) throws Exception {
doTest(new PerformAction() {