Skip to content

Commit

Permalink
Issue checkstyle#7754: Update AbstractChecks to log DetailAST - OneTo…
Browse files Browse the repository at this point in the history
…pLevelClass
  • Loading branch information
wltan authored and strkkk committed Mar 11, 2020
1 parent 6fcb2d5 commit e73ec41
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ public void testBad() throws Exception {
final String messageKey = "one.top.level.class";

final String[] expected = {
"25: " + getCheckMessage(clazz, messageKey, "NoSuperClone"),
"33: " + getCheckMessage(clazz, messageKey, "InnerClone"),
"50: " + getCheckMessage(clazz, messageKey, "CloneWithTypeArguments"),
"55: " + getCheckMessage(clazz, messageKey, "CloneWithTypeArgumentsAndNoSuper"),
"60: " + getCheckMessage(clazz, messageKey, "MyClassWithGenericSuperMethod"),
"77: " + getCheckMessage(clazz, messageKey, "AnotherClass"),
"25:1: " + getCheckMessage(clazz, messageKey, "NoSuperClone"),
"33:1: " + getCheckMessage(clazz, messageKey, "InnerClone"),
"50:1: " + getCheckMessage(clazz, messageKey, "CloneWithTypeArguments"),
"55:1: " + getCheckMessage(clazz, messageKey, "CloneWithTypeArgumentsAndNoSuper"),
"60:1: " + getCheckMessage(clazz, messageKey, "MyClassWithGenericSuperMethod"),
"77:1: " + getCheckMessage(clazz, messageKey, "AnotherClass"),
};

final Configuration checkConfig = getModuleConfig("OneTopLevelClass");
Expand All @@ -71,7 +71,7 @@ public void testBad1() throws Exception {
final String messageKey = "one.top.level.class";

final String[] expected = {
"4: " + getCheckMessage(clazz, messageKey, "FooEnum"),
"4:1: " + getCheckMessage(clazz, messageKey, "FooEnum"),
};

final Configuration checkConfig = getModuleConfig("OneTopLevelClass");
Expand All @@ -87,8 +87,8 @@ public void testBad2() throws Exception {
final String messageKey = "one.top.level.class";

final String[] expected = {
"5: " + getCheckMessage(clazz, messageKey, "FooIn"),
"7: " + getCheckMessage(clazz, messageKey, "FooClass"),
"5:1: " + getCheckMessage(clazz, messageKey, "FooIn"),
"7:1: " + getCheckMessage(clazz, messageKey, "FooClass"),
};

final Configuration checkConfig = getModuleConfig("OneTopLevelClass");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
////////////////////////////////////////////////////////////////////////////////
// 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.design.OneTopLevelClassCheck;

public class XpathRegressionOneTopLevelClassTest extends AbstractXpathTestSupport {

private final String checkName = OneTopLevelClassCheck.class.getSimpleName();

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

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

final DefaultConfiguration moduleConfig =
createModuleConfig(OneTopLevelClassCheck.class);

final String[] expectedViolation = {
"7:1: " + getCheckMessage(OneTopLevelClassCheck.class,
OneTopLevelClassCheck.MSG_KEY, "ViolatingSecondClass"),
};

final List<String> expectedXpathQueries = Arrays.asList(
"/CLASS_DEF[./IDENT[@text='ViolatingSecondClass']]",
"/CLASS_DEF[./IDENT[@text='ViolatingSecondClass']]/MODIFIERS",
"/CLASS_DEF[./IDENT[@text='ViolatingSecondClass']]/LITERAL_CLASS"
);

runVerifications(moduleConfig, fileToProcess, expectedViolation,
expectedXpathQueries);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.checkstyle.suppressionxpathfilter.onetoplevelclass;

public class SuppressionXpathRegressionOneTopLevelClass {
// methods
}

class ViolatingSecondClass { //warn
// methods
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package com.puppycrawl.tools.checkstyle.checks.design;

import java.util.Comparator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
Expand Down Expand Up @@ -92,14 +93,19 @@ public class OneTopLevelClassCheck extends AbstractCheck {
*/
public static final String MSG_KEY = "one.top.level.class";

/** Compare DetailAST nodes by line and then column number to make a unique ordering. */
private static final Comparator<DetailAST> LINE_AND_COL_COMPARATOR =
Comparator.comparingInt(DetailAST::getLineNo).thenComparingInt(DetailAST::getColumnNo);

/**
* True if a java source file contains a type
* with a public access level modifier.
*/
private boolean publicTypeFound;

/** Mapping between type names and line numbers of the type declarations.*/
private final SortedMap<Integer, String> lineNumberTypeMap = new TreeMap<>();
/** Mapping between type names and DetailAST nodes of the type declarations. */
private final SortedMap<DetailAST, String> lineNumberTypeMap =
new TreeMap<>(LINE_AND_COL_COMPARATOR);

@Override
public int[] getDefaultTokens() {
Expand Down Expand Up @@ -133,7 +139,7 @@ public void beginTree(DetailAST rootAST) {
else {
final String typeName = currentNode
.findFirstToken(TokenTypes.IDENT).getText();
lineNumberTypeMap.put(currentNode.getLineNo(), typeName);
lineNumberTypeMap.put(currentNode, typeName);
}
}
currentNode = currentNode.getNextSibling();
Expand All @@ -148,7 +154,7 @@ public void finishTree(DetailAST rootAST) {
lineNumberTypeMap.remove(lineNumberTypeMap.firstKey());
}

for (Map.Entry<Integer, String> entry
for (Map.Entry<DetailAST, String> entry
: lineNumberTypeMap.entrySet()) {
log(entry.getKey(), MSG_KEY, entry.getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@
* NoLineWrap
* </li>
* <li>
* OneTopLevelClass
* </li>
* <li>
* OuterTypeFilename
* </li>
* <li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ public void testClearState() throws Exception {
};

final List<String> expectedFirstInput = Collections.singletonList(
"10: " + getCheckMessage(MSG_KEY, "InputDeclarationOrderEnum"));
"10:1: " + getCheckMessage(MSG_KEY, "InputDeclarationOrderEnum"));
final List<String> expectedSecondInput = Arrays.asList(
"3: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner1"),
"11: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner2"));
"3:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner1"),
"11:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner2"));

verify(createChecker(checkConfig), inputs,
ImmutableMap.of(firstInputFilePath, expectedFirstInput,
Expand Down Expand Up @@ -111,7 +111,7 @@ public void testFileWithNoPublicTopLevelClass() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"8: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassNoPublic2"),
"8:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassNoPublic2"),
};
verify(checkConfig, getPath("InputOneTopLevelClassNoPublic.java"), expected);
}
Expand All @@ -121,8 +121,8 @@ public void testFileWithThreeTopLevelInterface() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"3: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner1"),
"11: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner2"),
"3:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner1"),
"11:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassInterface2inner2"),
};
verify(checkConfig, getPath("InputOneTopLevelClassInterface2.java"), expected);
}
Expand All @@ -132,8 +132,8 @@ public void testFileWithThreeTopLevelEnum() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"3: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassEnum2inner1"),
"11: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassEnum2inner2"),
"3:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassEnum2inner1"),
"11:1: " + getCheckMessage(MSG_KEY, "InputOneTopLevelClassEnum2inner2"),
};
verify(checkConfig, getPath("InputOneTopLevelClassEnum2.java"), expected);
}
Expand All @@ -143,13 +143,13 @@ public void testFileWithFewTopLevelClasses() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"25: " + getCheckMessage(MSG_KEY, "NoSuperClone"),
"29: " + getCheckMessage(MSG_KEY, "InnerClone"),
"33: " + getCheckMessage(MSG_KEY, "CloneWithTypeArguments"),
"37: " + getCheckMessage(MSG_KEY, "CloneWithTypeArgumentsAndNoSuper"),
"41: " + getCheckMessage(MSG_KEY, "MyClassWithGenericSuperMethod"),
"45: " + getCheckMessage(MSG_KEY, "AnotherClass"),
"48: " + getCheckMessage(MSG_KEY, "NativeTest"),
"25:1: " + getCheckMessage(MSG_KEY, "NoSuperClone"),
"29:1: " + getCheckMessage(MSG_KEY, "InnerClone"),
"33:1: " + getCheckMessage(MSG_KEY, "CloneWithTypeArguments"),
"37:1: " + getCheckMessage(MSG_KEY, "CloneWithTypeArgumentsAndNoSuper"),
"41:1: " + getCheckMessage(MSG_KEY, "MyClassWithGenericSuperMethod"),
"45:1: " + getCheckMessage(MSG_KEY, "AnotherClass"),
"48:1: " + getCheckMessage(MSG_KEY, "NativeTest"),
};
verify(checkConfig, getPath("InputOneTopLevelClassClone.java"), expected);
}
Expand All @@ -159,7 +159,7 @@ public void testFileWithSecondEnumTopLevelClass() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"10: " + getCheckMessage(MSG_KEY, "InputDeclarationOrderEnum"),
"10:1: " + getCheckMessage(MSG_KEY, "InputDeclarationOrderEnum"),
};
verify(checkConfig, getPath("InputOneTopLevelClassDeclarationOrder.java"), expected);
}
Expand All @@ -171,4 +171,26 @@ public void testPackageInfoWithNoTypesDeclared() throws Exception {
verify(checkConfig, getNonCompilablePath("package-info.java"), expected);
}

