IDEA-161607 Allow to introduce variable in the head of try-with-resources block

This commit is contained in:
Tagir Valeev
2018-12-24 15:03:11 +07:00
parent 81091e7748
commit ce8518f7d6
8 changed files with 64 additions and 20 deletions
@@ -33,7 +33,8 @@ public class JavaAnchorProvider extends SmartPointerAnchorProvider {
if (element instanceof PsiAnonymousClass) {
return ((PsiAnonymousClass)element).getBaseClassReference().getReferenceNameElement();
}
if (element instanceof PsiClass || element instanceof PsiMethod || element instanceof PsiVariable) {
if (element instanceof PsiClass || element instanceof PsiMethod ||
(element instanceof PsiVariable && !(element instanceof PsiLocalVariable))) {
return ((PsiNameIdentifierOwner)element).getNameIdentifier();
}
if (element instanceof PsiImportList) {
@@ -426,7 +426,7 @@ public class JavaVariableInplaceIntroducer extends AbstractJavaInplaceIntroducer
PsiVariable variable = VariableExtractor
.introduce(myProject, myExpr, myEditor, myChosenAnchor.getElement(), getOccurrences(), mySettings);
SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(myProject);
if (variable instanceof PsiField) {
if (variable instanceof PsiField || variable instanceof PsiResourceVariable) {
myPointer = smartPointerManager.createSmartPsiElementPointer(variable);
}
else {
@@ -12,6 +12,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.FieldConflictsResolver;
@@ -199,6 +200,12 @@ class VariableExtractor {
}
}
}
if (anchor instanceof PsiResourceListElement) {
PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)declaration;
PsiLocalVariable localVariable = (PsiLocalVariable)declarationStatement.getDeclaredElements()[0];
PsiResourceVariable resourceVariable = RefactoringUtil.createResourceVariable(anchor.getProject(), localVariable, initializer);
return anchor.replace(resourceVariable);
}
return anchor.getParent().addBefore(declaration, anchor);
}
@@ -252,6 +259,14 @@ class VariableExtractor {
return firstOccurrence;
}
}
if (anchor instanceof PsiTryStatement && firstOccurrence != null) {
PsiResourceList resourceList = ((PsiTryStatement)anchor).getResourceList();
PsiElement parent = firstOccurrence.getParent();
if (resourceList != null && parent instanceof PsiResourceExpression && parent.getParent() == resourceList
&& InheritanceUtil.isInheritor(firstOccurrence.getType(), CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE)) {
return parent;
}
}
if (anchor.getParent() instanceof PsiSwitchLabeledRuleStatement) {
return ExpressionUtils.getTopLevelExpression(expr);
}
@@ -1023,6 +1023,23 @@ public class RefactoringUtil {
return null;
}
public static PsiResourceVariable createResourceVariable(@NotNull Project project, PsiLocalVariable variable, PsiExpression initializer) {
PsiTryStatement tryStatement = (PsiTryStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText("try (X x = null){}", variable);
PsiResourceList resourceList = tryStatement.getResourceList();
assert resourceList != null;
PsiResourceVariable resourceVariable = (PsiResourceVariable)resourceList.iterator().next();
resourceVariable.getTypeElement().replace(variable.getTypeElement());
PsiIdentifier nameIdentifier = resourceVariable.getNameIdentifier();
assert nameIdentifier != null;
PsiIdentifier oldIdentifier = variable.getNameIdentifier();
assert oldIdentifier != null;
nameIdentifier.replace(oldIdentifier);
if (initializer != null) {
resourceVariable.setInitializer(initializer);
}
return resourceVariable;
}
public interface ImplicitConstructorUsageVisitor {
void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor);
@@ -0,0 +1,11 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
class Foo {
void test(File f) throws IOException {
try(FileInputStream temp = new FileInputStream(f)) {
}
}
}
@@ -0,0 +1,11 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
class Foo {
void test(File f) throws IOException {
try(new <caret>FileInputStream(f)) {
}
}
}
@@ -275,6 +275,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int"));
}
public void testInsideTryWithResources() {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "java.io.FileInputStream"));
}
public void testInsideForLoop() {
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int"));
}
@@ -28,6 +28,7 @@ import com.intellij.psi.util.FileTypeUtils;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.SmartList;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
@@ -387,7 +388,8 @@ public class TooBroadScopeInspection extends BaseInspection {
CommentTracker tracker = new CommentTracker();
if (commonParent instanceof PsiTryStatement) {
PsiElement resourceReference = referenceElement.getParent();
PsiResourceVariable resourceVariable = createResourceVariable(project, variable, initializer != null ? tracker.markUnchanged(initializer) : null);
PsiResourceVariable resourceVariable = RefactoringUtil
.createResourceVariable(project, variable, initializer != null ? tracker.markUnchanged(initializer) : null);
newDeclaration = resourceReference.getParent().addBefore(resourceVariable, resourceReference);
resourceReference.delete();
}
@@ -432,23 +434,6 @@ public class TooBroadScopeInspection extends BaseInspection {
}
}
private PsiResourceVariable createResourceVariable(@NotNull Project project, PsiLocalVariable variable, PsiExpression initializer) {
PsiTryStatement tryStatement = (PsiTryStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText("try (X x = null){}", variable);
PsiResourceList resourceList = tryStatement.getResourceList();
assert resourceList != null;
PsiResourceVariable resourceVariable = (PsiResourceVariable)resourceList.iterator().next();
resourceVariable.getTypeElement().replace(variable.getTypeElement());
PsiIdentifier nameIdentifier = resourceVariable.getNameIdentifier();
assert nameIdentifier != null;
PsiIdentifier oldIdentifier = variable.getNameIdentifier();
assert oldIdentifier != null;
nameIdentifier.replace(oldIdentifier);
if (initializer != null) {
resourceVariable.setInitializer(initializer);
}
return resourceVariable;
}
private void removeOldVariable(@NotNull PsiVariable variable, CommentTracker tracker) {
final PsiDeclarationStatement declaration = (PsiDeclarationStatement)variable.getParent();
if (declaration == null) {