mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Try-with-resource support: reuse variable quick fix
This commit is contained in:
+45
-39
@@ -27,21 +27,19 @@ import com.intellij.psi.scope.processor.VariablesNotProcessor;
|
||||
import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: cdr
|
||||
* @author cdr
|
||||
* Date: Nov 20, 2002
|
||||
* Time: 3:01:25 PM
|
||||
* To change this template use Options | File Templates.
|
||||
*/
|
||||
public class ReuseVariableDeclarationFix implements IntentionAction {
|
||||
private final PsiVariable variable;
|
||||
private final PsiIdentifier identifier;
|
||||
private final PsiVariable myVariable;
|
||||
private final PsiIdentifier myIdentifier;
|
||||
|
||||
public ReuseVariableDeclarationFix(PsiVariable variable, PsiIdentifier identifier) {
|
||||
this.variable = variable;
|
||||
this.identifier = identifier;
|
||||
public ReuseVariableDeclarationFix(final PsiVariable variable, final PsiIdentifier identifier) {
|
||||
this.myVariable = variable;
|
||||
this.myIdentifier = identifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -51,55 +49,63 @@ public class ReuseVariableDeclarationFix implements IntentionAction {
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return QuickFixBundle.message("reuse.variable.declaration.text", variable.getName());
|
||||
return QuickFixBundle.message("reuse.variable.declaration.text", myVariable.getName());
|
||||
}
|
||||
|
||||
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
|
||||
|
||||
PsiVariable previousVariable = findPreviousVariable();
|
||||
return
|
||||
variable != null
|
||||
&& variable.isValid()
|
||||
&& variable instanceof PsiLocalVariable
|
||||
&& previousVariable != null
|
||||
&& Comparing.equal(previousVariable.getType(), variable.getType())
|
||||
&& identifier != null
|
||||
&& identifier.isValid()
|
||||
&& variable.getManager().isInProject(variable);
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
|
||||
final PsiVariable previousVariable = findPreviousVariable();
|
||||
return myVariable != null &&
|
||||
myVariable.isValid() &&
|
||||
myVariable instanceof PsiLocalVariable &&
|
||||
!(myVariable.getParent() instanceof PsiResource && myVariable.getInitializer() == null) &&
|
||||
previousVariable != null &&
|
||||
Comparing.equal(previousVariable.getType(), myVariable.getType()) &&
|
||||
myIdentifier != null &&
|
||||
myIdentifier.isValid() &&
|
||||
myVariable.getManager().isInProject(myVariable);
|
||||
}
|
||||
|
||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||
PsiVariable refVariable = findPreviousVariable();
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
final PsiVariable refVariable = findPreviousVariable();
|
||||
if (refVariable == null) return;
|
||||
if (!CodeInsightUtil.preparePsiElementsForWrite(variable, refVariable)) return;
|
||||
PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false);
|
||||
if (variable.getInitializer() == null) {
|
||||
variable.delete();
|
||||
|
||||
if (!CodeInsightUtil.preparePsiElementsForWrite(myVariable, refVariable)) return;
|
||||
|
||||
final PsiExpression initializer = myVariable.getInitializer();
|
||||
if (initializer == null) {
|
||||
myVariable.delete();
|
||||
return;
|
||||
}
|
||||
PsiDeclarationStatement declaration = (PsiDeclarationStatement) variable.getParent();
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(variable.getProject()).getElementFactory();
|
||||
PsiStatement statement = factory.createStatementFromText(variable.getName() + " = " + variable.getInitializer().getText()+";", variable);
|
||||
declaration.replace(statement);
|
||||
|
||||
PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false);
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myVariable.getProject()).getElementFactory();
|
||||
final PsiElement replacement;
|
||||
final PsiElement parent = myVariable.getParent();
|
||||
if (parent instanceof PsiResource) {
|
||||
replacement = factory.createResourceFromText(myVariable.getName() + " = " + initializer.getText(), null);
|
||||
}
|
||||
else {
|
||||
replacement = factory.createStatementFromText(myVariable.getName() + " = " + initializer.getText() + ";", null);
|
||||
}
|
||||
parent.replace(replacement);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiVariable findPreviousVariable() {
|
||||
PsiElement scope = variable.getParent();
|
||||
PsiElement scope = myVariable.getParent();
|
||||
while (scope != null) {
|
||||
if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break;
|
||||
scope = scope.getParent();
|
||||
}
|
||||
if (scope == null) return null;
|
||||
VariablesNotProcessor proc = new VariablesNotProcessor(variable, false);
|
||||
PsiScopesUtil.treeWalkUp(proc, identifier, scope);
|
||||
|
||||
if(proc.size() > 0)
|
||||
return proc.getResult(0);
|
||||
return null;
|
||||
final VariablesNotProcessor proc = new VariablesNotProcessor(myVariable, false);
|
||||
PsiScopesUtil.treeWalkUp(proc, myIdentifier, scope);
|
||||
return proc.size() > 0 ? proc.getResult(0) : null;
|
||||
}
|
||||
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,6 +64,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
};
|
||||
|
||||
private static final JavaParserUtil.ParserWrapper RESOURCE = new JavaParserUtil.ParserWrapper() {
|
||||
@Override
|
||||
public void parse(final PsiBuilder builder) {
|
||||
DeclarationParser.parseResource(builder);
|
||||
}
|
||||
};
|
||||
|
||||
private static final JavaParserUtil.ParserWrapper TYPE = new JavaParserUtil.ParserWrapper() {
|
||||
@Override
|
||||
public void parse(final PsiBuilder builder) {
|
||||
@@ -162,6 +169,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation createAnnotationFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -172,16 +180,19 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocTag createDocTagFromText(@NotNull final String text) throws IncorrectOperationException {
|
||||
return createDocCommentFromText(join("/**\n", text, "\n */")).getTags()[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocTag createDocTagFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
return createDocTagFromText(text);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocComment createDocCommentFromText(@NotNull final String text) throws IncorrectOperationException {
|
||||
final PsiMethod method = createMethodFromText(join(text, "void m();"), null);
|
||||
final PsiDocComment comment = method.getDocComment();
|
||||
@@ -190,11 +201,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiDocComment createDocCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
return createDocCommentFromText(text);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass createClassFromText(@NotNull final String body, final PsiElement context) throws IncorrectOperationException {
|
||||
final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { ", body, " }"));
|
||||
final PsiClass[] classes = aFile.getClasses();
|
||||
@@ -205,6 +218,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiField createFieldFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -215,6 +229,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false, level), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -225,12 +240,14 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public final PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final LanguageLevel level = LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel();
|
||||
return createMethodFromText(text, context, level);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -241,11 +258,24 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
if (!(element instanceof PsiResource)) {
|
||||
throw new IncorrectOperationException("Incorrect resource \"" + text + "\".");
|
||||
}
|
||||
return (PsiResource)element;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType createTypeFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
return createTypeInner(text, context, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeElement createTypeElementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final boolean multiCatch = context instanceof PsiParameter &&
|
||||
context.getParent() instanceof PsiCatchSection &&
|
||||
@@ -271,6 +301,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiJavaCodeReferenceElement createReferenceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final boolean isStaticImport = context instanceof PsiImportStaticStatement &&
|
||||
!((PsiImportStaticStatement)context).isOnDemand();
|
||||
@@ -284,6 +315,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, true), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -294,6 +326,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiStatement createStatementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -304,6 +337,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiExpression createExpressionFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -320,6 +354,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -330,6 +365,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiComment createCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final PsiJavaFile aFile = createDummyJavaFile(text);
|
||||
for (PsiElement aChildren : aFile.getChildren()) {
|
||||
@@ -347,6 +383,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
|
||||
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, false), context);
|
||||
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
|
||||
@@ -357,6 +394,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, @NotNull final String exceptionName,
|
||||
final PsiElement context) throws IncorrectOperationException {
|
||||
final String text = join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}");
|
||||
@@ -396,6 +434,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
|
||||
psiCatchSection.getCatchBlock().replace(codeBlockFromText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType createPrimitiveType(@NotNull final String text, @NotNull final PsiAnnotation[] annotations) throws IncorrectOperationException {
|
||||
final PsiPrimitiveType primitiveType = getPrimitiveType(text);
|
||||
if (primitiveType == null) {
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PsiResourceImpl extends CompositePsiElement implements PsiResource
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
final PsiElement element = getResourceElement();
|
||||
final PsiElement element = getFirstChild();
|
||||
if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName();
|
||||
if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString();
|
||||
return "";
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Reuse previous variable 'r' declaration" "true"
|
||||
import java.io.*;
|
||||
|
||||
class a {
|
||||
static class MyResource implements AutoCloseable {
|
||||
public void close() { }
|
||||
}
|
||||
|
||||
void m() {
|
||||
MyResource r;
|
||||
try (r = new MyResource()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Reuse previous variable 'r' declaration" "true"
|
||||
import java.io.*;
|
||||
|
||||
class a {
|
||||
static class MyResource implements AutoCloseable {
|
||||
public void close() { }
|
||||
}
|
||||
|
||||
void m() {
|
||||
MyResource r;
|
||||
try (MyResource <caret>r = new MyResource()) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-5
@@ -1,9 +1,7 @@
|
||||
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
|
||||
|
||||
public class ReuseVariableDeclarationtTest extends LightQuickFixTestCase {
|
||||
public class ReuseVariableDeclarationTest extends LightQuickFixTestCase {
|
||||
|
||||
public void test() throws Exception { doAllTests(); }
|
||||
|
||||
@@ -11,6 +9,4 @@ public class ReuseVariableDeclarationtTest extends LightQuickFixTestCase {
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/reuseVariableDeclaration";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -116,6 +116,17 @@ public interface PsiJavaParserFacade extends PsiParserFacade {
|
||||
@NotNull
|
||||
PsiParameter createParameterFromText(@NotNull @NonNls String text, PsiElement context) throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* Creates a Java try-resource from the specified text.
|
||||
*
|
||||
* @param text the text of the resource to create.
|
||||
* @param context the PSI element used as context for resolving references from the resource.
|
||||
* @return the created resource instance.
|
||||
* @throws com.intellij.util.IncorrectOperationException if the text is not a valid resource definition.
|
||||
*/
|
||||
@NotNull
|
||||
PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException;
|
||||
|
||||
/**
|
||||
* Creates a Java type from the specified text.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user