Skip to content

Commit

Permalink
Issue checkstyle#7734: Update AbstractChecks to log DetailAST - Inden…
Browse files Browse the repository at this point in the history
…tation
  • Loading branch information
Abhishek-kumar09 committed Apr 16, 2020
1 parent 0294924 commit 8dcc41a
Show file tree
Hide file tree
Showing 19 changed files with 910 additions and 767 deletions.
Expand Up @@ -127,10 +127,11 @@ public void testCorrectChained() throws Exception {
@Test
public void testWarnChained() throws Exception {
final String[] expected = {
"18: " + getCheckMessage(IndentationCheck.class, MSG_CHILD_ERROR, "method call", 4, 8),
"23: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, ".", 4, 8),
"24: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, ".", 4, 8),
"27: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, "new", 4, 8),
"18:5: " + getCheckMessage(IndentationCheck.class,
MSG_CHILD_ERROR, "method call", 4, 8),
"23:5: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, ".", 4, 8),
"24:5: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, ".", 4, 8),
"27:5: " + getCheckMessage(IndentationCheck.class, MSG_ERROR, "new", 4, 8),
};

final Configuration checkConfig = getModuleConfig("Indentation");
Expand Down
@@ -0,0 +1,143 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2020 the original author or authors.
//
// 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 org.checkstyle.suppressionxpathfilter;

import java.io.File;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;

import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
import com.puppycrawl.tools.checkstyle.checks.indentation.IndentationCheck;

public class XpathRegressionIndentationTest extends AbstractXpathTestSupport {
private final String checkName = IndentationCheck.class.getSimpleName();

@Override
protected String getCheckName() {
return checkName;
}

@Test
public void testOne() throws Exception {
final File fileToProcess =
new File(getPath("SuppressionXpathRegressionIndentationTestOne.java"));

final DefaultConfiguration moduleConfig =
createModuleConfig(IndentationCheck.class);

final String[] expectedViolation = {
"4:1: " + getCheckMessage(IndentationCheck.class,
IndentationCheck.MSG_ERROR, "method def modifier", 0, 4),
};

final List<String> expectedXpathQueries = Arrays.asList(
"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestOne']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='wrongIntend']]",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestOne']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='wrongIntend']]/MODIFIERS",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestOne']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='wrongIntend']]/TYPE",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestOne']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='wrongIntend']]/TYPE/LITERAL_VOID"
);

runVerifications(moduleConfig, fileToProcess, expectedViolation,
expectedXpathQueries);
}

@Test
public void testBasicOffset() throws Exception {
final File fileToProcess =
new File(getPath("SuppressionXpathRegressionIndentationTestTwo.java"));

final DefaultConfiguration moduleConfig =
createModuleConfig(IndentationCheck.class);
moduleConfig.addAttribute("arrayInitIndent", "4");
moduleConfig.addAttribute("basicOffset", "10");
moduleConfig.addAttribute("braceAdjustment", "0");
moduleConfig.addAttribute("caseIndent", "4");
moduleConfig.addAttribute("forceStrictCondition", "false");
moduleConfig.addAttribute("lineWrappingIndentation", "4");
moduleConfig.addAttribute("tabWidth", "4");
moduleConfig.addAttribute("throwsIndent", "4");

final String[] expectedViolation = {
"4:5: " + getCheckMessage(IndentationCheck.class,
IndentationCheck.MSG_ERROR, "method def modifier", 4, 10),
};

final List<String> expectedXpathQueries = Arrays.asList(
"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestTwo']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestTwo']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/MODIFIERS",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestTwo']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/TYPE",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestTwo']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/TYPE/LITERAL_VOID"
);

runVerifications(moduleConfig, fileToProcess, expectedViolation,
expectedXpathQueries);
}

@Test
public void testCaseIndent() throws Exception {
final File fileToProcess =
new File(getPath("SuppressionXpathRegressionIndentationTestThree.java"));

final DefaultConfiguration moduleConfig =
createModuleConfig(IndentationCheck.class);
moduleConfig.addAttribute("arrayInitIndent", "4");
moduleConfig.addAttribute("basicOffset", "4");
moduleConfig.addAttribute("braceAdjustment", "0");
moduleConfig.addAttribute("caseIndent", "4");
moduleConfig.addAttribute("forceStrictCondition", "false");
moduleConfig.addAttribute("lineWrappingIndentation", "4");
moduleConfig.addAttribute("tabWidth", "4");
moduleConfig.addAttribute("throwsIndent", "4");

final String[] expectedViolation = {
"7:9: " + getCheckMessage(IndentationCheck.class,
IndentationCheck.MSG_CHILD_ERROR, "case", 8, 12),
};

final List<String> expectedXpathQueries = Arrays.asList(
"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestThree']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/SLIST/LITERAL_SWITCH/"
+ "CASE_GROUP",

"/CLASS_DEF[./IDENT[@text='SuppressionXpathRegressionIndentationTestThree']]"
+ "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/SLIST/LITERAL_SWITCH/"
+ "CASE_GROUP/LITERAL_CASE"
);

runVerifications(moduleConfig, fileToProcess, expectedViolation,
expectedXpathQueries);
}
}
@@ -0,0 +1,6 @@
package org.checkstyle.suppressionxpathfilter.indentation;

