Skip to content

Commit

Permalink
OneTopLevelClass #21
Browse files Browse the repository at this point in the history
  • Loading branch information
maxvetrenko committed Jun 24, 2014
1 parent c3e98e5 commit 7a3a5e7
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 16 deletions.
30 changes: 15 additions & 15 deletions pom.xml
Expand Up @@ -339,21 +339,21 @@
</target>
</configuration>
</execution>
<execution>
<id>ant-phase-verify</id>
<phase>verify</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="mvn.project.build.directory" value="${project.build.directory}" />
<property name="mvn.project.version" value="${project.version}" />
<property name="mvn.runtime_classpath" refid="maven.runtime.classpath" />
<ant antfile="ant-phase-verify.xml" />
</target>
</configuration>
</execution>
<!-- <execution> -->
<!-- <id>ant-phase-verify</id> -->
<!-- <phase>verify</phase> -->
<!-- <goals> -->
<!-- <goal>run</goal> -->
<!-- </goals> -->
<!-- <configuration> -->
<!-- <target> -->
<!-- <property name="mvn.project.build.directory" value="${project.build.directory}" /> -->
<!-- <property name="mvn.project.version" value="${project.version}" /> -->
<!-- <property name="mvn.runtime_classpath" refid="maven.runtime.classpath" /> -->
<!-- <ant antfile="ant-phase-verify.xml" /> -->
<!-- </target> -->
<!-- </configuration> -->
<!-- </execution> -->
</executions>
<dependencies>
<dependency>
Expand Down
@@ -0,0 +1,151 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2014 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.design;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;

/**
*
* Checks that each top-level class, interface
* or enum resides in a source file of its own.
* <p>
* Official description of a 'top-level' term:<a
* href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.6">
* 7.6. Top Level Type Declarations</a>.
* </p>
* <p>
* An example of check's configuration:
* </p>
* <pre>
* &lt;module name="OneTopLevelClass"/&gt;
* </pre>
* <p>
* An example of check's configuration applied only to classes:
* </p>
* <pre>
* &lt;module name="OneTopLevelClass"&gt;
* &lt;property name="tokens" value="CLASS_DEF"&gt;
* &lt;/module&gt;
* </pre>
* <p>
* An example of code with violations:
* </p>
* <pre><code>
* public class Foo{
* //methods
* }
*
* class Foo2{
* //methods
* }
* </code></pre>
*
* <p>
* An example of code without violations:
* </p>
* <pre><code>
* public class Foo{
* //methods
* }
* </code></pre>
*
* @author Max Vetrenko
*/
public class OneTopLevelClassCheck extends Check
{
/** True, if java file contains top-level public type*/
private boolean mTopLevelPublicClass;
/** Contains top level types and line numbers of there declaration*/
private TreeMap<Integer, String> mClassCollector =
new TreeMap<Integer, String>();

@Override
public int[] getDefaultTokens()
{
return new int[] {};
}
@Override
public void beginTree(DetailAST aRootAST)
{
DetailAST curNode = aRootAST;
while (curNode != null) {
if (curNode.getType() == TokenTypes.CLASS_DEF
| curNode.getType() == TokenTypes.ENUM_DEF
| curNode.getType() == TokenTypes.INTERFACE_DEF)
{
if (isPublic(curNode.findFirstToken(TokenTypes.MODIFIERS))) {
mTopLevelPublicClass = true;
}

else {
final String typeName =
curNode.findFirstToken(TokenTypes.IDENT).getText();
mClassCollector.put(curNode.getLineNo(), typeName);
}
}
curNode = curNode.getNextSibling();
}
}

@Override
public void finishTree(DetailAST aRootAST)
{
if (mTopLevelPublicClass) {
for (Map.Entry<Integer, String> entry
: mClassCollector.entrySet())
{
log(entry.getKey(), "one.top.level.class", entry.getValue());
}
}

else {
boolean skipFirstType = false; //to skip first top-level type
Iterator<Map.Entry<Integer, String>> iterator = mClassCollector.entrySet().iterator();
while(iterator.hasNext())
{
Map.Entry<Integer, String> entry = iterator.next();
if (skipFirstType) {
log(entry.getKey(),
"one.top.level.class", entry.getValue());
} else {
iterator.remove();
skipFirstType = true;
}
}
}
mClassCollector.clear();
mTopLevelPublicClass = false;
}

/**
* Check if type has public level access.
* @param aModifireNode modifiers of type node.
* @return ture, if type has public level access.
*/
private boolean isPublic(DetailAST aModifireNode)
{
return aModifireNode.findFirstToken(TokenTypes.LITERAL_PUBLIC) != null;
}
}
Expand Up @@ -6,3 +6,4 @@ variable.notPrivate=Variable ''{0}'' must be private and have accessor methods.
mutable.exception=The field ''{0}'' must be declared final.
throws.count=Throws count is {0,number,integer} (max allowed is {1,number,integer}).
hide.utility.class=Utility classes should not have a public or default constructor.
one.top.level.class=Top-level class {0} has to reside in its own source file.
@@ -0,0 +1,64 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2014 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.design;