@Test
public void testFileWithMultipleSameLine() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"3:47: " + getCheckMessage(MSG_KEY, "ViolatingSecondType"),
};
verify(checkConfig, getPath("InputOneTopLevelClassSameLine.java"), expected);
}

@Test
public void testFileWithIndentation() throws Exception {
final DefaultConfiguration checkConfig =
createModuleConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"7:2: " + getCheckMessage(MSG_KEY, "ViolatingIndentedClass1"),
"11:5: " + getCheckMessage(MSG_KEY, "ViolatingIndentedClass2"),
"15:1: " + getCheckMessage(MSG_KEY, "ViolatingNonIndentedInterface"),
};
verify(checkConfig, getPath("InputOneTopLevelClassIndentation.java"), expected);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public class XpathRegressionTest extends AbstractModuleTestSupport {
"NeedBraces",
"NoFinalizer",
"NoLineWrap",
"OneTopLevelClass",
"OuterTypeFilename",
"OverloadMethodsDeclarationOrder",
"PackageAnnotation",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.puppycrawl.tools.checkstyle.checks.design.onetoplevelclass;

public class InputOneTopLevelClassIndentation {
// methods
}

class ViolatingIndentedClass1 {
// methods
}

class ViolatingIndentedClass2 {
// methods
}

interface ViolatingNonIndentedInterface {
// methods
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.puppycrawl.tools.checkstyle.checks.design.onetoplevelclass;

public class InputOneTopLevelClassSameLine {} enum ViolatingSecondType {}
1 change: 0 additions & 1 deletion src/xdocs/config_filters.xml
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,6 @@ public class UserService {
<li>NeedBraces</li>
<li>NoFinalizer</li>
<li>NoLineWrap</li>
<li>OneTopLevelClass</li>
<li>OuterTypeFilename</li>
<li>OverloadMethodsDeclarationOrder</li>
<li>PackageAnnotation</li>
Expand Down

0 comments on commit e73ec41

Please sign in to comment.