public class SuppressionXpathRegressionIndentationTestOne {
void wrongIntend() { // warn
}
}
@@ -0,0 +1,11 @@
package org.checkstyle.suppressionxpathfilter.indentation;

public class SuppressionXpathRegressionIndentationTestThree {
void test() {
int key = 5;
switch (key) {
case 1: // warn
break;
}
}
}
@@ -0,0 +1,5 @@
package org.checkstyle.suppressionxpathfilter.indentation;

public class SuppressionXpathRegressionIndentationTestTwo {
void test() {} // warn
}
Expand Up @@ -143,25 +143,25 @@ protected final void logError(DetailAST ast, String subtypeName,
if (expectedIndent.isMultiLevel()) {
messageKey = IndentationCheck.MSG_ERROR_MULTI;
}
indentCheck.indentationLog(ast.getLineNo(), messageKey,
indentCheck.indentationLog(ast, messageKey,
typeName + typeStr, actualIndent, expectedIndent);
}

/**
* Log child indentation error.
*
* @param line the expression that caused the error
* @param ast the abstract syntax tree that causes the error
* @param actualIndent the actual indent level of the expression
* @param expectedIndent the expected indent level of the expression
*/
private void logChildError(int line,
private void logChildError(DetailAST ast,
int actualIndent,
IndentLevel expectedIndent) {
String messageKey = IndentationCheck.MSG_CHILD_ERROR;
if (expectedIndent.isMultiLevel()) {
messageKey = IndentationCheck.MSG_CHILD_ERROR_MULTI;
}
indentCheck.indentationLog(line, messageKey,
indentCheck.indentationLog(ast, messageKey,
typeName, actualIndent, expectedIndent);
}

Expand Down Expand Up @@ -251,26 +251,26 @@ protected boolean shouldIncreaseIndent() {
/**
* Check the indentation for a set of lines.
*
* @param lines the set of lines to check
* @param astSet the set of abstract syntax tree to check
* @param indentLevel the indentation level
* @param firstLineMatches whether or not the first line has to match
* @param firstLine first line of whole expression
*/
private void checkLinesIndent(LineSet lines,
private void checkLinesIndent(DetailAstSet astSet,
IndentLevel indentLevel,
boolean firstLineMatches,
int firstLine) {
if (!lines.isEmpty()) {
if (!astSet.isEmpty()) {
// check first line
final int startLine = lines.firstLine();
final int endLine = lines.lastLine();
final int startCol = lines.firstLineCol();
final DetailAST startLine = astSet.firstLine();
final int endLine = astSet.lastLine();
final int startCol = expandedTabsColumnNo(astSet.firstLine());

final int realStartCol =
getLineStart(indentCheck.getLine(startLine - 1));
getLineStart(indentCheck.getLine(startLine.getLineNo() - 1));

if (realStartCol == startCol) {
checkLineIndent(startLine, startCol, indentLevel,
checkLineIndent(startLine, indentLevel,
firstLineMatches);
}

Expand All @@ -287,14 +287,14 @@ private void checkLinesIndent(LineSet lines,
}

// check following lines
for (int i = startLine + 1; i <= endLine; i++) {
final Integer col = lines.getStartColumn(i);
for (int i = startLine.getLineNo() + 1; i <= endLine; i++) {
final Integer col = astSet.getStartColumn(i);
// startCol could be null if this line didn't have an
// expression that was required to be checked (it could be
// checked by a child expression)

if (col != null) {
checkLineIndent(i, col, theLevel, false);
checkLineIndent(astSet.getAst(i), theLevel, false);
}
}
}
Expand All @@ -303,22 +303,21 @@ private void checkLinesIndent(LineSet lines,
/**
* Check the indentation for a single line.
*
* @param lineNum the number of the line to check
* @param colNum the column number we are starting at
* @param ast the abstract syntax tree to check
* @param indentLevel the indentation level
* @param mustMatch whether or not the indentation level must match
*/
private void checkLineIndent(int lineNum, int colNum,
private void checkLineIndent(DetailAST ast,
IndentLevel indentLevel, boolean mustMatch) {
final String line = indentCheck.getLine(lineNum - 1);
final String line = indentCheck.getLine(ast.getLineNo() - 1);
final int start = getLineStart(line);
// if must match is set, it is a violation if the line start is not
// at the correct indention level; otherwise, it is an only an
// violation if this statement starts the line and it is less than
// the correct indentation level
if (mustMatch && !indentLevel.isAcceptable(start)
|| !mustMatch && colNum == start && indentLevel.isGreaterThan(start)) {
logChildError(lineNum, start, indentLevel);
|| !mustMatch && ast.getColumnNo() == start && indentLevel.isGreaterThan(start)) {
logChildError(ast, start, indentLevel);
}
}

Expand Down Expand Up @@ -390,37 +389,51 @@ protected final void checkExpressionSubtree(
boolean firstLineMatches,
boolean allowNesting
) {
final LineSet subtreeLines = new LineSet();
final int firstLine = getFirstLine(Integer.MAX_VALUE, tree);
final DetailAstSet subtreeAst = new DetailAstSet();
final int firstLine = getFirstLine(tree);
if (firstLineMatches && !allowNesting) {
subtreeLines.addLineAndCol(firstLine,
getLineStart(indentCheck.getLine(firstLine - 1)));
final DetailAST firstAst = getFirstAst(tree, tree);
subtreeAst.addAst(firstAst);
}
findSubtreeLines(subtreeLines, tree, allowNesting);
findSubtreeAst(subtreeAst, tree, allowNesting);

checkLinesIndent(subtreeLines, indentLevel, firstLineMatches, firstLine);
checkLinesIndent(subtreeAst, indentLevel, firstLineMatches, firstLine);
}

/**
* Get the first line for a given expression.
* Get the first line number for given expression.
*
* @param startLine the line we are starting from
* @param tree the expression to find the first line for
* @return the first line of expression
*/
protected static int getFirstLine(DetailAST tree) {
return getFirstAst(tree, tree).getLineNo();
}

/**
* Get the first ast for given expression.
*
* @param ast the current ast that may have minimum line number
* @param tree the expression to find the first line for
*
* @return the first line of the expression
* @return the first ast of the expression
*/
protected static int getFirstLine(int startLine, DetailAST tree) {
int realStart = startLine;
final int currLine = tree.getLineNo();
if (currLine < realStart) {
realStart = currLine;
protected static DetailAST getFirstAst(DetailAST ast, DetailAST tree) {
DetailAST realStart = ast;

if (tree.getLineNo() < realStart.getLineNo()) {
realStart = tree;
}
if (tree.getLineNo() == realStart.getLineNo()
&& tree.getColumnNo() < realStart.getColumnNo()) {
realStart = tree;
}

// check children
for (DetailAST node = tree.getFirstChild();
node != null;
node = node.getNextSibling()) {
realStart = getFirstLine(realStart, node);
node != null;
node = node.getNextSibling()) {
realStart = getFirstAst(realStart, node);
}

return realStart;
Expand All @@ -443,28 +456,28 @@ protected final int expandedTabsColumnNo(DetailAST ast) {
}

/**
* Find the set of lines for a given subtree.
* Find the set of abstract syntax tree for a given subtree.
*
* @param lines the set of lines to add to
* @param astSet the set of ast to add
* @param tree the subtree to examine
* @param allowNesting whether or not to allow nested subtrees
*/
protected final void findSubtreeLines(LineSet lines, DetailAST tree,
protected final void findSubtreeAst(DetailAstSet astSet, DetailAST tree,
boolean allowNesting) {
if (!indentCheck.getHandlerFactory().isHandledType(tree.getType())) {
final int lineNum = tree.getLineNo();
final Integer colNum = lines.getStartColumn(lineNum);
final Integer colNum = astSet.getStartColumn(lineNum);

final int thisLineColumn = expandedTabsColumnNo(tree);
if (colNum == null || thisLineColumn < colNum) {
lines.addLineAndCol(lineNum, thisLineColumn);
astSet.addAst(tree);
}

// check children
for (DetailAST node = tree.getFirstChild();
node != null;
node = node.getNextSibling()) {
findSubtreeLines(lines, node, allowNesting);
findSubtreeAst(astSet, node, allowNesting);
}
}
}
Expand Down

0 comments on commit 8dcc41a

Please sign in to comment.