Add 'finally' block fix (part of IDEA-200560)

This commit is contained in:
Tagir Valeev
2018-10-17 12:16:46 +07:00
parent 04aa2fbda7
commit 3eaa3ff64f
8 changed files with 119 additions and 26 deletions

View File

@@ -259,5 +259,6 @@
enabledByDefault="true" level="INFORMATION"
key="inspection.objects.equals.can.be.simplified.display.name" bundle="messages.InspectionsBundle"
implementationClass="com.siyeh.ig.style.ObjectsEqualsCanBeSimplifiedInspection"/>
<errorQuickFixProvider implementation="com.intellij.codeInsight.daemon.impl.analysis.JavaErrorQuickFixProvider"/>
</extensions>
</idea-plugin>

View File

@@ -0,0 +1,20 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.AddFinallyFix;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiTryStatement;
import org.jetbrains.annotations.NotNull;
public class JavaErrorQuickFixProvider implements ErrorQuickFixProvider {
@Override
public void registerErrorQuickFix(@NotNull PsiErrorElement errorElement, @NotNull HighlightInfo highlightInfo) {
if (errorElement.getParent() instanceof PsiTryStatement && errorElement.getErrorDescription().equals(
JavaErrorMessages.message("expected.catch.or.finally"))) {
QuickFixAction.registerQuickFixAction(highlightInfo, new AddFinallyFix((PsiTryStatement)errorElement.getParent()));
}
}
}

View File

@@ -0,0 +1,47 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.intention;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class AddFinallyFix extends BaseIntentionAction {
private final PsiTryStatement myTryStatement;
public AddFinallyFix(PsiTryStatement statement) {
myTryStatement = statement;
}
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getFamilyName() {
return QuickFixBundle.message("add.finally.block.family");
}
@NotNull
@Override
public String getText() {
return getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PsiJavaFile)) return false;
if (!myTryStatement.isValid()) return false;
if (myTryStatement.getFinallyBlock() != null) return false;
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiStatement replacement =
JavaPsiFacade.getElementFactory(project).createStatementFromText(myTryStatement.getText() + "finally {}", myTryStatement);
myTryStatement.replace(replacement);
}
}

View File

@@ -8,6 +8,7 @@ add.default.constructor.family=Add Default Constructor
add.default.constructor.text=Add {0} no-args constructor to {1}
add.catch.clause.family=Add exception to catch clause
add.catch.clause.text=Add 'catch' clause(s)
add.finally.block.family=Add 'finally' block
add.exception.to.throws.inherited.method.warning.text=Method ''{0}'' is inherited.\n\
Do you want to add exceptions to method signatures in the whole method hierarchy?
method.is.inherited.warning.title=Method Is Inherited

View File

@@ -0,0 +1,8 @@
// "Add 'finally' block" "true"
class Test {
void foo() {
try {
} finally {
}
}
}

View File

@@ -0,0 +1,6 @@
// "Add 'finally' block" "true"
class Test {
void foo() {
try {}<caret>
}
}

View File

@@ -0,0 +1,12 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
public class AddFinallyTest extends LightQuickFixParameterizedTestCase {
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/addFinally";
}
}

View File

@@ -132,18 +132,20 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware {
}
private static HighlightInfo createErrorElementInfo(@NotNull PsiErrorElement element) {
HighlightInfo info = createInfoWithoutFixes(element);
if (info != null) {
for(ErrorQuickFixProvider provider: ErrorQuickFixProvider.EP_NAME.getExtensionList()) {
provider.registerErrorQuickFix(element, info);
}
}
return info;
}
private static HighlightInfo createInfoWithoutFixes(@NotNull PsiErrorElement element) {
TextRange range = element.getTextRange();
String errorDescription = element.getErrorDescription();
if (!range.isEmpty()) {
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range);
builder.descriptionAndTooltip(errorDescription);
final HighlightInfo info = builder.create();
if (info != null) {
for(ErrorQuickFixProvider provider: ErrorQuickFixProvider.EP_NAME.getExtensionList()) {
provider.registerErrorQuickFix(element, info);
}
}
return info;
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(errorDescription).create();
}
int offset = range.getStartOffset();
PsiFile containingFile = element.getContainingFile();
@@ -151,28 +153,24 @@ class DefaultHighlightVisitor implements HighlightVisitor, DumbAware {
FileViewProvider viewProvider = containingFile.getViewProvider();
PsiElement elementAtOffset = viewProvider.findElementAt(offset, LanguageUtil.getRootLanguage(element));
String text = elementAtOffset == null ? null : elementAtOffset.getText();
HighlightInfo info;
if (offset < fileLength && text != null && !StringUtil.startsWithChar(text, '\n') && !StringUtil.startsWithChar(text, '\r')) {
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(offset, offset + 1);
builder.descriptionAndTooltip(errorDescription);
info = builder.create();
return builder.create();
}
int start;
int end;
if (offset > 0) {
start = offset/* - 1*/;
end = offset;
}
else {
int start;
int end;
if (offset > 0) {
start = offset/* - 1*/;
end = offset;
}
else {
start = offset;
end = offset < fileLength ? offset + 1 : offset;
}
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element, start, end);
builder.descriptionAndTooltip(errorDescription);
builder.endOfLine();
info = builder.create();
start = offset;
end = offset < fileLength ? offset + 1 : offset;
}
return info;
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element, start, end);
builder.descriptionAndTooltip(errorDescription);
builder.endOfLine();
return builder.create();
}
}