Add new options to the ImportOrderCheck to make it more flexible. Thanks to David Didier for providing patch #1854213.
This commit is contained in:
parent
94e8285d4c
commit
22136c67e9
|
|
@ -19,55 +19,74 @@
|
|||
|
||||
package com.puppycrawl.tools.checkstyle.checks.imports;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Check;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.FullIdent;
|
||||
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
|
||||
import com.puppycrawl.tools.checkstyle.checks.AbstractOptionCheck;
|
||||
|
||||
/**
|
||||
* Class to check the ordering/grouping of imports. Ensures that
|
||||
* groups of imports come in a specific order (e.g., java. comes
|
||||
* first, javax. comes second, then everything else) and imports
|
||||
* within each group are in lexicographic order. Static imports must
|
||||
* be at the end of a group and in lexicographic order amongst themselves.
|
||||
* Class to check the ordering/grouping of imports. Features are:
|
||||
* <ul>
|
||||
* <li>groups imports: ensures that groups of imports come in a specific order
|
||||
* (e.g., java. comes first, javax. comes second, then everything else)</li>
|
||||
* <li>adds a separation between groups : ensures that a blank line sit between
|
||||
* each group</li>
|
||||
* <li>sorts imports inside each group: ensures that imports within each group
|
||||
* are in lexicographic order</li>
|
||||
* <li>sorts according to case: ensures that the comparison between import is
|
||||
* case sensitive</li>
|
||||
* <li>groups static imports: ensures that static imports are at the top (or the
|
||||
* bottom) of all the imports, or above (or under) each group, or are treated
|
||||
* like non static imports (@see {@link ImportOrderOption}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Example:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <module name="ImportOrder">
|
||||
* <property name="groups" value="java,javax"/>
|
||||
* <property name="ordered" value="true"/>
|
||||
* <property name="caseSensitive" value="false"/>
|
||||
* </module>
|
||||
* <module name="ImportOrder">
|
||||
* <property name="groups" value="java,javax"/>
|
||||
* <property name="ordered" value="true"/>
|
||||
* <property name="caseSensitive" value="false"/>
|
||||
* <property name="option" value="above"/>
|
||||
* </module>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* There is always an additional, implied "everything else" package
|
||||
* group. If no "groups" property is supplied, all imports belong in
|
||||
* this "everything else" group. </p>
|
||||
*
|
||||
* <p>
|
||||
* ordered defaults to true.
|
||||
* group. If no "groups" property is supplied, all imports belong in
|
||||
* this "everything else" group.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* separated defaults to false.
|
||||
* Defaults:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>import groups: none</li>
|
||||
* <li>separation: false</li>
|
||||
* <li>ordered: true</li>
|
||||
* <li>case sensitive: true</li>
|
||||
* <li>static import: under</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Compatible with Java 1.5 source.
|
||||
* </p>
|
||||
*
|
||||
* @author Bill Schneider
|
||||
* @author o_sukhodolsky
|
||||
* @author David DIDIER
|
||||
*/
|
||||
public class ImportOrderCheck extends Check
|
||||
public class ImportOrderCheck
|
||||
extends AbstractOptionCheck<ImportOrderOption>
|
||||
{
|
||||
/** List of import groups specified by the user. */
|
||||
private String[] mGroups = new String[0];
|
||||
|
||||
/** Require imports in group. */
|
||||
private boolean mOrdered = true;
|
||||
|
||||
/** Require imports in group be separated. */
|
||||
private boolean mSeparated;
|
||||
/** Require imports in group. */
|
||||
private boolean mOrdered = true;
|
||||
/** Should comparison be case sensitive. */
|
||||
private boolean mCaseSensitive = true;
|
||||
|
||||
|
|
@ -83,21 +102,23 @@ public class ImportOrderCheck extends Check
|
|||
private boolean mBeforeFirstImport;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Groups static imports under each group.
|
||||
*/
|
||||
public ImportOrderCheck()
|
||||
{
|
||||
super(ImportOrderOption.UNDER, ImportOrderOption.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the list of package groups and the order they should
|
||||
* occur in the file.
|
||||
* Sets the list of package groups and the order they should occur in the
|
||||
* file.
|
||||
*
|
||||
* @param aGroups a comma-separated list of package names/prefixes
|
||||
* @param aGroups
|
||||
* a comma-separated list of package names/prefixes.
|
||||
*/
|
||||
public void setGroups(String[] aGroups)
|
||||
{
|
||||
mGroups = new String[ aGroups.length ];
|
||||
mGroups = new String[aGroups.length];
|
||||
|
||||
for (int i = 0; i < aGroups.length; i++) {
|
||||
String pkg = aGroups[i];
|
||||
|
|
@ -111,11 +132,12 @@ public class ImportOrderCheck extends Check
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not imports should be ordered within any one
|
||||
* group of imports.
|
||||
* Sets whether or not imports should be ordered within any one group of
|
||||
* imports.
|
||||
*
|
||||
* @param aOrdered whether lexicographic ordering of imports within
|
||||
* a group required or not.
|
||||
* @param aOrdered
|
||||
* whether lexicographic ordering of imports within a group
|
||||
* required or not.
|
||||
*/
|
||||
public void setOrdered(boolean aOrdered)
|
||||
{
|
||||
|
|
@ -123,10 +145,11 @@ public class ImportOrderCheck extends Check
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not groups of imports must be separated from
|
||||
* one another by at least one blank line.
|
||||
* Sets whether or not groups of imports must be separated from one another
|
||||
* by at least one blank line.
|
||||
*
|
||||
* @param aSeparated whehter groups should be separated by blank line.
|
||||
* @param aSeparated
|
||||
* whether groups should be separated by oen blank line.
|
||||
*/
|
||||
public void setSeparated(boolean aSeparated)
|
||||
{
|
||||
|
|
@ -134,10 +157,10 @@ public class ImportOrderCheck extends Check
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets whether string comparision should be case sensitive
|
||||
* or not.
|
||||
* @param aCaseSensitive whether string comparision should be
|
||||
* case sensitive.
|
||||
* Sets whether string comparison should be case sensitive or not.
|
||||
*
|
||||
* @param aCaseSensitive
|
||||
* whether string comparison should be case sensitive.
|
||||
*/
|
||||
public void setCaseSensitive(boolean aCaseSensitive)
|
||||
{
|
||||
|
|
@ -147,7 +170,7 @@ public class ImportOrderCheck extends Check
|
|||
@Override
|
||||
public int[] getDefaultTokens()
|
||||
{
|
||||
return new int[]{TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT};
|
||||
return new int[] {TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -156,8 +179,156 @@ public class ImportOrderCheck extends Check
|
|||
return getDefaultTokens();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTree(DetailAST aRootAST)
|
||||
{
|
||||
mLastGroup = Integer.MIN_VALUE;
|
||||
mLastImportLine = Integer.MIN_VALUE;
|
||||
mLastImport = "";
|
||||
mLastImportStatic = false;
|
||||
mBeforeFirstImport = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitToken(DetailAST aAST)
|
||||
{
|
||||
final FullIdent ident;
|
||||
final boolean isStatic;
|
||||
|
||||
if (aAST.getType() == TokenTypes.IMPORT) {
|
||||
ident = FullIdent.createFullIdentBelow(aAST);
|
||||
isStatic = false;
|
||||
}
|
||||
else {
|
||||
ident = FullIdent.createFullIdent((DetailAST) aAST.getFirstChild()
|
||||
.getNextSibling());
|
||||
isStatic = true;
|
||||
}
|
||||
|
||||
switch (getAbstractOption()) {
|
||||
case TOP:
|
||||
if (!isStatic && mLastImportStatic) {
|
||||
mLastGroup = Integer.MIN_VALUE;
|
||||
mLastImport = "";
|
||||
}
|
||||
// no break;
|
||||
|
||||
case ABOVE:
|
||||
// previous non-static but current is static
|
||||
doVisitToken(ident, isStatic, (!mLastImportStatic && isStatic));
|
||||
break;
|
||||
|
||||
case INFLOW:
|
||||
// previous argument is useless here
|
||||
doVisitToken(ident, isStatic, true);
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
if (isStatic && !mLastImportStatic) {
|
||||
mLastGroup = Integer.MIN_VALUE;
|
||||
mLastImport = "";
|
||||
}
|
||||
// no break;
|
||||
|
||||
case UNDER:
|
||||
// previous static but current is non-static
|
||||
doVisitToken(ident, isStatic, (mLastImportStatic && !isStatic));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mLastImportLine = aAST.findFirstToken(TokenTypes.SEMI).getLineNo();
|
||||
mLastImportStatic = isStatic;
|
||||
mBeforeFirstImport = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param aName import name to check.
|
||||
* Shares processing...
|
||||
*
|
||||
* @param aIdent the import to process.
|
||||
* @param aIsStatic whether the token is static or not.
|
||||
* @param aPrevious previous non-static but current is static (above), or
|
||||
* previous static but current is non-static (under).
|
||||
*/
|
||||
private void doVisitToken(FullIdent aIdent, boolean aIsStatic,
|
||||
boolean aPrevious)
|
||||
{
|
||||
if (aIdent != null) {
|
||||
final String name = aIdent.getText();
|
||||
final int groupIdx = getGroupNumber(name);
|
||||
final int line = aIdent.getLineNo();
|
||||
|
||||
if (groupIdx > mLastGroup) {
|
||||
if (!mBeforeFirstImport && mSeparated) {
|
||||
// This check should be made more robust to handle
|
||||
// comments and imports that span more than one line.
|
||||
if ((line - mLastImportLine) < 2) {
|
||||
log(line, "import.separation", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (groupIdx == mLastGroup) {
|
||||
doVisitTokenInSameGroup(aIdent, aIsStatic, aPrevious, name,
|
||||
line);
|
||||
}
|
||||
else {
|
||||
log(line, "import.ordering", name);
|
||||
}
|
||||
|
||||
mLastGroup = groupIdx;
|
||||
mLastImport = name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shares processing...
|
||||
*
|
||||
* @param aIdent the import to process.
|
||||
* @param aIsStatic whether the token is static or not.
|
||||
* @param aPrevious previous non-static but current is static (above), or
|
||||
* previous static but current is non-static (under).
|
||||
* @param aName the name of the current import.
|
||||
* @param aLine the line of the current import.
|
||||
*/
|
||||
private void doVisitTokenInSameGroup(FullIdent aIdent, boolean aIsStatic,
|
||||
boolean aPrevious, String aName, int aLine)
|
||||
{
|
||||
if (!mOrdered) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getAbstractOption().equals(ImportOrderOption.INFLOW)) {
|
||||
// out of lexicographic order
|
||||
if (compare(mLastImport, aName, mCaseSensitive) >= 0) {
|
||||
log(aLine, "import.ordering", aName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final boolean shouldFireError =
|
||||
// current and previous static or current and
|
||||
// previous non-static
|
||||
(!(mLastImportStatic ^ aIsStatic)
|
||||
&&
|
||||
// and out of lexicographic order
|
||||
(compare(mLastImport, aName, mCaseSensitive) >= 0))
|
||||
||
|
||||
// previous non-static but current is static (above)
|
||||
// or
|
||||
// previous static but current is non-static (under)
|
||||
aPrevious;
|
||||
|
||||
if (shouldFireError) {
|
||||
log(aLine, "import.ordering", aName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds out what group the specified import belongs to.
|
||||
*
|
||||
* @param aName the import name to find.
|
||||
* @return group number for given import name.
|
||||
*/
|
||||
private int getGroupNumber(String aName)
|
||||
|
|
@ -175,86 +346,27 @@ public class ImportOrderCheck extends Check
|
|||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTree(DetailAST aRootAST)
|
||||
/**
|
||||
* Compares two strings.
|
||||
*
|
||||
* @param aString1
|
||||
* the first string.
|
||||
* @param aString2
|
||||
* the second string.
|
||||
* @param aCaseSensitive
|
||||
* whether the comparison is case sensitive.
|
||||
* @return the value <code>0</code> if string1 is equal to string2; a value
|
||||
* less than <code>0</code> if string1 is lexicographically less
|
||||
* than the string2; and a value greater than <code>0</code> if
|
||||
* string1 is lexicographically greater than string2.
|
||||
*/
|
||||
private int compare(String aString1, String aString2,
|
||||
boolean aCaseSensitive)
|
||||
{
|
||||
mLastGroup = Integer.MIN_VALUE;
|
||||
mLastImportLine = Integer.MIN_VALUE;
|
||||
mLastImport = "";
|
||||
mLastImportStatic = false;
|
||||
mBeforeFirstImport = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitToken(DetailAST aAST)
|
||||
{
|
||||
final FullIdent ident;
|
||||
boolean isStatic;
|
||||
if (aAST.getType() == TokenTypes.IMPORT) {
|
||||
ident = FullIdent.createFullIdentBelow(aAST);
|
||||
isStatic = false;
|
||||
}
|
||||
else {
|
||||
ident = FullIdent.createFullIdent(
|
||||
(DetailAST) aAST.getFirstChild().getNextSibling());
|
||||
isStatic = true;
|
||||
if (aCaseSensitive) {
|
||||
return aString1.compareTo(aString2);
|
||||
}
|
||||
|
||||
if (ident != null) {
|
||||
final String name = ident.getText();
|
||||
final int groupIdx = getGroupNumber(name);
|
||||
final int line = ident.getLineNo();
|
||||
|
||||
if (groupIdx > mLastGroup) {
|
||||
if (!mBeforeFirstImport && mSeparated) {
|
||||
// This check should be made more robust to handle
|
||||
// comments and imports that span more than one line.
|
||||
if (line - mLastImportLine < 2) {
|
||||
log(line, "import.separation", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (groupIdx == mLastGroup) {
|
||||
if (mOrdered) {
|
||||
boolean shouldFireError = false;
|
||||
if (mCaseSensitive) {
|
||||
shouldFireError =
|
||||
//current and previous static or current and
|
||||
//previous non-static
|
||||
(!(mLastImportStatic ^ isStatic)
|
||||
&&
|
||||
//and out of lexicographic order
|
||||
(mLastImport.compareTo(name) >= 0))
|
||||
||
|
||||
//previous static but current is non-static
|
||||
(mLastImportStatic && !isStatic);
|
||||
}
|
||||
else {
|
||||
shouldFireError =
|
||||
//current and previous static or current and
|
||||
//previous non-static
|
||||
(!(mLastImportStatic ^ isStatic)
|
||||
&&
|
||||
//and out of lexicographic order
|
||||
(mLastImport.compareToIgnoreCase(name) >= 0))
|
||||
||
|
||||
//previous static but current is non-static
|
||||
(mLastImportStatic && !isStatic);
|
||||
}
|
||||
if (shouldFireError) {
|
||||
log(line, "import.ordering", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log(line, "import.ordering", name);
|
||||
}
|
||||
|
||||
mLastGroup = groupIdx;
|
||||
mLastImport = name;
|
||||
mLastImportLine = aAST.findFirstToken(TokenTypes.SEMI).getLineNo();
|
||||
mLastImportStatic = isStatic;
|
||||
mBeforeFirstImport = false;
|
||||
}
|
||||
return aString1.compareToIgnoreCase(aString2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2008 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.imports;
|
||||
|
||||
/**
|
||||
* Represents the policy for checking import order statements.
|
||||
* @see com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck
|
||||
* @author David DIDIER
|
||||
*/
|
||||
public enum ImportOrderOption
|
||||
{
|
||||
/**
|
||||
* Represents the policy that static imports are all at the top.
|
||||
* For example:
|
||||
*
|
||||
* <pre>
|
||||
import static java.awt.Button.ABORT;
|
||||
import static java.io.File.createTempFile;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.event.ActionEvent;
|
||||
* </pre>
|
||||
*/
|
||||
TOP,
|
||||
|
||||
/**
|
||||
* Represents the policy that static imports are above the local group.
|
||||
* For example:
|
||||
*
|
||||
* <pre>
|
||||
import static java.awt.Button.A;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
import java.awt.Dialog;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import static java.io.File.createTempFile;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
* </pre>
|
||||
*/
|
||||
ABOVE,
|
||||
|
||||
/**
|
||||
* Represents the policy that static imports are processed like non static
|
||||
* imports. For example:
|
||||
*
|
||||
* <pre>
|
||||
import java.awt.Button;
|
||||
import static java.awt.Button.ABORT;
|
||||
import java.awt.Dialog;
|
||||
|
||||
import static javax.swing.WindowConstants.HIDE_ON_CLOSE;
|
||||
import javax.swing.JComponent;
|
||||
* </pre>
|
||||
*/
|
||||
INFLOW,
|
||||
|
||||
/**
|
||||
* Represents the policy that static imports are under the local group.
|
||||
* For example:
|
||||
*
|
||||
* <pre>
|
||||
import java.awt.Dialog;
|
||||
import javax.swing.JComponent;
|
||||
import static java.awt.Button.A;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import static java.io.File.createTempFile;
|
||||
* </pre>
|
||||
*/
|
||||
UNDER,
|
||||
|
||||
/**
|
||||
* Represents the policy that static imports are all at the bottom.
|
||||
* For example:
|
||||
*
|
||||
* <pre>
|
||||
import java.awt.Button;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import static java.awt.Button.ABORT;
|
||||
import static java.io.File.createTempFile;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
* </pre>
|
||||
*/
|
||||
BOTTOM;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.puppycrawl.tools.checkstyle.imports;
|
||||
|
||||
import static java.awt.Button.ABORT;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
import static java.awt.Button.ABORT;
|
||||
import java.awt.Button;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import java.io.File;
|
||||
import static java.io.File.createTempFile;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
public class InputImportOrder_Above {
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.puppycrawl.tools.checkstyle.imports;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import static java.io.File.*;
|
||||
import java.io.File;
|
||||
|
||||
import static java.io.File.createTempFile;
|
||||
import static java.awt.Button.ABORT;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
public class InputImportOrder_Bottom {
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package com.puppycrawl.tools.checkstyle.imports;
|
||||
|
||||
import java.awt.Button;
|
||||
import static java.awt.Button.ABORT;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import static javax.swing.WindowConstants.HIDE_ON_CLOSE;
|
||||
import static javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import static java.io.File.createTempFile;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
public class InputImportOrder_InFlow {
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.puppycrawl.tools.checkstyle.imports;
|
||||
|
||||
import static java.io.File.createTempFile;
|
||||
import static java.awt.Button.ABORT;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTable;
|
||||
|
||||
import static java.io.File.*;
|
||||
import java.io.File;
|
||||
import java.io.Reader;
|
||||
|
||||
public class InputImportOrder_Top {
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.puppycrawl.tools.checkstyle.imports;
|
||||
|
||||
import java.awt.Button;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTable;
|
||||
import static java.awt.Button.ABORT;
|
||||
import static javax.swing.WindowConstants.*;
|
||||
import static java.awt.Button.ABORT;
|
||||
|
||||
import static java.io.File.createTempFile;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
|
||||
public class InputImportOrder_Under {
|
||||
}
|
||||
|
|
@ -62,4 +62,83 @@ public class ImportOrderCheckTest extends BaseCheckTestSupport
|
|||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrderCaseInsensitive.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTop() throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ImportOrderCheck.class);
|
||||
checkConfig.addAttribute("option", "top");
|
||||
final String[] expected = {
|
||||
"4: Wrong order for 'java.awt.Button.ABORT' import.",
|
||||
"18: Wrong order for 'java.io.File.*' import."
|
||||
};
|
||||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrder_Top.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbove() throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ImportOrderCheck.class);
|
||||
checkConfig.addAttribute("option", "above");
|
||||
final String[] expected = {
|
||||
"5: Wrong order for 'java.awt.Button.ABORT' import.",
|
||||
"8: Wrong order for 'java.awt.Dialog' import.",
|
||||
"13: Wrong order for 'java.io.File' import.",
|
||||
"14: Wrong order for 'java.io.File.createTempFile' import."
|
||||
};
|
||||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrder_Above.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInFlow() throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ImportOrderCheck.class);
|
||||
checkConfig.addAttribute("option", "inflow");
|
||||
final String[] expected = {
|
||||
"6: Wrong order for 'java.awt.Dialog' import.",
|
||||
"11: Wrong order for 'javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE' import.",
|
||||
"12: Wrong order for 'javax.swing.WindowConstants.*' import.",
|
||||
"13: Wrong order for 'javax.swing.JTable' import.",
|
||||
"15: Wrong order for 'java.io.File.createTempFile' import.",
|
||||
"16: Wrong order for 'java.io.File' import."
|
||||
};
|
||||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrder_InFlow.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnder() throws Exception
|
||||
{
|
||||
// is default (testDefault)
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ImportOrderCheck.class);
|
||||
checkConfig.addAttribute("option", "under");
|
||||
final String[] expected = {
|
||||
"5: Wrong order for 'java.awt.Dialog' import.",
|
||||
"11: Wrong order for 'java.awt.Button.ABORT' import.",
|
||||
"14: Wrong order for 'java.io.File' import."
|
||||
};
|
||||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrder_Under.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBottom() throws Exception
|
||||
{
|
||||
final DefaultConfiguration checkConfig =
|
||||
createCheckConfig(ImportOrderCheck.class);
|
||||
checkConfig.addAttribute("option", "bottom");
|
||||
final String[] expected = {
|
||||
"15: Wrong order for 'java.io.File' import.",
|
||||
"18: Wrong order for 'java.awt.Button.ABORT' import.",
|
||||
"21: Wrong order for 'java.io.Reader' import."
|
||||
};
|
||||
|
||||
verify(checkConfig, getPath("imports" + File.separator + "InputImportOrder_Bottom.java"), expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,12 +323,21 @@ class FooBar {
|
|||
<section name="ImportOrder">
|
||||
<subsection name="Description">
|
||||
<p>
|
||||
Checks the ordering/grouping of imports. Ensures that groups of
|
||||
imports come in a specific order (e.g., java. comes first,
|
||||
javax. comes first, then everything else) and imports within each
|
||||
group are in lexicographic order.
|
||||
Static imports must be at the end of a group and in lexicographic
|
||||
order amongst themselves.
|
||||
Checks the ordering/grouping of imports. Features are:
|
||||
<ul>
|
||||
<li>groups imports: ensures that groups of imports come in a
|
||||
specific order (e.g., java. comes first, javax. comes second,
|
||||
then everything else)</li>
|
||||
<li>adds a separation between groups : ensures that a blank
|
||||
line sit between each group</li>
|
||||
<li>sorts imports inside each group: ensures that imports
|
||||
within each group are in lexicographic order</li>
|
||||
<li>sorts according to case: ensures that the comparison
|
||||
between imports is case sensitive</li>
|
||||
<li>groups static imports: ensures the relative order between
|
||||
regular imports and static imports (see
|
||||
<a href="property_types.html#importOrder">import orders</a>)</li>
|
||||
</ul>
|
||||
</p>
|
||||
</subsection>
|
||||
|
||||
|
|
@ -340,6 +349,12 @@ class FooBar {
|
|||
<th>type</th>
|
||||
<th>default value</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>option</td>
|
||||
<td>policy on the relative order between regular imports and static imports</td>
|
||||
<td><a href="property_types.html#importOrder">import order</a></td>
|
||||
<td><span class="default">under</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>groups</td>
|
||||
<td>
|
||||
|
|
@ -375,10 +390,13 @@ class FooBar {
|
|||
|
||||
<subsection name="Example">
|
||||
<p>
|
||||
To configure the check so that it requires "java" packages
|
||||
first, than "javax" and than all other imports, imports
|
||||
will be sorted in the groups and groups are separated by, at least,
|
||||
on blank line:
|
||||
To configure the check so that it requires that:
|
||||
<ul>
|
||||
<li>"java" packages first, then "javax" and then all other imports</li>
|
||||
<li>imports will be sorted in the groups</li>
|
||||
<li>groups are separated by, at least, on blank line</li>
|
||||
<li>static imports are above each local groups</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<source>
|
||||
|
|
@ -386,6 +404,7 @@ class FooBar {
|
|||
<property name="groups" value="java,javax"/>
|
||||
<property name="ordered" value="true"/>
|
||||
<property name="separated" value="true"/>
|
||||
<property name="option" value="above"/>
|
||||
</module>
|
||||
</source>
|
||||
</subsection>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
This property represents a regular expression. The string
|
||||
representation is parsed using <a
|
||||
href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/package-summary.html">java.util.regex
|
||||
package</a>.
|
||||
package</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
<td>Option</td>
|
||||
<td>Definition</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><span class="code">eol</span></td>
|
||||
<td>
|
||||
|
|
@ -330,5 +330,80 @@
|
|||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section name="importOrder">
|
||||
<p>
|
||||
This property represents the policy for checking imports order.
|
||||
The following table describes the valid options:
|
||||
</p>
|
||||
|
||||
<table summary="import order options">
|
||||
<tr>
|
||||
<td>Option</td>
|
||||
<td>Definition</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class="code">top</span></td>
|
||||
<td>All static imports are at the top. For example:
|
||||
<pre>
|
||||
import static a.b.C.*;
|
||||
import static x.y.Z.*;
|
||||
|
||||
import a.b.D;
|
||||
import x.y.Z;</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class="code">above</span></td>
|
||||
<td>All static imports are above the local group.. For example:
|
||||
<pre>
|
||||
import static a.b.C.*;
|
||||
import a.b.D;
|
||||
|
||||
import static x.y.Z.*;
|
||||
import x.y.Z;</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class="code">inflow</span></td>
|
||||
<td>All static imports are processed like non static
|
||||
imports. For example:
|
||||
<pre>
|
||||
import static a.b.C.*;
|
||||
import a.b.D;
|
||||
|
||||
import x.y.Z;
|
||||
import static x.y.Z.*;</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class="code">under</span></td>
|
||||
<td>All static imports are under the local group. For example:
|
||||
<pre>
|
||||
import a.b.D;
|
||||
import static a.b.C.*;
|
||||
|
||||
import x.y.Z;
|
||||
import static x.y.Z.*;</pre>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><span class="code">bottom</span></td>
|
||||
<td>All static imports are at the bottom. For example:
|
||||
<pre>
|
||||
import a.b.D;
|
||||
import x.y.Z;
|
||||
|
||||
import static a.b.C.*;
|
||||
import static x.y.Z.*;</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</body>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@
|
|||
for enforcing the maximum number of outer types per file. Inspired
|
||||
by patch #1145023 from Alexander Jesse.
|
||||
</li>
|
||||
<li>
|
||||
Add new options to the <a
|
||||
href="config_sizes.html#ImportOrderCheck">ImportOrderCheck</a>
|
||||
to make it more flexible. Thanks to David Didier for providing
|
||||
patch #1854213.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Fixed Bugs:</p>
|
||||
|
|
|
|||
Loading…
Reference in New Issue