public class ImportOrderCheck extends AbstractCheck
Checks the ordering/grouping of imports. Features are:
option - specify policy on the relative order between type imports and static
imports.
Type is com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderOption.
Default value is under.
groups - specify list of type import groups (every group identified
either by a common prefix string, or by a regular expression enclosed in forward slashes
(e.g. /regexp/). All type imports, which does not match any group, falls into an
additional group, located at the end.
Thus, the empty list of type groups (the default value) means one group for all type imports.
Type is java.util.regex.Pattern[].
Default value is "".
ordered - control whether type imports within each group should be
sorted.
It doesn't affect sorting for static imports.
Type is boolean.
Default value is true.
separated - control whether type import groups should be separated
by, at least, one blank line or comment and aren't separated internally.
It doesn't affect separations for static imports.
Type is boolean.
Default value is false.
separatedStaticGroups - control whether static import groups should
be separated by, at least, one blank line or comment and aren't separated internally.
This property has effect only when the property option is set to top
or bottom and when property staticGroups is enabled.
Type is boolean.
Default value is false.
caseSensitive - control whether string comparison should be case
sensitive or not. Case sensitive sorting is in
ASCII sort order.
It affects both type imports and static imports.
Type is boolean.
Default value is true.
staticGroups - specify list of static import groups (every group
identified either by a common prefix string, or by a regular expression enclosed in forward
slashes (e.g. /regexp/). All static imports, which does not match any group, falls into
an additional group, located at the end. Thus, the empty list of static groups (the default
value) means one group for all static imports. This property has effect only when the property
option is set to top or bottom.
Type is java.util.regex.Pattern[].
Default value is "".
sortStaticImportsAlphabetically - control whether
static imports located at top or bottom are sorted within the group.
Type is boolean.
Default value is false.
useContainerOrderingForStatic - control whether to use container
ordering (Eclipse IDE term) for static imports or not.
Type is boolean.
Default value is false.
tokens - tokens to check
Type is java.lang.String[].
Validation type is tokenSet.
Default value is:
STATIC_IMPORT.
To configure the check:
<module name="ImportOrder"/>
Example:
import java.io.IOException;
import java.net.URL;
import java.io.IOException; // violation, extra separation before import
// and wrong order, comes before 'java.net.URL'.
import javax.net.ssl.TrustManager; // violation, extra separation due to above comment
import javax.swing.JComponent;
import org.apache.http.conn.ClientConnectionManager; // OK
import java.util.Set; // violation, wrong order, 'java' should not come after 'org' imports
import com.neurologic.http.HttpClient; // violation, wrong order, 'com' imports comes at top
import com.neurologic.http.impl.ApacheHttpClient; // OK
public class SomeClass { }
To configure the check so that it matches default Eclipse formatter configuration (tested on Kepler and Luna releases):
Notes:
<module name="ImportOrder"> <property name="groups" value="/^java\./,javax,org"/> <property name="ordered" value="true"/> <property name="separated" value="true"/> <property name="option" value="above"/> <property name="sortStaticImportsAlphabetically" value="true"/> </module>
Example:
import static java.lang.System.out;
import static java.lang.Math; // violation, alphabetical case sensitive ASCII order, 'M' < 'S'
import java.io.IOException;
import java.net.URL; // violation, extra separation before import
import java.security.KeyManagementException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager; // violation, groups should not be separated internally
import org.apache.http.conn.ClientConnectionManager;
public class SomeClass { }
To configure the check so that it matches default Eclipse formatter configuration (tested on Mars release):
<module name="ImportOrder"> <property name="groups" value="/^java\./,javax,org,com"/> <property name="ordered" value="true"/> <property name="separated" value="true"/> <property name="option" value="above"/> <property name="sortStaticImportsAlphabetically" value="true"/> </module>
Example:
import static java.io.File.createTempFile;
import static java.lang.Math.abs; // OK, alphabetical case sensitive ASCII order, 'i' < 'l'
import java.lang.Math.sqrt; // OK, follows property 'Option' value 'above'
import java.io.File; // violation, alphabetical case sensitive ASCII order, 'i' < 'l'
import java.io.IOException; // violation, extra separation in 'java' import group
import org.albedo.*;
import static javax.WindowConstants.*; // violation, wrong order, 'javax' comes before 'org'
import javax.swing.JComponent;
import org.apache.http.ClientConnectionManager; // violation, must separate from previous import
import org.linux.apache.server.SoapServer; // OK
import com.neurologic.http.HttpClient; // OK
import com.neurologic.http.impl.ApacheHttpClient; // OK
public class SomeClass { }
To configure the check so that it matches default IntelliJ IDEA formatter configuration (tested on v2018.2):
Note: a suppression xpath single filter is needed because IDEA has no blank line between "javax" and "java". ImportOrder has a limitation by design to enforce an empty line between groups ("java", "javax"). There is no flexibility to enforce empty lines between some groups and no empty lines between other groups.
Note: "separated" option is disabled because IDEA default has blank line between "java" and static imports, and no blank line between "javax" and "java".
<module name="ImportOrder"> <property name="groups" value="*,javax,java"/> <property name="ordered" value="true"/> <property name="separated" value="false"/> <property name="option" value="bottom"/> <property name="sortStaticImportsAlphabetically" value="true"/> </module> <module name="SuppressionXpathSingleFilter"> <property name="checks" value="ImportOrder"/> <property name="message" value="^'java\..*'.*"/> </module>
Example:
import com.neurologic.http.impl.ApacheHttpClient; // OK
import static java.awt.Button.A;
import javax.swing.JComponent; // violation, wrong order, caused by above static import
// all static imports comes at bottom
import java.net.URL; // violation, extra separation in import group
import java.security.KeyManagementException;
import javax.swing.JComponent; // violation, wrong order, 'javax' should be above 'java' imports
import com.neurologic.http.HttpClient; // violation, wrong order, 'com' imports should be at top
public class TestClass { }
To configure the check so that it matches default NetBeans formatter configuration (tested on v8):
<module name="ImportOrder"> <property name="option" value="inflow"/> </module>
Example:
import static java.io.File.createTempFile;
import java.lang.Math.sqrt;
import javax.swing.JComponent; // violation, extra separation in import group
import static javax.windowConstants.*; // OK
// all static imports are processed like non static imports.
public class SomeClass { }
Group descriptions enclosed in slashes are interpreted as regular expressions. If multiple groups match, the one matching a longer substring of the imported name will take precedence, with ties broken first in favor of earlier matches and finally in favor of the first matching group.
There is always a wildcard group to which everything not in a named group belongs.
If an import does not match a named group, the group belongs to this wildcard group.
The wildcard group position can be specified using the * character.
Check also has on option making it more flexible: sortStaticImportsAlphabetically - sets whether static imports grouped by top or bottom option should be sorted alphabetically or not, default value is false. It is applied to static imports grouped with top or bottom options. This option is helping in reconciling of this Check and other tools like Eclipse's Organize Imports feature.
To configure the Check allows static imports grouped to the top being sorted alphabetically:
<module name="ImportOrder"> <property name="sortStaticImportsAlphabetically" value="true"/> <property name="option" value="top"/> </module>
import static java.lang.Math.PI;
import static java.lang.Math.abs; // OK, alphabetical case sensitive ASCII order, 'P' < 'a'
import static org.abego.treelayout.Configuration.AlignmentInLevel; // OK, alphabetical order
import java.util.Set; // violation, extra separation in import group
import static java.lang.Math.abs; // violation, wrong order, all static imports comes at 'top'
import org.abego.*;
public class SomeClass { }
To configure the Check with groups of static imports:
<module name="ImportOrder"> <property name="staticGroups" value="org,java"/> <property name="sortStaticImportsAlphabetically" value="true"/> <property name="option" value="top"/> </module>
import static org.abego.treelayout.Configuration.AlignmentInLevel; // Group 1
import static java.lang.Math.abs; // Group 2
import static java.lang.String.format; // Group 2
import static com.google.common.primitives.Doubles.BYTES; // Group "everything else"
public class SomeClass { }
The following example shows the idea of 'useContainerOrderingForStatic' option that is useful for Eclipse IDE users to match ordering validation. This is how the import comparison works for static imports: we first compare the container of the static import, container is the type enclosing the static element being imported. When the result of the comparison is 0 (containers are equal), we compare the fully qualified import names. For e.g. this is what is considered to be container names for the given example: import static HttpConstants.COLON => HttpConstants import static HttpHeaders.addHeader => HttpHeaders import static HttpHeaders.setHeader => HttpHeaders import static HttpHeaders.Names.DATE => HttpHeaders.Names According to this logic, HttpHeaders.Names should come after HttpHeaders.
Example for useContainerOrderingForStatic=true
<module name="ImportOrder"> <property name="useContainerOrderingForStatic" value="true"/> <property name="ordered" value="true"/> <property name="option" value="top"/> <property name="caseSensitive" value="false"/> <property name="sortStaticImportsAlphabetically" value="true"/> </module>
import static io.netty.handler.codec.http.HttpConstants.COLON;
import static io.netty.handler.codec.http.HttpHeaders.addHeader;
import static io.netty.handler.codec.http.HttpHeaders.setHeader;
import static io.netty.handler.codec.http.HttpHeaders.Names.DATE;
public class InputEclipseStaticImportsOrder { }
Example for useContainerOrderingForStatic=false
<module name="ImportOrder"> <property name="useContainerOrderingForStatic" value="false"/> <property name="ordered" value="true"/> <property name="option" value="top"/> <property name="caseSensitive" value="false"/> <property name="sortStaticImportsAlphabetically" value="true"/> </module>
import static io.netty.handler.codec.http.HttpConstants.COLON;
import static io.netty.handler.codec.http.HttpHeaders.addHeader;
import static io.netty.handler.codec.http.HttpHeaders.setHeader;
import static io.netty.handler.codec.http.HttpHeaders.Names.DATE; // violation
public class InputEclipseStaticImportsOrder { }
To configure the check to enforce static import group separation
Example for separatedStaticGroups=true
<module name="ImportOrder"> <property name="staticGroups" value="*,java,javax,org"/> <property name="option" value="top"/> <property name="separatedStaticGroups" value="true"/> </module>
import static java.lang.Math.PI;
import static java.io.File.createTempFile;
import static javax.swing.JComponent; // violation, should be separated from previous imports
import static javax.WindowConstants.*; // OK
import java.net.URL;
public class SomeClass { }
To configure the Check with groups of static imports when staticGroups=""
represents all imports as everything else group:
<module name="ImportOrder"> <property name="staticGroups" value=""/> <property name="option" value="top"/> </module>
import static java.io.File.listRoots; // OK
import static javax.swing.WindowConstants.*; // OK
import static java.io.File.createTempFile; // OK
import static com.puppycrawl.tools.checkstyle; // OK
public class SomeClass { }
To configure the Check with groups of static imports when
staticGroups="java, javax" represents three groups i.e java*, javax*
and * (everything else). In below example the static imports com...
should be in last group:
<module name="ImportOrder"> <property name="staticGroups" value="java, javax"/> <property name="option" value="top"/> </module>
import static java.io.File.listRoots; // OK
import static javax.swing.WindowConstants.*; // OK
import static java.io.File.createTempFile; // violation should be before javax
import static com.puppycrawl.tools.checkstyle; // OK
public class SomeClass { }
Parent is com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
import.groups.separated.internally
import.ordering
import.separation
AutomaticBean.OutputStreamOptions| Modifier and Type | Field and Description |
|---|---|
private boolean |
beforeFirstImport
Whether there was any imports.
|
private boolean |
caseSensitive
Control whether string comparison should be case sensitive or not.
|
private static java.util.regex.Pattern[] |
EMPTY_PATTERN_ARRAY
Empty array of pattern type needed to initialize check.
|
private java.util.regex.Pattern[] |
groups
Specify list of type import groups (every group identified either by a common prefix
string, or by a regular expression enclosed in forward slashes (e.g.
|
private int |
lastGroup
Last imported group.
|
private java.lang.String |
lastImport
Name of last import.
|
private int |
lastImportLine
Line number of last import.
|
private boolean |
lastImportStatic
If last import was static.
|
static java.lang.String |
MSG_ORDERING
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_SEPARATED_IN_GROUP
A key is pointing to the warning message text in "messages.properties"
file.
|
static java.lang.String |
MSG_SEPARATION
A key is pointing to the warning message text in "messages.properties"
file.
|
private ImportOrderOption |
option
Specify policy on the relative order between type imports and static imports.
|
private boolean |
ordered
Control whether type imports within each group should be sorted.
|
private boolean |
separated
Control whether type import groups should be separated by, at least, one blank
line or comment and aren't separated internally.
|
private boolean |
separatedStaticGroups
Control whether static import groups should be separated by, at least, one blank
line or comment and aren't separated internally.
|
private boolean |
sortStaticImportsAlphabetically
Control whether static imports located at top or bottom are
sorted within the group.
|
private java.util.regex.Pattern[] |
staticGroups
Specify list of static import groups (every group identified either by a common prefix
string, or by a regular expression enclosed in forward slashes (e.g.
|
private boolean |
staticImportsApart
Whether static and type import groups should be split apart.
|
private boolean |
useContainerOrderingForStatic
Control whether to use container ordering (Eclipse IDE term) for static imports
or not.
|
private static java.lang.String |
WILDCARD_GROUP_NAME
The special wildcard that catches all remaining groups.
|
| Constructor and Description |
|---|
ImportOrderCheck() |
| Modifier and Type | Method and Description |
|---|---|
void |
beginTree(DetailAST rootAST)
Called before the starting to process a tree.
|
private static int |
compare(java.lang.String string1,
java.lang.String string2,
boolean caseSensitive)
Compares two strings.
|
private static int |
compareContainerOrder(java.lang.String importName1,
java.lang.String importName2,
boolean caseSensitive)
Compares two import strings.
|
private static java.util.regex.Pattern[] |
compilePatterns(java.lang.String... packageGroups)
Compiles the list of package groups and the order they should occur in the file.
|
private void |
doVisitToken(FullIdent ident,
boolean isStatic,
boolean previous,
DetailAST ast)
Shares processing...
|
private void |
doVisitTokenInSameGroup(boolean isStatic,
boolean previous,
java.lang.String name,
DetailAST ast)
Shares processing...
|
int[] |
getAcceptableTokens()
The configurable token set.
|
int[] |
getDefaultTokens()
Returns the default token a check is interested in.
|
private int |
getGroupNumber(boolean isStatic,
java.lang.String name)
Finds out what group the specified import belongs to.
|
private static int |
getGroupNumber(java.util.regex.Pattern[] patterns,
java.lang.String name)
Finds out what group the specified import belongs to.
|
private static java.lang.String |
getImportContainer(java.lang.String qualifiedImportName)
Extracts import container name from fully qualified import name.
|
int[] |
getRequiredTokens()
The tokens that this check must be registered for.
|
private boolean |
isSeparatorBeforeImport(int line)
Checks whether there is any separator before current import.
|
private boolean |
isSeparatorInGroup(int groupIdx,
boolean isStatic,
int line)
Checks whether imports group separated internally.
|
private boolean |
isWrongOrder(java.lang.String name,
boolean isStatic)
Checks whether import name is in wrong order.
|
private boolean |
needSeparator(boolean isStatic)
Checks whether import groups should be separated.
|
void |
setCaseSensitive(boolean caseSensitive)
Setter to control whether string comparison should be case sensitive or not.
|
void |
setGroups(java.lang.String... packageGroups)
Setter to specify list of type import groups (every group identified either by a
common prefix string, or by a regular expression enclosed in forward slashes
(e.g.
|
void |
setOption(java.lang.String optionStr)
Setter to specify policy on the relative order between type imports and static imports.
|
void |
setOrdered(boolean ordered)
Setter to control whether type imports within each group should be sorted.
|
void |
setSeparated(boolean separated)
Setter to control whether type import groups should be separated by, at least,
one blank line or comment and aren't separated internally.
|
void |
setSeparatedStaticGroups(boolean separatedStaticGroups)
Setter to control whether static import groups should be separated by, at least,
one blank line or comment and aren't separated internally.
|
void |
setSortStaticImportsAlphabetically(boolean sortAlphabetically)
Setter to control whether static imports located at top or
bottom are sorted within the group.
|
void |
setStaticGroups(java.lang.String... packageGroups)
Setter to specify list of static import groups (every group identified either by a
common prefix string, or by a regular expression enclosed in forward slashes
(e.g.
|
void |
setUseContainerOrderingForStatic(boolean useContainerOrdering)
Setter to control whether to use container ordering (Eclipse IDE term) for static
imports or not.
|
void |
visitToken(DetailAST ast)
Called to process a token.
|
clearViolations, destroy, finishTree, getFileContents, getLine, getLineCodePoints, getLines, getTabWidth, getTokenNames, getViolations, init, isCommentNodesRequired, leaveToken, log, log, log, setFileContents, setTabWidth, setTokensfinishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeverityconfigure, contextualize, getConfiguration, setupChildpublic static final java.lang.String MSG_SEPARATION
public static final java.lang.String MSG_ORDERING
public static final java.lang.String MSG_SEPARATED_IN_GROUP
private static final java.lang.String WILDCARD_GROUP_NAME
private static final java.util.regex.Pattern[] EMPTY_PATTERN_ARRAY
private java.util.regex.Pattern[] groups
/regexp/).
All type imports, which does not match any group, falls into an additional group,
located at the end. Thus, the empty list of type groups (the default value) means one group
for all type imports.private java.util.regex.Pattern[] staticGroups
/regexp/).
All static imports, which does not match any group, falls into an additional group, located
at the end. Thus, the empty list of static groups (the default value) means one group for all
static imports. This property has effect only when the property option is set to
top or bottom.private boolean separated
private boolean separatedStaticGroups
option is set to top or bottom and when property
staticGroups is enabled.private boolean ordered
private boolean caseSensitive
private int lastGroup
private int lastImportLine
private java.lang.String lastImport
private boolean lastImportStatic
private boolean beforeFirstImport
private boolean staticImportsApart
option property is set to INFLOW, ABOVE or UNDER,
both the type and static imports use the properties groups and separated.
When the option property is set to TOP or BOTTOM, static imports
uses the properties staticGroups and separatedStaticGroups.private boolean sortStaticImportsAlphabetically
private boolean useContainerOrderingForStatic
private ImportOrderOption option
public ImportOrderCheck()
public void setOption(java.lang.String optionStr)
optionStr - string to decode option fromjava.lang.IllegalArgumentException - if unable to decodepublic void setGroups(java.lang.String... packageGroups)
/regexp/). All type imports, which does not match any group, falls into an
additional group, located at the end. Thus, the empty list of type groups (the default value)
means one group for all type imports.packageGroups - a comma-separated list of package names/prefixes.public void setStaticGroups(java.lang.String... packageGroups)
/regexp/). All static imports, which does not match any group, falls into an
additional group, located at the end. Thus, the empty list of static groups (the default
value) means one group for all static imports. This property has effect only when
the property option is set to top or bottom.packageGroups - a comma-separated list of package names/prefixes.public void setOrdered(boolean ordered)
ordered - whether lexicographic ordering of imports within a group
required or not.public void setSeparated(boolean separated)
separated - whether groups should be separated by one blank line or comment.public void setSeparatedStaticGroups(boolean separatedStaticGroups)
option is set to top or bottom and when property staticGroups
is enabled.separatedStaticGroups - whether groups should be separated by one blank line or comment.public void setCaseSensitive(boolean caseSensitive)
caseSensitive - whether string comparison should be case sensitive.public void setSortStaticImportsAlphabetically(boolean sortAlphabetically)
sortAlphabetically - true or false.public void setUseContainerOrderingForStatic(boolean useContainerOrdering)
useContainerOrdering - whether to use container ordering for static imports or not.public int[] getDefaultTokens()
AbstractCheckgetDefaultTokens in class AbstractCheckTokenTypespublic int[] getAcceptableTokens()
AbstractCheckgetAcceptableTokens in class AbstractCheckTokenTypespublic int[] getRequiredTokens()
AbstractCheckgetRequiredTokens in class AbstractCheckTokenTypespublic void beginTree(DetailAST rootAST)
AbstractCheckbeginTree in class AbstractCheckrootAST - the root of the treepublic void visitToken(DetailAST ast)
AbstractCheckvisitToken in class AbstractCheckast - the token to processprivate void doVisitToken(FullIdent ident, boolean isStatic, boolean previous, DetailAST ast)
ident - the import to process.isStatic - whether the token is static or not.previous - previous non-static but current is static (above), or
previous static but current is non-static (under).ast - node of the AST.private boolean needSeparator(boolean isStatic)
isStatic - whether the token is static or not.private boolean isSeparatorInGroup(int groupIdx, boolean isStatic, int line)
groupIdx - group number.isStatic - whether the token is static or not.line - the line of the current import.private boolean isSeparatorBeforeImport(int line)
line - the line of the current import.private void doVisitTokenInSameGroup(boolean isStatic, boolean previous, java.lang.String name, DetailAST ast)
isStatic - whether the token is static or not.previous - previous non-static but current is static (above), or
previous static but current is non-static (under).name - the name of the current import.ast - node of the AST.private boolean isWrongOrder(java.lang.String name, boolean isStatic)
name - import name.isStatic - whether it is a static import name.private static int compareContainerOrder(java.lang.String importName1, java.lang.String importName2, boolean caseSensitive)
import static HttpConstants.COLON => HttpConstants import static HttpHeaders.addHeader => HttpHeaders import static HttpHeaders.setHeader => HttpHeaders import static HttpHeaders.Names.DATE => HttpHeaders.Names
According to this logic, HttpHeaders.Names would come after HttpHeaders. For more details, see static imports comparison method in Eclipse.
importName1 - first import name.importName2 - second import name.caseSensitive - whether the comparison of fully qualified import names is case
sensitive.0 if str1 is equal to str2; a value
less than 0 if str is less than the str2 (container order
or lexicographical); and a value greater than 0 if str1 is greater than str2
(container order or lexicographically).private static java.lang.String getImportContainer(java.lang.String qualifiedImportName)
import static HttpConstants.COLON => HttpConstants import static HttpHeaders.addHeader => HttpHeaders import static HttpHeaders.setHeader => HttpHeaders import static HttpHeaders.Names.DATE => HttpHeaders.Names
qualifiedImportName - fully qualified import name.private int getGroupNumber(boolean isStatic, java.lang.String name)
isStatic - whether the token is static or not.name - the import name to find.private static int getGroupNumber(java.util.regex.Pattern[] patterns, java.lang.String name)
patterns - groups to check.name - the import name to find.private static int compare(java.lang.String string1, java.lang.String string2, boolean caseSensitive)
string1 - the first string.string2 - the second string.caseSensitive - whether the comparison is case sensitive.0 if string1 is equal to string2; a value
less than 0 if string1 is lexicographically less
than the string2; and a value greater than 0 if
string1 is lexicographically greater than string2.private static java.util.regex.Pattern[] compilePatterns(java.lang.String... packageGroups)
packageGroups - a comma-separated list of package names/prefixes.java.lang.IllegalArgumentException - if any of the package groups are not valid.Copyright © 2001-2022. All Rights Reserved.