diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/AssignHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/AssignHandler.java new file mode 100644 index 000000000..bd4587814 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/AssignHandler.java @@ -0,0 +1,82 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2003 Oliver Burn +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//////////////////////////////////////////////////////////////////////////////// +package com.puppycrawl.tools.checkstyle.checks.indentation; + +import com.puppycrawl.tools.checkstyle.api.DetailAST; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; + +/** + * Handler for assignements. + * + * @author o_sukhodolsky + */ +public class AssignHandler extends BlockParentHandler +{ + /** + * Construct an instance of this handler with the given indentation check, + * abstract syntax tree, and parent handler. + * + * @param aIndentCheck the indentation check + * @param aAst the abstract syntax tree + * @param aParent the parent handler + */ + public AssignHandler(IndentationCheck aIndentCheck, + DetailAST aAst, ExpressionHandler aParent) + { + super(aIndentCheck, "assign", aAst, aParent); + } + + /** + * Check the indentation of the expression we are handling. + */ + public void checkIndentation() + { + IndentLevel expectedLevel = getChildrenExpectedLevel(); + + // check indentation of assign if it starts line + DetailAST assign = getMainAst(); + if (startsLine(assign) + && !expectedLevel.accept(expandedTabsColumnNo(assign))) + { + logError(assign, "" , expandedTabsColumnNo(assign), expectedLevel); + } + + // check indentation of rvalue + DetailAST child = (DetailAST) assign.getFirstChild(); + + // if this is assign in expression then skip first child, + // because it's lvalue. + if (assign.getParent() != null + && assign.getParent().getType() == TokenTypes.EXPR) + { + child = (DetailAST) child.getNextSibling(); + } + checkExpressionSubtree(child, expectedLevel, false, true); + } + + /** + * @return true if indentation should be increased after + * fisrt line in checkLinesIndent() + * false otherwise + */ + protected boolean shouldIncreaseIndent() + { + return false; + } +} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java index a38fdc76a..c61dc32d4 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/BlockParentHandler.java @@ -203,7 +203,8 @@ public class BlockParentHandler extends ExpressionHandler { return; } - logError(rcurly, "rcurly", expandedTabsColumnNo(rcurly), curlyLevel()); + logError(rcurly, "rcurly", expandedTabsColumnNo(rcurly), + new IndentLevel(curlyLevel())); } /** diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ExpressionHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ExpressionHandler.java index 8140fd78f..d76a53cbb 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ExpressionHandler.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ExpressionHandler.java @@ -121,7 +121,8 @@ public abstract class ExpressionHandler protected final void logError(DetailAST aAst, String aSubtypeName, int aActualLevel) { - logError(aAst, aSubtypeName, aActualLevel, getLevel()); + logError(aAst, aSubtypeName, aActualLevel, + new IndentLevel(getLevel())); } /** @@ -133,13 +134,13 @@ public abstract class ExpressionHandler * @param aExpectedLevel the expected indent level of the expression */ protected final void logError(DetailAST aAst, String aSubtypeName, - int aActualLevel, int aExpectedLevel) + int aActualLevel, IndentLevel aExpectedLevel) { String typeStr = (aSubtypeName == "" ? "" : (" " + aSubtypeName)); Object[] args = new Object[] { mTypeName + typeStr, new Integer(aActualLevel), - new Integer(aExpectedLevel), + aExpectedLevel, }; mIndentCheck.indentationLog(aAst.getLineNo(), "indentation.error", @@ -226,9 +227,7 @@ public abstract class ExpressionHandler */ protected final int getLineStart(DetailAST aAst) { - // TODO: this breaks indentation -- add to tests - String line = mIndentCheck.getLines()[ - aAst.getLineNo() - 1]; + String line = mIndentCheck.getLines()[aAst.getLineNo() - 1]; return getLineStart(line); } @@ -263,7 +262,7 @@ public abstract class ExpressionHandler * fisrt line in checkLinesIndent() * false otherwise */ - protected boolean shouldIncraeseIndent() + protected boolean shouldIncreaseIndent() { return true; } @@ -303,11 +302,11 @@ public abstract class ExpressionHandler // doesn't start the line) then don't indent more, the first // indentation is absorbed by the nesting - // TODO: shouldIncreseIndent() is a hack, should be removed + // TODO: shouldIncreaseIndent() is a hack, should be removed // after complete rewriting of checkExpressionSubtree() if (aFirstLineMatches - || (aFirstLine > mMainAst.getLineNo() && shouldIncraeseIndent())) + || (aFirstLine > mMainAst.getLineNo() && shouldIncreaseIndent())) { aIndentLevel = new IndentLevel(aIndentLevel, mIndentCheck.getBasicOffset()); diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/HandlerFactory.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/HandlerFactory.java index 79798e3ef..04f54c950 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/HandlerFactory.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/HandlerFactory.java @@ -56,6 +56,7 @@ public class HandlerFactory }); mTypeHandlers.put(new Integer(aType), ctor); } + ///CLOVER:OFF catch (NoSuchMethodException e) { throw new RuntimeException("couldn't find ctor for " + aHandlerClass); @@ -65,6 +66,7 @@ public class HandlerFactory + aHandlerClass, e); } + ///CLOVER:ON } /** creates a HandlerFactory */ @@ -92,8 +94,19 @@ public class HandlerFactory register(TokenTypes.METHOD_CALL, MethodCallHandler.class); register(TokenTypes.CTOR_CALL, MethodCallHandler.class); register(TokenTypes.LABELED_STAT, LabelHandler.class); - register(TokenTypes.LABELED_STAT, LabelHandler.class); register(TokenTypes.STATIC_INIT, StaticInitHandler.class); + register(TokenTypes.ASSIGN, AssignHandler.class); + register(TokenTypes.PLUS_ASSIGN, AssignHandler.class); + register(TokenTypes.MINUS_ASSIGN, AssignHandler.class); + register(TokenTypes.STAR_ASSIGN, AssignHandler.class); + register(TokenTypes.DIV_ASSIGN, AssignHandler.class); + register(TokenTypes.MOD_ASSIGN, AssignHandler.class); + register(TokenTypes.SR_ASSIGN, AssignHandler.class); + register(TokenTypes.BSR_ASSIGN, AssignHandler.class); + register(TokenTypes.SL_ASSIGN, AssignHandler.class); + register(TokenTypes.BAND_ASSIGN, AssignHandler.class); + register(TokenTypes.BXOR_ASSIGN, AssignHandler.class); + register(TokenTypes.BOR_ASSIGN, AssignHandler.class); } /** @@ -137,12 +150,15 @@ public class HandlerFactory public ExpressionHandler getHandler(IndentationCheck aIndentCheck, DetailAST aAst, ExpressionHandler aParent) { - int type = aAst.getType(); + if (aAst.getType() == TokenTypes.METHOD_CALL) { + return createMethodCallHandler(aIndentCheck, aAst, aParent); + } + + Integer type = new Integer(aAst.getType()); ExpressionHandler expHandler = null; try { - Constructor handlerCtor = (Constructor) mTypeHandlers.get( - new Integer(type)); + Constructor handlerCtor = (Constructor) mTypeHandlers.get(type); if (handlerCtor != null) { expHandler = (ExpressionHandler) handlerCtor.newInstance( new Object[] { @@ -153,6 +169,7 @@ public class HandlerFactory ); } } + ///CLOVER:OFF catch (InstantiationException e) { throw new RuntimeException("couldn't instantiate constructor for " + aAst, e); @@ -169,6 +186,39 @@ public class HandlerFactory if (expHandler == null) { throw new RuntimeException("no handler for type " + type); } + ///CLOVER:ON return expHandler; } + + /** + * Create new instance of handler for METHOD_CALL. + * + * @param aIndentCheck the indentation check + * @param aAst ast to handle + * @param aParent the handler parent of this AST + * + * @return new instance. + */ + ExpressionHandler createMethodCallHandler(IndentationCheck aIndentCheck, + DetailAST aAst, ExpressionHandler aParent) + { + ExpressionHandler handler = + (ExpressionHandler) mCreatedHandlers.get(aAst); + if (handler != null) { + return handler; + } + + DetailAST ast = (DetailAST) aAst.getFirstChild(); + while (ast != null && ast.getType() == TokenTypes.DOT) { + ast = (DetailAST) ast.getFirstChild(); + } + if (ast != null && ast.getType() == TokenTypes.METHOD_CALL) { + aParent = createMethodCallHandler(aIndentCheck, ast, aParent); + mCreatedHandlers.put(ast, aParent); + } + return new MethodCallHandler(aIndentCheck, aAst, aParent); + } + + /** cache for created method call handlers */ + private Map mCreatedHandlers = new HashMap(); } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheck.java index 3a0696134..001d8c8d1 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheck.java @@ -258,7 +258,7 @@ public class IndentationCheck * * @return the handler factory */ - public HandlerFactory getHandlerFactory() + final HandlerFactory getHandlerFactory() { return mHandlerFactory; } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodCallHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodCallHandler.java index 7cdea5597..59896fddd 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodCallHandler.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodCallHandler.java @@ -94,10 +94,8 @@ public class MethodCallHandler extends ExpressionHandler { // if inside a method call's params, this could be part of // an expression, so get the previous line's start - if (getParent() instanceof MethodCallHandler) { - MethodCallHandler container = ((MethodCallHandler) getParent()) - .findContainingMethodCall(this); + MethodCallHandler container = ((MethodCallHandler) getParent()); if (container != null) { if (areOnSameLine(container.getMainAst(), getMainAst())) { return container.getLevel(); @@ -110,7 +108,7 @@ public class MethodCallHandler extends ExpressionHandler // if we get here, we are the child of the left hand side (name // side) of a method call with no "containing" call, use - // the first non-method callparent + // the first non-method call parent ExpressionHandler p = getParent(); while (p instanceof MethodCallHandler) { @@ -145,10 +143,6 @@ public class MethodCallHandler extends ExpressionHandler // walk down the first child part of the dots that make up a method // call name - // TODO: I'm not convinced this will work yet, what will happen - // when there is a method call in the dots? -- we would have to go - // down that call? - DetailAST ast = (DetailAST) aAst.getFirstChild(); while (ast != null && ast.getType() == TokenTypes.DOT) { ast = (DetailAST) ast.getFirstChild(); @@ -190,40 +184,6 @@ public class MethodCallHandler extends ExpressionHandler return indentLevel; } - /** - * Find the handler for the method call that contains the specified child - * - * @param aChild the child - * - * @return the handler that contains the specified child - */ - private MethodCallHandler findContainingMethodCall( - ExpressionHandler aChild) - { - DetailAST firstChild = (DetailAST) getMainAst().getFirstChild(); - DetailAST secondChild = (DetailAST) firstChild.getNextSibling(); - DetailAST climber = aChild.getMainAst().getParent(); - while (climber != null) { - if (climber == firstChild) { - // part of method name - if (getParent() instanceof MethodCallHandler) { - return ((MethodCallHandler) getParent()) - .findContainingMethodCall(this); - } - else { - return null; - } - } - else if (climber == secondChild) { - // part of method arguments, this the method the child - // is contained in - return this; - } - climber = climber.getParent(); - } - return null; - } - /** * Check the indentation of the expression we are handling. */ @@ -262,7 +222,7 @@ public class MethodCallHandler extends ExpressionHandler * fisrt line in checkLinesIndent() * false otherwise */ - protected boolean shouldIncraeseIndent() + protected boolean shouldIncreaseIndent() { return false; } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodDefHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodDefHandler.java index 470f2cf43..0255254c0 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodDefHandler.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/MethodDefHandler.java @@ -78,11 +78,11 @@ public class MethodDefHandler extends BlockParentHandler } int columnNo = expandedTabsColumnNo(throwsAst); - int expectedColumnNo = - getLevel() + getIndentCheck().getBasicOffset(); + IndentLevel expectedColumnNo = + new IndentLevel(getLevel() + getIndentCheck().getBasicOffset()); if (startsLine(throwsAst) - && columnNo != expectedColumnNo) + && !expectedColumnNo.accept(columnNo)) { logError(throwsAst, "throws", columnNo, expectedColumnNo); } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ObjectBlockHandler.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ObjectBlockHandler.java index 8125adeb1..285103cbc 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ObjectBlockHandler.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/indentation/ObjectBlockHandler.java @@ -89,13 +89,7 @@ public class ObjectBlockHandler extends BlockParentHandler */ public int getLevelImpl() { - DetailAST parentAST = getMainAst().getParent(); - if (parentAST.getType() != TokenTypes.LITERAL_NEW) { - return getParent().getLevel(); - } - else { - return getLineStart(parentAST); - } + return getParent().getLevel(); } /** diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidAssignIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidAssignIndent.java new file mode 100644 index 000000000..354482021 --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidAssignIndent.java @@ -0,0 +1,20 @@ +public class InputInvalidAssignIndent +{ + void foo(String[] args) + { + String line = mIndentCheck[ + getLineNo()]; + String line1 = + getLineNo(); + line1 = + getLineNo(); + int i + = + 1; + // TODO: this should be illegal. + i = + 3; + // TODO: add more testing + } + +} diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidIfIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidIfIndent.java index d113aebb6..700d85dab 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidIfIndent.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidIfIndent.java @@ -128,12 +128,12 @@ public class InputInvalidIfIndent { } // lcurly for if and else on same line if (test) { - // TODO: broken -// System. -// getProperty("blah"); + + System. + getProperty("blah"); } else { -// System. // TODO: broken -// getProperty("blah"); + System. + getProperty("blah"); } // lcurly for if and else on same line diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidMethodIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidMethodIndent.java index 8e8defb53..73f348abb 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidMethodIndent.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputInvalidMethodIndent.java @@ -147,7 +147,7 @@ public class InputInvalidMethodIndent { // getInteger("mytest").intValue(), // 11); - // TODO: should complain about indentation + System.out.toString() .equals("blah"); diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidAssignIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidAssignIndent.java new file mode 100644 index 000000000..906565a2e --- /dev/null +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidAssignIndent.java @@ -0,0 +1,25 @@ +public class InputValidAssignIndent +{ + void foo(String[] args) + { + i = 1 + + 2 + + 3; + String line = mIndentCheck[ + getLineNo()]; + String line1 = + getLineNo(); + line1 = + getLineNo(); + int i + = + 1; + i = 3; + + brace = + (candidate == SLIST) + ? candidate : null; + // TODO: add more testing + } + +} diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidDotIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidDotIndent.java index dcdf742b3..02a1f6c8f 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidDotIndent.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidDotIndent.java @@ -46,9 +46,9 @@ public class InputValidDotIndent { border = new javax.swing.border. BevelBorder(BevelBorder.LOWERED); - // TODO: enable this when function parameter handling is turned on -// border = new javax.swing.border.BevelBorder( -// BevelBorder.LOWERED); + + border = new javax.swing.border.BevelBorder( + BevelBorder.LOWERED); border = new javax. swing. border. diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidMethodIndent.java b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidMethodIndent.java index 7f10910c7..93e73acb7 100644 --- a/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidMethodIndent.java +++ b/src/testinputs/com/puppycrawl/tools/checkstyle/indentation/InputValidMethodIndent.java @@ -176,7 +176,7 @@ public class InputValidMethodIndent extends java.awt.event.MouseAdapter implemen + method1()); System.out.toString() - .equals("blah"); + .equals("blah"); if (!areOnSameLine((DetailAST)aChild.expr.getFirstChild(), diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java index 0076df32e..ce4299233 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/indentation/IndentationCheckTest.java @@ -115,8 +115,7 @@ public class IndentationCheckTest extends BaseCheckTestCase { "125: method call rparen at indentation level 6 not at correct indentation, 8", "139: method call child at indentation level 10 not at correct indentation, 12", "142: method call child at indentation level 10 not at correct indentation, 12", - // todo: 152 -- 8 should be 12 - "152: method call child at indentation level 6 not at correct indentation, 8", + "152: method call child at indentation level 6 not at correct indentation, 12", "158: method def throws at indentation level 6 not at correct indentation, 8", }; verify(c, fname, expected); @@ -320,10 +319,6 @@ public class IndentationCheckTest extends BaseCheckTestCase { "121: class def rcurly at indentation level 10 not at correct indentation, 8", "124: class def child at indentation level 10 not at correct indentation, 12", "129: method def child at indentation level 10 not at correct indentation, 8", - "130: object def lcurly at indentation level 8 not at correct indentation, 10", - "131: method def modifier at indentation level 12 not at correct indentation, 14", - "133: method def rcurly at indentation level 12 not at correct indentation, 14", - "134: object def rcurly at indentation level 8 not at correct indentation, 10", "138: object def lcurly at indentation level 6 not at correct indentation, 8", "142: object def rcurly at indentation level 6 not at correct indentation, 8", "147: method def modifier at indentation level 10 not at correct indentation, 12", @@ -438,6 +433,13 @@ public class IndentationCheckTest extends BaseCheckTestCase { "126: if lcurly at indentation level 10 not at correct indentation, 8", "127: if child at indentation level 10 not at correct indentation, 12", "127: method call child at indentation level 10 not at correct indentation, 12", + "132: if child at indentation level 14 not at correct indentation, 12", + // TODO: should be 16, not 12 + "133: method call child at indentation level 10 not at correct indentation, 12", + "135: else child at indentation level 10 not at correct indentation, 12", + // TODO: why we get this message (it's duplicate of previous. + "135: method call child at indentation level 10 not at correct indentation, 12", + "136: method call child at indentation level 8 not at correct indentation, 12", "143: if child at indentation level 16 not at correct indentation, 12", "144: if rcurly at indentation level 9 not at correct indentation, 8", "147: else child at indentation level 16 not at correct indentation, 12", @@ -670,5 +672,23 @@ public class IndentationCheckTest extends BaseCheckTestCase { verify(checkConfig, getPath("indentation/InputBraceAdjustment.java"), expected); } + public void testInvalidAssignWithChecker() throws Exception + { + final DefaultConfiguration checkConfig = createCheckConfig(IndentationCheck.class); + final String[] expected = { + "6: method call child at indentation level 10 not at correct indentation, 12", + "8: method call child at indentation level 10 not at correct indentation, 12", + "10: method call child at indentation level 10 not at correct indentation, 12", + "12: assign at indentation level 9 not at correct indentation, 12", + "13: assign child at indentation level 10 not at correct indentation, 12", + }; + verify(checkConfig, getPath("indentation/InputInvalidAssignIndent.java"), expected); + } + public void testValidAssignWithChecker() throws Exception + { + final DefaultConfiguration checkConfig = createCheckConfig(IndentationCheck.class); + final String[] expected = {}; + verify(checkConfig, getPath("indentation/InputValidAssignIndent.java"), expected); + } }