mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
IDEA-103114 ("Surround with try-with-resources" fixed to not lose last declaration element)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -31,9 +31,8 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -113,78 +112,56 @@ public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<PsiElement> moveStatements(@NotNull final PsiElement first, final PsiElement last, final PsiTryStatement statement) {
|
||||
final PsiCodeBlock tryBlock = statement.getTryBlock();
|
||||
private static List<PsiElement> moveStatements(@NotNull PsiElement first, PsiElement last, PsiTryStatement statement) {
|
||||
PsiCodeBlock tryBlock = statement.getTryBlock();
|
||||
assert tryBlock != null : statement.getText();
|
||||
final PsiJavaToken rBrace = tryBlock.getRBrace();
|
||||
assert rBrace != null : statement.getText();
|
||||
PsiElement parent = statement.getParent();
|
||||
|
||||
final PsiElement parent = statement.getParent();
|
||||
final LocalSearchScope scope = new LocalSearchScope(parent);
|
||||
List<PsiElement> toFormat = null, toDelete = null;
|
||||
|
||||
final PsiElement stopAt = last.getNextSibling();
|
||||
List<PsiElement> toFormat = new SmartList<PsiElement>();
|
||||
PsiElement stopAt = last.getNextSibling();
|
||||
for (PsiElement child = first; child != null && child != stopAt; child = child.getNextSibling()) {
|
||||
if (!(child instanceof PsiDeclarationStatement)) continue;
|
||||
|
||||
final PsiElement[] declaredElements = ((PsiDeclarationStatement)child).getDeclaredElements();
|
||||
int varsProcessed = 0;
|
||||
for (PsiElement declared : declaredElements) {
|
||||
PsiElement anchor = child;
|
||||
for (PsiElement declared : ((PsiDeclarationStatement)child).getDeclaredElements()) {
|
||||
if (!(declared instanceof PsiLocalVariable)) continue;
|
||||
|
||||
final boolean contained = ReferencesSearch.search(declared, scope).forEach(new Processor<PsiReference>() {
|
||||
final int endOffset = last.getTextRange().getEndOffset();
|
||||
boolean contained = ReferencesSearch.search(declared, new LocalSearchScope(parent)).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
return reference.getElement().getTextOffset() <= last.getTextRange().getEndOffset();
|
||||
return reference.getElement().getTextOffset() <= endOffset;
|
||||
}
|
||||
});
|
||||
|
||||
if (!contained) {
|
||||
final PsiLocalVariable var = (PsiLocalVariable)declared;
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(statement.getProject());
|
||||
final String name = var.getName();
|
||||
PsiLocalVariable var = (PsiLocalVariable)declared;
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(statement.getProject());
|
||||
|
||||
String name = var.getName();
|
||||
assert name != null : child.getText();
|
||||
toFormat.add(parent.addBefore(factory.createVariableDeclarationStatement(name, var.getType(), null), statement));
|
||||
|
||||
toFormat = plus(toFormat, parent.addBefore(factory.createVariableDeclarationStatement(name, var.getType(), null), statement));
|
||||
PsiExpression varInit = var.getInitializer();
|
||||
assert varInit != null : child.getText();
|
||||
String varAssignText = name + " = " + varInit.getText() + ";";
|
||||
anchor = parent.addAfter(factory.createStatementFromText(varAssignText, parent), anchor);
|
||||
|
||||
final PsiExpression varInit = var.getInitializer();
|
||||
if (varInit != null) {
|
||||
final String varAssignText = name + " = " + varInit.getText() + ";";
|
||||
parent.addBefore(factory.createStatementFromText(varAssignText, parent), child.getNextSibling());
|
||||
}
|
||||
|
||||
++varsProcessed;
|
||||
toDelete = plus(toDelete, declared);
|
||||
declared.delete();
|
||||
var.delete();
|
||||
}
|
||||
}
|
||||
|
||||
if (varsProcessed == declaredElements.length) {
|
||||
toDelete = plus(toDelete, child);
|
||||
if (child == last && !child.isValid()) {
|
||||
last = anchor;
|
||||
}
|
||||
}
|
||||
|
||||
if (toDelete != null) {
|
||||
for (PsiElement element : toDelete) {
|
||||
if (element.isValid()) {
|
||||
element.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tryBlock.addRangeBefore(first, last, rBrace);
|
||||
tryBlock.addRangeBefore(first, last, tryBlock.getRBrace());
|
||||
parent.deleteChildRange(first, last);
|
||||
|
||||
return toFormat;
|
||||
}
|
||||
|
||||
private static List<PsiElement> plus(@Nullable List<PsiElement> list, PsiElement element) {
|
||||
if (list == null) list = ContainerUtil.newArrayList();
|
||||
list.add(element);
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
class C {
|
||||
void m(File file) throws IOException {
|
||||
<caret>FileInputStream stream = new FileInputStream(file);
|
||||
stream.getFD();
|
||||
FileChannel channel1 = stream.getChannel(), channel2 = stream.getChannel();
|
||||
channel1.close();
|
||||
channel2.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
class C {
|
||||
void m(File file) throws IOException {
|
||||
FileChannel channel1;
|
||||
FileChannel channel2;
|
||||
try (FileInputStream stream = new FileInputStream(file)) {
|
||||
stream.getFD();
|
||||
channel1 = stream.getChannel();
|
||||
channel2 = stream.getChannel();
|
||||
}
|
||||
channel1.close();
|
||||
channel2.close();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -39,6 +39,7 @@ public class SurroundAutoCloseableActionTest extends JavaCodeInsightFixtureTestC
|
||||
public void testSimple() { doTest(); }
|
||||
public void testUsage() { doTest(); }
|
||||
public void testMixedUsages() { doTest(); }
|
||||
public void testLastDeclaration() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
String name = getTestName(false);
|
||||
|
||||
Reference in New Issue
Block a user