Java inspection: Converted "Remove Braces" intention into an INFORMATION-level inspection. Reused bits of code from ControlFlowStatementWithoutBracesInspection. Tests added. (IDEA-157727)

This commit is contained in:
Pavel Dolgov
2016-07-14 17:12:02 +03:00
parent 9c9d5bb50a
commit f8762e5dc6
27 changed files with 429 additions and 357 deletions
@@ -2387,6 +2387,10 @@
key="control.flow.statement.without.braces.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
implementationClass="com.siyeh.ig.style.ControlFlowStatementWithoutBracesInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="SingleStatementInBlock" bundle="com.siyeh.InspectionGadgetsBundle"
key="single.statement.in.block.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
implementationClass="com.siyeh.ig.style.SingleStatementInBlockInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="EqualsCalledOnEnumConstant" bundle="com.siyeh.InspectionGadgetsBundle"
key="equals.called.on.enum.constant.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING"
@@ -2202,4 +2202,6 @@ if.to.assertion.descriptor=Replace 'if' with 'assert' statement
replace.equality.with.equals.name=Replace Equality with Equals
replace.equality.with.equals.descriptor=Replace ''{0}'' with ''{1}equals()''
replace.equality.with.safe.equals.name=Replace Equality with Safe Equals
replace.equality.with.safe.equals.descriptor=Replace ''{0}'' with safe ''{1}equals()''
replace.equality.with.safe.equals.descriptor=Replace ''{0}'' with safe ''{1}equals()''
single.statement.in.block.name=Code Block Contains Single Statement
single.statement.in.block.descriptor=Remove braces from ''{0}'' statement
@@ -0,0 +1,117 @@
/*
* Copyright 2000-2016 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.siyeh.ig.style;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.openapi.project.Project;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import org.jetbrains.annotations.Contract;
public abstract class ControlFlowStatementVisitorBase extends BaseInspectionVisitor {
private final HighlightDisplayKey myKey;
protected ControlFlowStatementVisitorBase(BaseInspection inspection) {
final String shortName = inspection.getShortName();
myKey = HighlightDisplayKey.find(shortName);
}
@Override
public void visitForeachStatement(PsiForeachStatement statement) {
super.visitForeachStatement(statement);
if (isApplicable(statement.getBody())) {
registerKeywordOrStatementError(statement, PsiKeyword.FOR);
}
}
@Override
public void visitForStatement(PsiForStatement statement) {
super.visitForStatement(statement);
if (isApplicable(statement.getBody())) {
registerKeywordOrStatementError(statement, PsiKeyword.FOR);
}
}
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
super.visitWhileStatement(statement);
if (isApplicable(statement.getBody())) {
registerKeywordOrStatementError(statement, PsiKeyword.WHILE);
}
}
@Override
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
super.visitDoWhileStatement(statement);
if (isApplicable(statement.getBody())) {
registerKeywordOrStatementError(statement, PsiKeyword.DO);
}
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
super.visitIfStatement(statement);
final PsiStatement thenBranch = statement.getThenBranch();
if (isApplicable(thenBranch)) {
registerKeywordOrStatementError(statement.getFirstChild(), thenBranch, PsiKeyword.IF);
}
final PsiStatement elseBranch = statement.getElseBranch();
if (isApplicable(elseBranch)) {
registerKeywordOrStatementError(statement.getElseElement(), elseBranch, PsiKeyword.ELSE);
}
}
@Contract("null->false")
protected abstract boolean isApplicable(PsiStatement body);
private void registerKeywordOrStatementError(PsiStatement statement, String text) {
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(statement);
if (highlightOnlyKeyword) {
registerStatementError(statement, text);
}
else {
registerError(statement, text);
}
}
private void registerKeywordOrStatementError(PsiElement keyword, PsiStatement body, String text) {
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(body);
if (highlightOnlyKeyword) {
registerError(keyword != null ? keyword : body, text);
}
else {
registerErrorAtRange(keyword != null ? keyword : body, body, text);
}
}
private boolean isHighlightOnlyKeyword(PsiElement element) {
if (!isOnTheFly()) {
return true;
}
if (myKey != null) {
final Project project = element.getProject();
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
final HighlightDisplayLevel errorLevel = profile.getErrorLevel(myKey, element);
return !HighlightDisplayLevel.DO_NOT_SHOW.equals(errorLevel);
}
return false;
}
}
@@ -15,12 +15,8 @@
*/
package com.siyeh.ig.style;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
@@ -28,18 +24,12 @@ import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
public class ControlFlowStatementWithoutBracesInspection
extends BaseInspection {
@NonNls private static final String DO_TEXT = "do";
@NonNls private static final String ELSE_TEXT = "else";
@NonNls private static final String FOR_TEXT = "for";
@NonNls private static final String IF_TEXT = "if";
@NonNls private static final String WHILE_TEXT = "while";
@Override
@NotNull
public String getDisplayName() {
@@ -58,11 +48,11 @@ public class ControlFlowStatementWithoutBracesInspection
public InspectionGadgetsFix buildFix(Object... infos) {
if (infos.length == 1 && infos[0] instanceof String) {
switch ((String)infos[0]) {
case DO_TEXT: return new DoBracesFix();
case ELSE_TEXT: return new ElseBracesFix();
case FOR_TEXT: return new ForBracesFix();
case IF_TEXT: return new IfBracesFix();
case WHILE_TEXT: return new WhileBracesFix();
case PsiKeyword.DO: return new DoBracesFix();
case PsiKeyword.ELSE: return new ElseBracesFix();
case PsiKeyword.FOR: return new ForBracesFix();
case PsiKeyword.IF: return new IfBracesFix();
case PsiKeyword.WHILE: return new WhileBracesFix();
}
}
return null;
@@ -138,122 +128,24 @@ public class ControlFlowStatementWithoutBracesInspection
@Override
public BaseInspectionVisitor buildVisitor() {
final String shortName = getShortName();
final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
return new ControlFlowStatementVisitor(key);
return new ControlFlowStatementVisitor(this);
}
private static class ControlFlowStatementVisitor
extends BaseInspectionVisitor {
private HighlightDisplayKey myKey;
public ControlFlowStatementVisitor(HighlightDisplayKey key) {
myKey = key;
private static class ControlFlowStatementVisitor extends ControlFlowStatementVisitorBase {
private ControlFlowStatementVisitor(BaseInspection inspection) {
super(inspection);
}
@Contract("null->false")
@Override
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
super.visitDoWhileStatement(statement);
final PsiStatement body = statement.getBody();
if (body == null || body instanceof PsiBlockStatement) {
return;
}
registerKeywordOrStatementError(statement, DO_TEXT);
}
@Override
public void visitForeachStatement(PsiForeachStatement statement) {
super.visitForeachStatement(statement);
final PsiStatement body = statement.getBody();
if (body == null || body instanceof PsiBlockStatement) {
return;
}
registerKeywordOrStatementError(statement, FOR_TEXT);
}
@Override
public void visitForStatement(PsiForStatement statement) {
super.visitForStatement(statement);
final PsiStatement body = statement.getBody();
if (body == null || body instanceof PsiBlockStatement) {
return;
}
registerKeywordOrStatementError(statement, FOR_TEXT);
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
super.visitIfStatement(statement);
final PsiStatement thenBranch = statement.getThenBranch();
if (thenBranch == null) {
return;
}
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(statement);
if (!(thenBranch instanceof PsiBlockStatement)) {
if (highlightOnlyKeyword) {
registerStatementError(statement, IF_TEXT);
}
else {
final PsiElement startElement = statement.getFirstChild();
registerErrorAtRange(startElement != null ? startElement : thenBranch, thenBranch, IF_TEXT);
}
}
final PsiStatement elseBranch = statement.getElseBranch();
if (elseBranch == null) {
return;
}
if (!(elseBranch instanceof PsiBlockStatement) &&
!(elseBranch instanceof PsiIfStatement)) {
final PsiKeyword elseKeyword = statement.getElseElement();
if (elseKeyword == null) {
return;
}
if (highlightOnlyKeyword) {
registerError(elseKeyword, ELSE_TEXT);
}
else {
registerErrorAtRange(elseKeyword, elseBranch, ELSE_TEXT);
}
}
}
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
super.visitWhileStatement(statement);
final PsiStatement body = statement.getBody();
if (body == null || body instanceof PsiBlockStatement) {
return;
}
registerKeywordOrStatementError(statement, WHILE_TEXT);
}
private void registerKeywordOrStatementError(PsiStatement statement, String text) {
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(statement);
if (highlightOnlyKeyword) {
registerStatementError(statement, text);
}
else {
registerError(statement, text);
}
}
private boolean isHighlightOnlyKeyword(PsiElement element) {
if (!isOnTheFly()) {
return true;
}
if (myKey != null) {
final Project project = element.getProject();
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
HighlightDisplayLevel errorLevel = profile.getErrorLevel(myKey, element);
return !HighlightDisplayLevel.DO_NOT_SHOW.equals(errorLevel);
}
return false;
protected boolean isApplicable(PsiStatement body) {
return body != null && !(body instanceof PsiBlockStatement);
}
}
private static class DoBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return DO_TEXT; } }
private static class ElseBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return ELSE_TEXT; } }
private static class ForBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return FOR_TEXT; } }
private static class IfBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return IF_TEXT; } }
private static class WhileBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return WHILE_TEXT; } }
private static class DoBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return PsiKeyword.DO; } }
private static class ElseBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return PsiKeyword.ELSE; } }
private static class ForBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return PsiKeyword.FOR; } }
private static class IfBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return PsiKeyword.IF; } }
private static class WhileBracesFix extends ControlFlowStatementFix { @Override String getKeywordText() { return PsiKeyword.WHILE; } }
}
@@ -0,0 +1,173 @@
/*
* Copyright 2000-2016 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.siyeh.ig.style;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.FileTypeUtils;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class SingleStatementInBlockInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("single.statement.in.block.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("single.statement.in.block.descriptor", infos);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new SingleStatementInBlockVisitor(this);
}
@Nullable
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
if (infos.length == 1 && infos[0] instanceof String) {
switch ((String)infos[0]) {
case PsiKeyword.DO:
return new RemoveDoBracesFix();
case PsiKeyword.ELSE:
return new RemoveElseBracesFix();
case PsiKeyword.FOR:
return new RemoveForBracesFix();
case PsiKeyword.IF:
return new RemoveIfBracesFix();
case PsiKeyword.WHILE:
return new RemoveWhileBracesFix();
}
}
return null;
}
private static void doFixImpl(@NotNull PsiBlockStatement blockStatement) {
final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
final PsiStatement[] statements = codeBlock.getStatements();
final PsiStatement statement = statements[0];
handleComments(blockStatement, codeBlock);
final String text = statement.getText();
PsiReplacementUtil.replaceStatement(blockStatement, text);
}
private static void handleComments(PsiBlockStatement blockStatement, PsiCodeBlock codeBlock) {
final PsiElement parent = blockStatement.getParent();
assert parent != null;
final PsiElement grandParent = parent.getParent();
assert grandParent != null;
PsiElement sibling = codeBlock.getFirstChild();
assert sibling != null;
sibling = sibling.getNextSibling();
while (sibling != null) {
if (sibling instanceof PsiComment) {
grandParent.addBefore(sibling, parent);
}
sibling = sibling.getNextSibling();
}
final PsiElement lastChild = blockStatement.getLastChild();
if (lastChild instanceof PsiComment) {
final PsiElement nextSibling = parent.getNextSibling();
grandParent.addAfter(lastChild, nextSibling);
}
}
private static class SingleStatementInBlockVisitor extends ControlFlowStatementVisitorBase {
protected SingleStatementInBlockVisitor(BaseInspection inspection) {
super(inspection);
}
@Contract("null->false")
@Override
protected boolean isApplicable(PsiStatement body) {
if (body instanceof PsiBlockStatement) {
final PsiBlockStatement statement = (PsiBlockStatement)body;
final PsiStatement[] statements = statement.getCodeBlock().getStatements();
if (statements.length == 1 && !(statements[0] instanceof PsiDeclarationStatement)) {
final PsiFile file = statement.getContainingFile();
//this inspection doesn't work in JSP files, as it can't tell about tags
// inside the braces
if (!FileTypeUtils.isInServerPageFile(file)) {
return true;
}
}
}
return false;
}
}
private static abstract class SingleStatementInBlockFix extends InspectionGadgetsFix {
@Nls
@NotNull
@Override
public String getName() {
return InspectionGadgetsBundle.message("single.statement.in.block.descriptor", getKeywordText());
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return InspectionGadgetsBundle.message("single.statement.in.block.name");
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement startElement = descriptor.getStartElement();
final PsiElement startParent = startElement.getParent();
final PsiElement body;
if (startElement instanceof PsiLoopStatement) {
body = ((PsiLoopStatement)startElement).getBody();
}
else if (startParent instanceof PsiLoopStatement) {
body = ((PsiLoopStatement)startParent).getBody();
}
else {
assert startElement instanceof PsiKeyword;
assert startParent instanceof PsiIfStatement;
PsiIfStatement ifStatement = (PsiIfStatement)startParent;
body = ((PsiKeyword)startElement).getTokenType() == JavaTokenType.IF_KEYWORD
? ifStatement.getThenBranch()
: ifStatement.getElseBranch();
}
assert body instanceof PsiBlockStatement;
doFixImpl((PsiBlockStatement)body);
}
abstract String getKeywordText();
}
private static class RemoveDoBracesFix extends SingleStatementInBlockFix { @Override String getKeywordText() { return PsiKeyword.DO; } }
private static class RemoveElseBracesFix extends SingleStatementInBlockFix { @Override String getKeywordText() { return PsiKeyword.ELSE; } }
private static class RemoveForBracesFix extends SingleStatementInBlockFix { @Override String getKeywordText() { return PsiKeyword.FOR; } }
private static class RemoveIfBracesFix extends SingleStatementInBlockFix { @Override String getKeywordText() { return PsiKeyword.IF; } }
private static class RemoveWhileBracesFix extends SingleStatementInBlockFix { @Override String getKeywordText() { return PsiKeyword.WHILE; } }
}
@@ -1,6 +1,6 @@
<html>
<body>
This intention removes braces from control flow statements with
This inspection reports control flow statements with
only a single statement in their code block.
</body>
</html>
@@ -0,0 +1,6 @@
class X {
{
do System.out.println();
while (true)<caret>;
}
}
@@ -0,0 +1,8 @@
class X {
{
do {
System.out.println();
}
while (true)<caret>;
}
}
@@ -0,0 +1,5 @@
class X {
void f(int[] a){
for(int i: a) System.out.println(i);
}
}
@@ -0,0 +1,7 @@
class X {
void f(int[] a){
for(int i: a) <caret> {
System.out.println(i);
}
}
}
@@ -0,0 +1,5 @@
class X {
void f(int[] a){
for(int i=0; i<a.length; i++) System.out.println(a[i]);
}
}
@@ -0,0 +1,7 @@
class X {
void f(int[] a){
for(int i=0; i<a.length; i++) {
System.out.println(a[i]);<caret>
}
}
}
@@ -2,7 +2,7 @@ class X {
{
if (true) {
System.out.println();
}<caret>
<caret>}
else {
System.out.println();
}
@@ -0,0 +1,5 @@
class X {
{
while (true) System.out.println();
}
}
@@ -0,0 +1,7 @@
class X {
{
while (true)<caret> {
System.out.println();
}
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2016 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.siyeh.ig.fixes.braces;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.IGQuickFixesTestCase;
import com.siyeh.ig.style.SingleStatementInBlockInspection;
/**
* @author Bas Leijdekkers
* @author Pavel.Dolgov
*/
public class SingleStatementInBlockFixTest extends IGQuickFixesTestCase {
public void testBetweenIfAndElse() { assertQuickfixNotAvailable(getMessagePrefix());}
public void testIfElse() { doTest("if"); }
public void testIfElse2() { doTest("if"); }
public void testWhile() { doTest("while"); }
public void testForEach() { doTest("for"); }
public void testForIndex() { doTest("for"); }
public void testDoWhile() { doTest("do"); }
@Override
protected void setUp() throws Exception {
super.setUp();
myRelativePath = "single_statement_block";
}
@Override
protected BaseInspection getInspection() {
return new SingleStatementInBlockInspection();
}
protected void doTest(String keyword) {
super.doTest(getMessage(keyword));
}
private static String getMessage(String keyword) {
return InspectionGadgetsBundle.message("single.statement.in.block.descriptor", keyword);
}
private static String getMessagePrefix() {
final String message = InspectionGadgetsBundle.message("single.statement.in.block.descriptor", "@");
final int index = message.indexOf("@");
if (index >= 0) return message.substring(0, index);
return message;
}
}
@@ -351,11 +351,6 @@
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
<categoryKey>intention.category.control.flow</categoryKey>
</intentionAction>
<intentionAction>
<className>com.siyeh.ipp.braces.RemoveBracesIntention</className>
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
<categoryKey>intention.category.control.flow</categoryKey>
</intentionAction>
<intentionAction>
<className>com.siyeh.ipp.forloop.ReverseForLoopDirectionIntention</className>
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
@@ -89,7 +89,6 @@ demorgans.intention.family.name=DeMorgan Law
flip.comparison.intention.family.name=Flip Comparison
flip.conjunction.intention.family.name=Flip Conjunction Operands
negate.comparison.intention.family.name=Negate Comparison
remove.braces.intention.family.name=Remove Braces
flip.commutative.method.call.intention.family.name=Flip Commutative Method Call
constant.subexpression.intention.family.name=Compute Constant Value for Subexpression
extract.increment.intention.family.name=Extract Increment
@@ -171,7 +170,6 @@ flip.smth.intention.name1=Flip ''{0}'' (changes semantics)
flip.comparison.intention.name=Flip ''{0}'' to ''{1}''
negate.comparison.intention.name=Negate ''{0}''
negate.comparison.intention.name1=Negate ''{0}'' to ''{1}''
remove.braces.intention.name=Remove braces from ''{0}'' statement
flip.commutative.method.call.intention.name=Flip ''.{0}()''
flip.commutative.method.call.intention.name1=Flip ''.{0}()'' (may change semantics)
constant.expression.intention.name=Compute constant value of ''{0}''
@@ -1,76 +0,0 @@
/*
* Copyright 2000-2014 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.siyeh.ipp.braces;
import com.intellij.psi.*;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.base.MutablyNamedIntention;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Danila Ponomarenko
*/
public abstract class BaseBracesIntention extends MutablyNamedIntention {
protected final String getTextForElement(PsiElement element) {
final PsiElement body = getSurroundingStatement(element);
if (body == null) {
return null;
}
return IntentionPowerPackBundle.message(getMessageKey(), getKeyword(body.getParent(), body));
}
@NotNull
protected abstract String getMessageKey();
@NotNull
private static String getKeyword(@NotNull PsiElement parent, @NotNull PsiElement element) {
if (parent instanceof PsiIfStatement) {
final PsiIfStatement ifStatement = (PsiIfStatement)parent;
final PsiStatement elseBranch = ifStatement.getElseBranch();
return element.equals(elseBranch) ? PsiKeyword.ELSE : PsiKeyword.IF;
}
final PsiElement firstChild = parent.getFirstChild();
assert firstChild != null;
return firstChild.getText();
}
@Nullable
protected static PsiStatement getSurroundingStatement(@NotNull PsiElement element) {
final PsiElement parent = element.getParent();
if (parent instanceof PsiIfStatement) {
final PsiIfStatement ifStatement = (PsiIfStatement)parent;
final PsiStatement thenBranch = ifStatement.getThenBranch();
final int offset = element.getTextOffset();
if (thenBranch != null && offset > thenBranch.getTextOffset()) {
final PsiKeyword elseElement = ifStatement.getElseElement();
if (elseElement == null || offset < elseElement.getTextOffset()) {
// no 'else' branch or after 'then' branch but before 'else' keyword
return null;
}
return ifStatement.getElseBranch();
}
return thenBranch;
}
if (parent instanceof PsiLoopStatement) {
return ((PsiLoopStatement)parent).getBody();
}
return null;
}
}
@@ -1,91 +0,0 @@
/*
* Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
*
* 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.siyeh.ipp.braces;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.util.FileTypeUtils;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
public class RemoveBracesIntention extends BaseBracesIntention {
@NotNull
protected PsiElementPredicate getElementPredicate() {
return new PsiElementPredicate() {
@Override
public boolean satisfiedBy(PsiElement element) {
final PsiStatement statement = getSurroundingStatement(element);
if (statement == null || !(statement instanceof PsiBlockStatement)) {
return false;
}
final PsiStatement[] statements = ((PsiBlockStatement)statement).getCodeBlock().getStatements();
if (statements.length != 1 || statements[0] instanceof PsiDeclarationStatement) {
return false;
}
final PsiFile file = statement.getContainingFile();
//this intention doesn't work in JSP files, as it can't tell about tags
// inside the braces
return !FileTypeUtils.isInServerPageFile(file);
}
};
}
@NotNull
@Override
protected String getMessageKey() {
return "remove.braces.intention.name";
}
protected void processIntention(@NotNull PsiElement element)
throws IncorrectOperationException {
final PsiStatement body = getSurroundingStatement(element);
if (body == null || !(body instanceof PsiBlockStatement)) return;
final PsiBlockStatement blockStatement = (PsiBlockStatement)body;
final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
final PsiStatement[] statements = codeBlock.getStatements();
final PsiStatement statement = statements[0];
handleComments(blockStatement, codeBlock);
final String text = statement.getText();
PsiReplacementUtil.replaceStatement(blockStatement, text);
}
private static void handleComments(PsiBlockStatement blockStatement, PsiCodeBlock codeBlock) {
final PsiElement parent = blockStatement.getParent();
assert parent != null;
final PsiElement grandParent = parent.getParent();
assert grandParent != null;
PsiElement sibling = codeBlock.getFirstChild();
assert sibling != null;
sibling = sibling.getNextSibling();
while (sibling != null) {
if (sibling instanceof PsiComment) {
grandParent.addBefore(sibling, parent);
}
sibling = sibling.getNextSibling();
}
final PsiElement lastChild = blockStatement.getLastChild();
if (lastChild instanceof PsiComment) {
final PsiElement nextSibling = parent.getNextSibling();
grandParent.addAfter(lastChild, nextSibling);
}
}
}
@@ -1,7 +0,0 @@
public class X {
int f(boolean b) {
if (b)
return 1;
return 0;
}
}
@@ -1,8 +0,0 @@
public class X {
int f(boolean b) {
if (b) <spot>{
return 1;
}</spot>
return 0;
}
}
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2014 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.siyeh.ipp.braces;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.IPPTestCase;
/**
* @see RemoveBracesIntention
* @author Bas Leijdekkers
*/
public class RemoveBracesIntentionTest extends IPPTestCase {
@Override
protected String getRelativePath() {
return "braces/remove";
}
@Override
protected String getIntentionName() {
return IntentionPowerPackBundle.message("remove.braces.intention.name", "if");
}
public void testBetweenIfAndElse() { assertIntentionNotAvailable(RemoveBracesIntention.class);}
public void testIfElse() { doTest(); }
public void testIfElse2() { doTest(); }
}