IDEA-81171 (Surround AutoCloseable - initial implementation)

This commit is contained in:
Roman Shevchenko
2012-02-12 23:49:34 +01:00
parent 3ebed051c8
commit 668afd0260
11 changed files with 206 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class SurroundAutoCloseableAction extends PsiElementBaseIntentionAction {
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) {
if (!element.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return false;
if (!PsiUtil.getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_1_7)) return false;
final PsiLocalVariable variable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
if (variable == null) return false;
final PsiExpression initializer = variable.getInitializer();
if (initializer == null) return false;
final PsiElement declaration = variable.getParent();
if (!(declaration instanceof PsiDeclarationStatement)) return false;
final PsiElement codeBlock = declaration.getParent();
if (!(codeBlock instanceof PsiCodeBlock)) return false;
final PsiType type = variable.getType();
if (!(type instanceof PsiClassType)) return false;
final PsiClass aClass = ((PsiClassType)type).resolve();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project));
if (!InheritanceUtil.isInheritorOrSelf(aClass, autoCloseable, true)) return false;
return true;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
final PsiLocalVariable variable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class);
if (variable == null) return;
final PsiExpression initializer = variable.getInitializer();
if (initializer == null) return;
final PsiElement declaration = variable.getParent();
if (!(declaration instanceof PsiDeclarationStatement)) return;
final PsiElement codeBlock = declaration.getParent();
if (!(codeBlock instanceof PsiCodeBlock)) return;
final String text = "try (" + variable.getTypeElement().getText() + " " + variable.getName() + " = " + initializer.getText() + ") {}";
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiStatement armStatement = factory.createStatementFromText(text, codeBlock);
final PsiElement newElement = declaration.replace(armStatement);
final PsiElement formattedElement = CodeStyleManager.getInstance(project).reformat(newElement);
final PsiCodeBlock tryBlock = ((PsiTryStatement)formattedElement).getTryBlock();
if (tryBlock != null) {
final PsiJavaToken brace = tryBlock.getLBrace();
if (brace != null) {
editor.getCaretModel().moveToOffset(brace.getTextOffset() + 1);
}
}
}
@NotNull
@Override
public String getFamilyName() {
return CodeInsightBundle.message("intention.surround.resource.with.ARM.block");
}
@NotNull
@Override
public String getText() {
return getFamilyName();
}
}

View File

@@ -0,0 +1,24 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.*;
import java.net.*;
class C {
public void read(URLConnection connection) {
<caret>InputStream stream = connection.getInputStream();
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.*;
import java.net.*;
class C {
public void read(URLConnection connection) {
try (InputStream stream = connection.getInputStream()) {<caret>
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
public class SurroundAutoCloseableActionTest extends JavaCodeInsightFixtureTestCase {
private String myIntention;
@Override
public void setUp() throws Exception {
super.setUp();
myIntention = CodeInsightBundle.message("intention.surround.resource.with.ARM.block");
}
@Override
protected void tuneFixture(final JavaModuleFixtureBuilder moduleBuilder) throws Exception {
moduleBuilder.setLanguageLevel(LanguageLevel.JDK_1_7);
}
public void testSimple() throws Exception {
CodeInsightTestUtil.doIntentionTest(myFixture, myIntention, "Simple.java", "Simple_after.java");
}
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/surroundAutoCloseable/";
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -169,6 +169,7 @@ intention.replace.concatenation.with.formatted.output.family=Replace Concatenati
intention.replace.concatenation.with.formatted.output.text=Replace '+' with 'java.text.MessageFormat.format()'
intention.color.chooser.dialog=Choose Color
intention.convert.to.basic.latin=Convert to Basic Latin
intention.surround.resource.with.ARM.block=Surround with try-with-resources block
dialog.create.field.from.parameter.title=Create Field
dialog.create.field.from.parameter.already.exists.text=Use existing field ''{0}''?
dialog.create.field.from.parameter.already.exists.title=Field Already Exists

View File

@@ -0,0 +1,2 @@
try (InputStream stream = connection.getInputStream()) {
}

View File

@@ -0,0 +1 @@
<spot>InputStream stream = connection.getInputStream();</spot>

View File

@@ -0,0 +1,5 @@
<html>
<body>
This intention wraps locals variable of AutoCloseable type into try-with-resources statement.
</body>
</html>

View File

@@ -632,6 +632,7 @@
<className>com.intellij.codeInsight.intention.impl.ConcatenationToMessageFormatAction</className>
<category>I18N</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.ConvertToBasicLatinAction</className>
<category>I18N</category>
@@ -693,6 +694,11 @@
<category>Strings</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.intention.impl.SurroundAutoCloseableAction</className>
<category>Declaration</category>
</intentionAction>
<lang.parserDefinition language="JAVA" implementationClass="com.intellij.lang.java.JavaParserDefinition"/>
<lang.refactoringSupport language="JAVA" implementationClass="com.intellij.lang.java.JavaRefactoringSupportProvider"/>