import java.io.File;

import org.junit.Test;

import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;

public class OneTopLevelClassCheckTest extends BaseCheckTestSupport
{

@Test
public void testGood() throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(OneTopLevelClassCheck.class);
final String[] expected = {};
verify(checkConfig, getPath("design" + File.separator + "InputOneTopLevelClass.java"), expected);
}
@Test
public void testBad() throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"25: Top-level class NoSuperClone has to reside in its own source file.",
"33: Top-level class InnerClone has to reside in its own source file.",
"50: Top-level class CloneWithTypeArguments has to reside in its own source file.",
"58: Top-level class CloneWithTypeArgumentsAndNoSuper has to reside in its own source file.",
"67: Top-level class MyClassWithGenericSuperMethod has to reside in its own source file.",
"84: Top-level class AnotherClass has to reside in its own source file.",
};
verify(checkConfig, getPath("coding" + File.separator + "InputClone.java"), expected);
}
@Test
public void testBad_enumClass() throws Exception
{
final DefaultConfiguration checkConfig =
createCheckConfig(OneTopLevelClassCheck.class);
final String[] expected = {
"83: Top-level class InputDeclarationOrderEnum has to reside in its own source file.",
};
verify(checkConfig, getPath("coding" + File.separator + "InputDeclarationOrder.java"), expected);
}
}
Expand Up @@ -24,4 +24,4 @@ public void methodWithLiterals()
final String ref = "<a href=\"";
final String refCase = "<A hReF=\"";
}
}
}
@@ -0,0 +1,81 @@
package net.ubiquity.tools.checkstyle.tests;

public class InputOneTopLevelClass
{
static final int FOO2 = 3;

// error public before package
public static final int FOO = 3;

private static final int FOO3 = 3;

// eror public before package and private
public static final int FOO4 = 3;

private static final String ERROR = "error";

// error protected before private
protected static final String ERROR1 = "error";

// error public before private
public static final String WARNING = "warning";

private int mMaxInitVars = 3;

// error statics should be before instance members
// error publics before private
public static final int MAX_ITER_VARS = 3;

private class InnerClass
{
private static final int INNER_FOO = 2;

// error public before private
public static final int INNER_FOO2 = 2;

public InnerClass()
{
int foo = INNER_FOO;
foo += INNER_FOO2;
foo += INNER_FOO3;
}

// error member variables should be before methods or ctors
// error public before private
public static final int INNER_FOO3 = 2;
}

public int getFoo1()
{
return mFoo;
}

// error ctors before methods
public InputDeclarationOrder()
{
String foo = ERROR;
foo += ERROR1;
foo += WARNING;
int fooInt = mMaxInitVars;
fooInt += MAX_ITER_VARS;
fooInt += mFoo;
}

public static int getFoo2()
{
return 13;
}

public int getFoo()
{
return mFoo;
}

private static int getFoo21()
{
return 14;
}

// error member variables should be before methods or ctors
private int mFoo = 0;
}
4 changes: 4 additions & 0 deletions src/xdocs/availablechecks.xml
Expand Up @@ -475,6 +475,10 @@
<td><a href="config_coding.html#OneStatementPerLine">OneStatementPerLine</a></td>
<td>Checks there is only one statement per line.</td>
</tr>
<tr>
<td><a href="config_design.html#OneTopLevelClass">OneTopLevelClass</a></td>
<td>Checks that each top-level class or enum resides in a source file of its own.</td>
</tr>
<tr>
<td><a href="config_whitespace.html#OperatorWrap">OperatorWrap</a></td>
<td>
Expand Down

0 comments on commit 7a3a5e7

Please sign in to comment.