Wrap switch rule statements into block fix (IDEA-202664, IDEA-207059)

GitOrigin-RevId: 184ebf34bd15c46f54685cf06521cee1d903b056
This commit is contained in:
Tagir Valeev
2019-07-02 06:52:16 +03:00
committed by intellij-monorepo-bot
parent dc7a6184d7
commit da9c5dd049
15 changed files with 208 additions and 4 deletions
@@ -536,4 +536,7 @@ public abstract class QuickFixFactory {
@NotNull
public abstract IntentionAction createChangeModifierFix();
@NotNull
public abstract IntentionAction createWrapSwitchRuleStatementsIntoBlockFix(PsiSwitchLabeledRuleStatement rule);
}
@@ -2607,7 +2607,8 @@ public class HighlightUtil extends HighlightUtilBase {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(first).descriptionAndTooltip(description).create();
}
PsiElement element = first, alien = null;
PsiElement element = first;
PsiStatement alien = null;
boolean classicLabels = false, enhancedLabels = false, levelChecked = false;
while (element != null && !PsiUtil.isJavaToken(element, JavaTokenType.RBRACE)) {
if (element instanceof PsiSwitchLabeledRuleStatement) {
@@ -2617,14 +2618,14 @@ public class HighlightUtil extends HighlightUtilBase {
levelChecked = true;
}
if (classicLabels) {
alien = element;
alien = (PsiStatement)element;
break;
}
enhancedLabels = true;
}
else if (element instanceof PsiStatement) {
if (enhancedLabels) {
alien = element;
alien = (PsiStatement)element;
break;
}
classicLabels = true;
@@ -2642,6 +2643,16 @@ public class HighlightUtil extends HighlightUtilBase {
element = PsiTreeUtil.skipWhitespacesAndCommentsForward(element);
}
if (alien != null) {
if (enhancedLabels && !(alien instanceof PsiSwitchLabelStatementBase)) {
PsiSwitchLabeledRuleStatement previousRule = PsiTreeUtil.getPrevSiblingOfType(alien, PsiSwitchLabeledRuleStatement.class);
String description = JavaErrorMessages.message("statement.must.be.prepended.with.case.label");
HighlightInfo info =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(alien).descriptionAndTooltip(description).create();
if (previousRule != null) {
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createWrapSwitchRuleStatementsIntoBlockFix(previousRule));
}
return info;
}
String description = JavaErrorMessages.message("different.case.kinds.in.switch");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(alien).descriptionAndTooltip(description).create();
}
@@ -6,8 +6,10 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.quickfix.AddExceptionToCatchFix;
import com.intellij.codeInsight.daemon.impl.quickfix.AddFinallyFix;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.daemon.impl.quickfix.WrapSwitchRuleStatementsIntoBlockFix;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
import com.intellij.psi.PsiSwitchLabeledRuleStatement;
import com.intellij.psi.PsiTryStatement;
import org.jetbrains.annotations.NotNull;
@@ -20,5 +22,9 @@ public class JavaErrorQuickFixProvider implements ErrorQuickFixProvider {
QuickFixAction.registerQuickFixAction(highlightInfo, new AddExceptionToCatchFix(false));
QuickFixAction.registerQuickFixAction(highlightInfo, new AddFinallyFix((PsiTryStatement)parent));
}
if (parent instanceof PsiSwitchLabeledRuleStatement && errorElement.getErrorDescription().equals(
JavaErrorMessages.message("expected.switch.rule"))) {
QuickFixAction.registerQuickFixAction(highlightInfo, new WrapSwitchRuleStatementsIntoBlockFix((PsiSwitchLabeledRuleStatement)parent));
}
}
}
@@ -0,0 +1,80 @@
// Copyright 2000-2019 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.quickfix;
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.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class WrapSwitchRuleStatementsIntoBlockFix extends BaseIntentionAction {
private final PsiSwitchLabeledRuleStatement myRuleStatement;
public WrapSwitchRuleStatementsIntoBlockFix(PsiSwitchLabeledRuleStatement ruleStatement) {
myRuleStatement = ruleStatement;
}
@Nls(capitalization = Nls.Capitalization.Sentence)
@NotNull
@Override
public String getFamilyName() {
return "Create block";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!(file instanceof PsiJavaFile)) return false;
if (!myRuleStatement.isValid()) return false;
if (myRuleStatement.getBody() instanceof PsiBlockStatement) return false;
PsiStatement sibling = PsiTreeUtil.getNextSiblingOfType(myRuleStatement, PsiStatement.class);
if (sibling == null || sibling instanceof PsiSwitchLabelStatementBase) {
setText(getFamilyName());
} else {
setText("Wrap with block");
}
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!myRuleStatement.isValid()) return;
PsiCodeBlock parent = ObjectUtils.tryCast(myRuleStatement.getParent(), PsiCodeBlock.class);
if (parent == null) return;
PsiJavaToken rBrace = parent.getRBrace();
PsiElement[] children = parent.getChildren();
int index = ArrayUtil.indexOf(children, myRuleStatement);
assert index >= 0;
int nextIndex = index + 1;
while (nextIndex < children.length && !(children[nextIndex] instanceof PsiSwitchLabelStatementBase) && children[nextIndex] != rBrace) {
nextIndex++;
}
if (children[nextIndex - 1] instanceof PsiWhiteSpace) {
nextIndex--;
}
PsiElement oldBody = null;
if (myRuleStatement.getBody() != null) {
oldBody = myRuleStatement.getBody().copy();
myRuleStatement.getBody().delete();
}
PsiSwitchLabeledRuleStatement newRule = (PsiSwitchLabeledRuleStatement)JavaPsiFacade.getElementFactory(project).createStatementFromText(
myRuleStatement.getText() + "{}", myRuleStatement);
PsiCodeBlock block = ((PsiBlockStatement)Objects.requireNonNull(newRule.getBody())).getCodeBlock();
if (oldBody != null) {
block.add(oldBody);
}
if (nextIndex > index + 1) {
PsiElement first = children[index + 1];
PsiElement last = children[nextIndex - 1];
block.addRange(first, last);
parent.deleteChildRange(first, last);
}
myRuleStatement.replace(newRule);
}
}
@@ -959,4 +959,10 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
public IntentionAction createChangeModifierFix() {
return new ChangeModifierIntention(true);
}
@NotNull
@Override
public IntentionAction createWrapSwitchRuleStatementsIntoBlockFix(PsiSwitchLabeledRuleStatement rule) {
return new WrapSwitchRuleStatementsIntoBlockFix(rule);
}
}
@@ -15,7 +15,7 @@ class EnhancedSwitchStatements {
switch (new Random().nextInt()) {
case 0 -> throw new IllegalStateException("no args");
<error descr="Different case kinds used in the switch">break;</error>
<error descr="Statement must be prepended with case label">break;</error>
}
switch (new Random().nextInt()) {
case 0 -> throw new IllegalStateException("no args");
@@ -0,0 +1,9 @@
// "Create block" "true"
class X {
void foo(int i) {
switch(i) {
default -> {
}
}
}
}
@@ -0,0 +1,11 @@
// "Wrap with block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 -> {
for(int i=0; i<10; i++) System.out.println(i);
}
case 2 ->
}
}
}
@@ -0,0 +1,10 @@
// "Create block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 -> {
}
case 2 ->
}
}
}
@@ -0,0 +1,11 @@
// "Wrap with block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 -> {
System.out.println("foo");
System.out.println("bar");
}
}
}
}
@@ -0,0 +1,8 @@
// "Create block" "true"
class X {
void foo(int i) {
switch(i) {
default -><caret>
}
}
}
@@ -0,0 +1,9 @@
// "Wrap with block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 -><caret> for(int i=0; i<10; i++) System.out.println(i);
case 2 ->
}
}
}
@@ -0,0 +1,9 @@
// "Create block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 -><caret>
case 2 ->
}
}
}
@@ -0,0 +1,10 @@
// "Wrap with block" "true"
class X {
void foo(int i) {
switch(i) {
case 1 ->
System.out.println("foo");
System<caret>.out.println("bar");
}
}
}
@@ -0,0 +1,21 @@
// Copyright 2000-2019 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;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
import static com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase.JAVA_12;
public class WrapSwitchRuleStatementsIntoBlockFixTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_12;
}
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/wrapSwitchRuleStatements";
}
}