From 14494ace1bf762afcfce80268667195e2b51fe8f Mon Sep 17 00:00:00 2001 From: Dave Griffith Date: Thu, 10 Feb 2005 17:42:41 +0300 Subject: [PATCH] (no message) --- plugins/InspectionGadgets/Leftovers.txt | 4 - .../com/siyeh/ig/InspectionComparator.java | 21 +- .../junit/SetupCallsSuperSetupInspection.java | 44 +++- .../TeardownCallsSuperTeardownInspection.java | 44 +++- .../MethodMayBeStaticInspection.java | 6 + .../performance/TailRecursionInspection.java | 208 ++++++++++++++++-- .../siyeh/ig/psiutils/ControlFlowUtils.java | 53 +++++ .../UnnecessaryContinueInspection.java | 82 ++++--- .../verbose/UnnecessaryReturnInspection.java | 57 ++--- .../junit/SetupCallsSuperSetupInspection.java | 13 ++ .../performance/TailRecursionInspection.java | 23 +- .../UnnecessaryContinueInspection.java | 36 ++- .../verbose/UnnecessaryReturnInspection.java | 8 + 13 files changed, 462 insertions(+), 137 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/junit/SetupCallsSuperSetupInspection.java diff --git a/plugins/InspectionGadgets/Leftovers.txt b/plugins/InspectionGadgets/Leftovers.txt index 3c531cb65ae3..345330e27d52 100644 --- a/plugins/InspectionGadgets/Leftovers.txt +++ b/plugins/InspectionGadgets/Leftovers.txt @@ -20,14 +20,11 @@ Equals methods that do not check parameter type Call to simple getter or setter from within class Copyright comment - Tail recursion quickfix Make "Merge else-if" understand chained returning ifs - "Extract method" as quickfix to overly complex expression Flag on class without no-arg constructor Static inheritance fix Fixes for the assignment and return encapsulation inspections Static import fix - Fixes for call to super for JUnit setUp() and tearDown() Check IDs for all inspections Flag inspections with default on-off and default warning level Quick fix for "Constant StringBuffer may be String" @@ -40,7 +37,6 @@ QuickFix for "Integer division in floating point context" Quickfix for "Non-serializable class with..." Quickfix for "Unnecessary default" - JUnit test methods should not be marked "may be static" Inheritance as type def (change the EmptyClass inspection) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionComparator.java b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionComparator.java index fa0569a1dd32..d76f643f416e 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionComparator.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/InspectionComparator.java @@ -32,18 +32,25 @@ class InspectionComparator implements Comparator { String displayName2 = inspection2.getDisplayName(); displayName1 = displayName1.toUpperCase(); displayName2 = displayName2.toUpperCase(); - displayName1 = stripLeadingNonCharacters(displayName1); - displayName2 = stripLeadingNonCharacters(displayName2); + displayName1 = stripQuotes(displayName1); + displayName2 = stripQuotes(displayName2); + return displayName1.compareTo(displayName2); } - private static String stripLeadingNonCharacters(String str) { - for (int i = 0; i < str.length(); i++) { + private static String stripQuotes(String str) { + if(str.indexOf((int) '\'') <0 && str.indexOf((int) '"')<0) + { + return str; + } + final int length = str.length(); + final StringBuffer buffer = new StringBuffer(length); + for (int i = 0; i < length; i++) { final char ch = str.charAt(i); - if (Character.isLetter(ch)) { - return str.substring(i); + if(ch != '"' && ch != '\''){ + buffer.append(ch); } } - return str; + return buffer.toString(); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java index a6e696ce00ac..92825043bbc7 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/SetupCallsSuperSetupInspection.java @@ -1,14 +1,17 @@ package com.siyeh.ig.junit; import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.psi.*; -import com.siyeh.ig.BaseInspection; -import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.GroupNames; -import com.siyeh.ig.MethodInspection; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.ig.*; import com.siyeh.ig.psiutils.ClassUtils; public class SetupCallsSuperSetupInspection extends MethodInspection { + private final AddSuperSetUpCall fix = new AddSuperSetUpCall(); public String getDisplayName() { return "setUp() doesn't call super.setUp()"; @@ -22,6 +25,39 @@ public class SetupCallsSuperSetupInspection extends MethodInspection { return "#ref() doesn't call super.setUp()"; } + private static class AddSuperSetUpCall extends InspectionGadgetsFix{ + public String getName(){ + return "add call to super.setUp()"; + } + + public void applyFix(Project project, ProblemDescriptor descriptor){ + try{ + final PsiElement methodName = descriptor.getPsiElement(); + final PsiMethod method = (PsiMethod) methodName.getParent(); + final PsiCodeBlock body = method.getBody(); + final PsiManager psiManager = PsiManager.getInstance(project); + final PsiElementFactory factory = + psiManager.getElementFactory(); + final PsiStatement newStatement = + factory.createStatementFromText("super.setUp();", null); + final CodeStyleManager styleManager = + psiManager.getCodeStyleManager(); + final PsiJavaToken brace = body.getLBrace(); + body.addAfter(newStatement, brace); + styleManager.reformat(body); + } catch(IncorrectOperationException e){ + final Class aClass = getClass(); + final String className = aClass.getName(); + final Logger logger = Logger.getInstance(className); + logger.error(e); + } + } + } + + protected InspectionGadgetsFix buildFix(PsiElement location){ + return fix; + } + public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) { return new SetupCallsSuperSetupVisitor(this, inspectionManager, onTheFly); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java index 072fb1fac7b5..d950b2b42c69 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TeardownCallsSuperTeardownInspection.java @@ -1,15 +1,19 @@ package com.siyeh.ig.junit; import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.psi.*; -import com.siyeh.ig.BaseInspection; -import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.GroupNames; -import com.siyeh.ig.MethodInspection; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.ig.*; import com.siyeh.ig.psiutils.ClassUtils; public class TeardownCallsSuperTeardownInspection extends MethodInspection { + private AddSuperTearDownCall fix = new AddSuperTearDownCall(); + public String getDisplayName() { return "tearDown() doesn't call super.tearDown()"; } @@ -22,6 +26,38 @@ public class TeardownCallsSuperTeardownInspection extends MethodInspection { return "#ref() doesn't call super.tearDown()"; } + private static class AddSuperTearDownCall extends InspectionGadgetsFix{ + public String getName(){ + return "add call to super.tearDown()"; + } + + public void applyFix(Project project, ProblemDescriptor descriptor){ + try{ + final PsiElement methodName = descriptor.getPsiElement(); + final PsiMethod method = (PsiMethod) methodName.getParent(); + final PsiCodeBlock body = method.getBody(); + final PsiManager psiManager = PsiManager.getInstance(project); + final PsiElementFactory factory = + psiManager.getElementFactory(); + final PsiStatement newStatement = + factory.createStatementFromText("super.tearDown();", null); + final CodeStyleManager styleManager = + psiManager.getCodeStyleManager(); + final PsiJavaToken brace = body.getRBrace(); + body.addBefore(newStatement, brace); + styleManager.reformat(body); + } catch(IncorrectOperationException e){ + final Class aClass = getClass(); + final String className = aClass.getName(); + final Logger logger = Logger.getInstance(className); + logger.error(e); + } + } + } + + protected InspectionGadgetsFix buildFix(PsiElement location){ + return fix; + } public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) { return new TeardownCallsSuperTeardownVisitor(this, inspectionManager, onTheFly); } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java index 0882c81c0ad5..de84b83d7a56 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/MethodMayBeStaticInspection.java @@ -131,6 +131,12 @@ public class MethodMayBeStaticInspection extends MethodInspection { !method.hasModifierProperty(PsiModifier.PRIVATE)) { return; } + final String methodName = method.getName(); + if(methodName!=null && methodName.startsWith("test") && + ClassUtils.isSubclass(containingClass, + "junit.framework.TestCase")){ + return; + } final PsiMethod[] superMethods = method.findSuperMethods(); if (superMethods.length > 0) { return; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/TailRecursionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/TailRecursionInspection.java index 50ed630fe46d..d8966eeccd38 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/TailRecursionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/TailRecursionInspection.java @@ -1,65 +1,227 @@ package com.siyeh.ig.performance; import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; -import com.siyeh.ig.BaseInspection; -import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.ExpressionInspection; -import com.siyeh.ig.GroupNames; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.ig.*; +import com.siyeh.ig.psiutils.ControlFlowUtils; -public class TailRecursionInspection extends ExpressionInspection { - - public String getDisplayName() { +public class TailRecursionInspection extends ExpressionInspection{ + public String getDisplayName(){ return "Tail recursion"; } - public String getGroupDisplayName() { + public String getGroupDisplayName(){ return GroupNames.PERFORMANCE_GROUP_NAME; } - public String buildErrorString(PsiElement location) { + public String buildErrorString(PsiElement location){ return "Tail recursive call #ref() #loc"; } - public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) { + protected InspectionGadgetsFix buildFix(PsiElement location){ + final PsiMethod containingMethod = + (PsiMethod) PsiTreeUtil.getParentOfType(location, + PsiMethod.class); + if(mayBeReplacedByIterativeMethod(containingMethod)){ + return new RemoveTailRecursionFix(); + } else{ + return null; + } + } + + private static boolean mayBeReplacedByIterativeMethod(PsiMethod containingMethod){ + if(!containingMethod.hasModifierProperty(PsiModifier.STATIC) && + !containingMethod.hasModifierProperty(PsiModifier.PRIVATE)){ + return false; + } + final PsiParameterList parameterList = + containingMethod.getParameterList(); + final PsiParameter[] parameters = parameterList.getParameters(); + for(int i = 0; i < parameters.length; i++){ + final PsiParameter parameter = parameters[i]; + if(parameter.hasModifierProperty(PsiModifier.FINAL)){ + return false; + } + } + return true; + } + + private static class RemoveTailRecursionFix + extends InspectionGadgetsFix{ + public String getName(){ + return "Replace tail recursion with iteration"; + } + + public void applyFix(Project project, + ProblemDescriptor problemDescriptor){ + try{ + final PsiElement methodNameToken = + problemDescriptor.getPsiElement(); + final PsiMethod method = + (PsiMethod) PsiTreeUtil.getParentOfType(methodNameToken, + PsiMethod.class); + + final PsiCodeBlock body = method.getBody(); + final String replacementText; + + final PsiManager psiManager = PsiManager.getInstance(project); + + final CodeStyleManager codeStyleManager = + psiManager.getCodeStyleManager(); + + final PsiElement[] children = body.getChildren(); + final StringBuffer buffer = new StringBuffer(); + final boolean[] containedTailCallInLoop = new boolean[1]; + containedTailCallInLoop[0] = false; + for(int i = 1; i < children.length; i++){ + replaceTailCalls(children[i], method, buffer, containedTailCallInLoop); + } + final String labelString; + if(containedTailCallInLoop[0]){ + labelString = method.getName() + ':'; + } else{ + labelString = ""; + } + replacementText = '{' + labelString + "while(true){" + + buffer + '}'; + + final PsiElementFactory elementFactory = + psiManager.getElementFactory(); + final PsiCodeBlock block = + elementFactory.createCodeBlockFromText(replacementText, + null); + body.replace(block); + codeStyleManager.reformat(method); + } catch(IncorrectOperationException e){ + } + } + + + private void replaceTailCalls(PsiElement element, + PsiMethod method, + StringBuffer out, + boolean[] containedTailCallInLoop){ + + final String text = element.getText(); + if(isTailCallReturn(element, method)){ + final PsiReturnStatement returnStatement = + (PsiReturnStatement) element; + final PsiMethodCallExpression call = + (PsiMethodCallExpression) returnStatement.getReturnValue(); + final PsiExpressionList argumentList = call.getArgumentList(); + final PsiExpression[] args = + argumentList.getExpressions(); + + final PsiParameterList parameterList = method.getParameterList(); + final PsiParameter[] parameters = + parameterList.getParameters(); + final boolean isInBlock = + returnStatement.getParent() instanceof PsiCodeBlock; + + if(!isInBlock){ + out.append('{'); + } + for(int i = 0; i < parameters.length; i++){ + final PsiParameter parameter = parameters[i]; + final PsiExpression arg = args[i]; + final String parameterName = parameter.getName(); + final String argText = arg.getText(); + out.append(parameterName + " = " + argText + ';'); + } + if(ControlFlowUtils.blockCompletesWithStatement(method.getBody(), returnStatement)) + { + //don't do anything, as the continue is unnecessary + } + else if(ControlFlowUtils.isInLoop(element)){ + final String methodName = method.getName(); + containedTailCallInLoop[0] = true; + out.append("continue " + methodName + ';'); + } else{ + out.append("continue;"); + } + if(!isInBlock){ + out.append('}'); + } + } else{ + final PsiElement[] children = element.getChildren(); + if(children.length == 0){ + out.append(text); + } else{ + for(int i = 0; i < children.length; i++){ + final PsiElement child = children[i]; + replaceTailCalls(child, method, out, containedTailCallInLoop); + } + } + } + } + + private boolean isTailCallReturn(PsiElement element, + PsiMethod containingMethod){ + if(!(element instanceof PsiReturnStatement)){ + return false; + } + final PsiReturnStatement returnStatement = + (PsiReturnStatement) element; + final PsiExpression returnValue = returnStatement.getReturnValue(); + if(!(returnValue instanceof PsiMethodCallExpression)){ + return false; + } + final PsiMethodCallExpression call = + (PsiMethodCallExpression) returnValue; + final PsiMethod method = call.resolveMethod(); + return containingMethod.equals(method); + } + } + + public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, + boolean onTheFly){ return new TailRecursionVisitor(this, inspectionManager, onTheFly); } - private static class TailRecursionVisitor extends BaseInspectionVisitor { - private TailRecursionVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) { + + private static class TailRecursionVisitor extends BaseInspectionVisitor{ + private TailRecursionVisitor(BaseInspection inspection, + InspectionManager inspectionManager, + boolean isOnTheFly){ super(inspection, inspectionManager, isOnTheFly); } - public void visitReturnStatement(PsiReturnStatement statement) { + public void visitReturnStatement(PsiReturnStatement statement){ super.visitReturnStatement(statement); final PsiExpression returnValue = statement.getReturnValue(); - if (returnValue == null) { + if(returnValue == null){ return; } - if (!(returnValue instanceof PsiMethodCallExpression)) { + if(!(returnValue instanceof PsiMethodCallExpression)){ return; } final PsiMethod containingMethod = - (PsiMethod) PsiTreeUtil.getParentOfType(statement, PsiMethod.class); - if (containingMethod == null) { + (PsiMethod) PsiTreeUtil.getParentOfType(statement, + PsiMethod.class); + if(containingMethod == null){ return; } - final PsiMethodCallExpression returnCall = (PsiMethodCallExpression) returnValue; + final PsiMethodCallExpression returnCall = + (PsiMethodCallExpression) returnValue; final PsiMethod method = returnCall.resolveMethod(); - if (method == null) { + if(method == null){ return; } - if (!method.equals(containingMethod)) { + if(!method.equals(containingMethod)){ return; } - final PsiReferenceExpression methodExpression = returnCall.getMethodExpression(); - if (methodExpression == null) { + final PsiReferenceExpression methodExpression = + returnCall.getMethodExpression(); + if(methodExpression == null){ return; } registerMethodCallError(returnCall); } } - } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java index 5a63a67c6ebd..a18d0f995919 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/ControlFlowUtils.java @@ -272,6 +272,59 @@ public class ControlFlowUtils { } } + public static boolean blockCompletesWithStatement(PsiCodeBlock body, + PsiStatement statement){ + PsiElement statementToCheck = statement; + while(true) + { + final PsiElement container = + getContainingStatementOrBlock(statementToCheck); + if(container == null) + { + return false; + } + if(container instanceof PsiCodeBlock) + { + if(!statementIsLastInBlock((PsiCodeBlock) container, (PsiStatement)statementToCheck)) + { + return false; + } + if(container.equals(body)) + { + return true; + } + } + if(container instanceof PsiWhileStatement || + container instanceof PsiDoWhileStatement || + container instanceof PsiForeachStatement || + container instanceof PsiForStatement) + { + return false; + } + statementToCheck = container; + } + } + + private static PsiElement getContainingStatementOrBlock(PsiElement statement){ + return PsiTreeUtil.getParentOfType(statement, new Class[]{PsiStatement.class, PsiCodeBlock.class}); + } + + private static boolean statementIsLastInBlock(PsiCodeBlock block, + PsiStatement statement){ + final PsiStatement[] statements = block.getStatements(); + for(int i = statements.length - 1; i >= 0; i--){ + final PsiStatement childStatement = statements[i]; + if(statement.equals(childStatement)){ + return true; + } + if(!(statement instanceof PsiEmptyStatement)){ + return false; + } + } + return false; + } + + private static class ReturnFinder extends PsiRecursiveElementVisitor { private boolean m_found = false; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryContinueInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryContinueInspection.java index 1e2964820017..7e51aafe66fe 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryContinueInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryContinueInspection.java @@ -5,82 +5,80 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.siyeh.ig.*; +import com.siyeh.ig.psiutils.ControlFlowUtils; -public class UnnecessaryContinueInspection extends StatementInspection { +public class UnnecessaryContinueInspection extends StatementInspection{ private final UnnecessaryContinueFix fix = new UnnecessaryContinueFix(); - public String getDisplayName() { + public String getDisplayName(){ return "Unnecessary 'continue' statement"; } - public String getGroupDisplayName() { + public String getGroupDisplayName(){ return GroupNames.VERBOSE_GROUP_NAME; } - public String buildErrorString(PsiElement location) { + public String buildErrorString(PsiElement location){ return "#ref is unnecessary as the last statement in a loop #loc"; } - public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) { - return new UnnecessaryContinueVisitor(this, inspectionManager, onTheFly); + public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, + boolean onTheFly){ + return new UnnecessaryContinueVisitor(this, inspectionManager, + onTheFly); } - public InspectionGadgetsFix buildFix(PsiElement location) { + public InspectionGadgetsFix buildFix(PsiElement location){ return fix; } - private static class UnnecessaryContinueFix extends InspectionGadgetsFix { - public String getName() { + private static class UnnecessaryContinueFix extends InspectionGadgetsFix{ + public String getName(){ return "Remove unnecessary continue"; } - public void applyFix(Project project, ProblemDescriptor descriptor) { + public void applyFix(Project project, ProblemDescriptor descriptor){ final PsiElement returnKeywordElement = descriptor.getPsiElement(); - final PsiElement continueStatement = returnKeywordElement.getParent(); + final PsiElement continueStatement = + returnKeywordElement.getParent(); deleteElement(continueStatement); } - } - private static class UnnecessaryContinueVisitor extends BaseInspectionVisitor { - private UnnecessaryContinueVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) { + private static class UnnecessaryContinueVisitor + extends BaseInspectionVisitor{ + private UnnecessaryContinueVisitor(BaseInspection inspection, + InspectionManager inspectionManager, + boolean isOnTheFly){ super(inspection, inspectionManager, isOnTheFly); } + public void visitContinueStatement(PsiContinueStatement statement){ + final PsiStatement continuedStatement = + statement.findContinuedStatement(); + PsiStatement body = null; + if(continuedStatement instanceof PsiForeachStatement){ + body = ((PsiForeachStatement) continuedStatement).getBody(); + } else if(continuedStatement instanceof PsiForStatement){ + body = ((PsiForStatement) continuedStatement).getBody(); + } else if(continuedStatement instanceof PsiDoWhileStatement){ + body = ((PsiDoWhileStatement) continuedStatement).getBody(); + } else if(continuedStatement instanceof PsiWhileStatement){ + body = ((PsiWhileStatement) continuedStatement).getBody(); + } - public void visitContinueStatement(PsiContinueStatement statement) { - final PsiIdentifier identifier = statement.getLabelIdentifier(); - if (identifier != null) { + if(body == null){ return; } - final PsiStatement continuedStatement = statement.findContinuedStatement(); - final PsiElement parent = statement.getParent(); - if (parent.equals(continuedStatement)) { + if(!(body instanceof PsiBlockStatement)){ + registerStatementError(statement); + return; + } + final PsiCodeBlock block = ((PsiBlockStatement) body).getCodeBlock(); + if(ControlFlowUtils.blockCompletesWithStatement(block, statement)){ registerStatementError(statement); - } else if (parent instanceof PsiCodeBlock) { - final PsiCodeBlock block = (PsiCodeBlock) parent; - if (statementIsLastInBlock(block, statement)) { - final PsiElement blockStatement = block.getParent(); - final PsiElement containingStatement = blockStatement.getParent(); - if (containingStatement.equals(continuedStatement)) { - registerStatementError(statement); - } - } } } - private boolean statementIsLastInBlock(PsiCodeBlock block, PsiContinueStatement statement) { - final PsiStatement[] statements = block.getStatements(); - for (int i = statements.length - 1; i >= 0; i--) { - final PsiStatement childStatement = statements[i]; - if (statement.equals(childStatement)) { - return true; - } - if (!(statement instanceof PsiEmptyStatement)) { - return false; - } - } - return false; - } } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryReturnInspection.java index fdf65d99e4a4..69e7e1f13c89 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryReturnInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/verbose/UnnecessaryReturnInspection.java @@ -6,73 +6,76 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.*; +import com.siyeh.ig.psiutils.ControlFlowUtils; -public class UnnecessaryReturnInspection extends StatementInspection { +public class UnnecessaryReturnInspection extends StatementInspection{ private final UnnecessaryReturnFix fix = new UnnecessaryReturnFix(); - public String getDisplayName() { + public String getDisplayName(){ return "Unnecessary 'return' statement"; } - public String getGroupDisplayName() { + public String getGroupDisplayName(){ return GroupNames.VERBOSE_GROUP_NAME; } - public String buildErrorString(PsiElement location) { + public String buildErrorString(PsiElement location){ final PsiMethod method = - (PsiMethod) PsiTreeUtil.getParentOfType(location, PsiMethod.class); - if (method.isConstructor()) { + (PsiMethod) PsiTreeUtil.getParentOfType(location, + PsiMethod.class); + if(method.isConstructor()){ return "#ref is unnecessary as the last statement in a constructor #loc"; - } else { + } else{ return "#ref is unnecessary as the last statement in a method returning 'void' #loc"; } } - public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, boolean onTheFly) { + public BaseInspectionVisitor createVisitor(InspectionManager inspectionManager, + boolean onTheFly){ return new UnnecessaryReturnVisitor(this, inspectionManager, onTheFly); } - public InspectionGadgetsFix buildFix(PsiElement location) { + public InspectionGadgetsFix buildFix(PsiElement location){ return fix; } - private static class UnnecessaryReturnFix extends InspectionGadgetsFix { - public String getName() { + private static class UnnecessaryReturnFix extends InspectionGadgetsFix{ + public String getName(){ return "Remove unnecessary return"; } - public void applyFix(Project project, ProblemDescriptor descriptor) { + public void applyFix(Project project, ProblemDescriptor descriptor){ final PsiElement returnKeywordElement = descriptor.getPsiElement(); final PsiElement returnStatement = returnKeywordElement.getParent(); deleteElement(returnStatement); } - } - private static class UnnecessaryReturnVisitor extends BaseInspectionVisitor { - private UnnecessaryReturnVisitor(BaseInspection inspection, InspectionManager inspectionManager, boolean isOnTheFly) { + private static class UnnecessaryReturnVisitor extends BaseInspectionVisitor{ + private UnnecessaryReturnVisitor(BaseInspection inspection, + InspectionManager inspectionManager, + boolean isOnTheFly){ super(inspection, inspectionManager, isOnTheFly); } - public void visitMethod(PsiMethod method) { - // don't call super, to keep from drilling in + + public void visitReturnStatement(PsiReturnStatement statement){ + super.visitReturnStatement(statement); + final PsiMethod method = + (PsiMethod) PsiTreeUtil.getParentOfType(statement, + PsiMethod.class); final PsiType returnType = method.getReturnType(); - if (!method.isConstructor() && !returnType.equals(PsiType.VOID)) { + if(!method.isConstructor() && !returnType.equals(PsiType.VOID)){ return; } final PsiCodeBlock body = method.getBody(); - if (body == null) { + if(body == null){ return; } - final PsiStatement[] statements = body.getStatements(); - if (statements == null || statements.length == 0) { - return; + if(ControlFlowUtils.blockCompletesWithStatement(body, statement)) + { + registerStatementError(statement); } - final PsiStatement finalStatement = statements[statements.length - 1]; - if (!(finalStatement instanceof PsiReturnStatement)) { - return; - } - registerStatementError(finalStatement); } } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/SetupCallsSuperSetupInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/SetupCallsSuperSetupInspection.java new file mode 100644 index 000000000000..049aca4d277a --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/SetupCallsSuperSetupInspection.java @@ -0,0 +1,13 @@ +package com.siyeh.igtest.junit; + +import junit.framework.TestCase; + +public class SetupCallsSuperSetupInspection extends TestCase{ + protected void setUp() throws Exception { + System.out.println("foo"); + } + + protected void tearDown() throws Exception { + System.out.println("bar"); + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/TailRecursionInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/TailRecursionInspection.java index 63667e450b49..fed2e5fdc6b7 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/TailRecursionInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/TailRecursionInspection.java @@ -2,31 +2,24 @@ package com.siyeh.igtest.performance; import java.io.IOException; -public class TailRecursionInspection -{ - public TailRecursionInspection() - { +public class TailRecursionInspection { + public TailRecursionInspection() { } - public int foo() throws IOException + public static int foo() throws IOException { return foo(); } - public int factorial(int val) - { + public int factorial(int val) { return factorial(val, 1); } - public int factorial(int val, int runningVal) - { - if(val == 1) - { + private int factorial(int val, int runningVal) { + if (val == 1) { return runningVal; - } - else - { - return factorial(val-1, runningVal * val); + } else { + return factorial(val - 1, runningVal * val); } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryContinueInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryContinueInspection.java index e2b6928663bb..2aa8fce28226 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryContinueInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryContinueInspection.java @@ -1,20 +1,34 @@ package com.siyeh.igtest.verbose; -public class UnnecessaryContinueInspection -{ - - public UnnecessaryContinueInspection() - { - for(;;) - { - continue; +public class UnnecessaryContinueInspection { + public UnnecessaryContinueInspection() { + for (; ;) { + continue; } } - public void foo() - { - while(true) + + public void foo() { + while (true) continue; } + public void foo2() { + while (true) + if (true) + { + continue; + } + } + public void foo3() { + while (true) + { + if (true) + { + continue; + } + System.out.println("foo"); + } + } + } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java index cc9622d6717c..c45a13f09826 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/verbose/UnnecessaryReturnInspection.java @@ -21,4 +21,12 @@ public class UnnecessaryReturnInspection } } + public void barzoom() + { + while(true) + { + return; + } + } + } \ No newline at end of file