From 22136c67e9c83494e7aa977ffe7a79beee1b4175 Mon Sep 17 00:00:00 2001
From: Oliver Burn
* Example:
+ *
* There is always an additional, implied "everything else" package
- * group. If no "groups" property is supplied, all imports belong in
- * this "everything else" group.
- * ordered defaults to true.
+ * group. If no "groups" property is supplied, all imports belong in
+ * this "everything else" group.
*
- * separated defaults to false.
+ * Defaults:
*
* Compatible with Java 1.5 source.
+ *
- 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:
+
+ *
*
*
- * <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>
*
*
+ *
+ *
*
+ * 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 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);
}
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderOption.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderOption.java
new file mode 100644
index 000000000..0d79bf319
--- /dev/null
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderOption.java
@@ -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:
+ *
+ *
+ 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;
+ *
+ */
+ TOP,
+
+ /**
+ * Represents the policy that static imports are above the local group.
+ * For example:
+ *
+ *
+ 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;
+ *
+ */
+ ABOVE,
+
+ /**
+ * Represents the policy that static imports are processed like non static
+ * imports. For example:
+ *
+ *
+ 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;
+ *
+ */
+ INFLOW,
+
+ /**
+ * Represents the policy that static imports are under the local group.
+ * For example:
+ *
+ *
+ 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;
+ *
+ */
+ UNDER,
+
+ /**
+ * Represents the policy that static imports are all at the bottom.
+ * For example:
+ *
+ *
+ 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.*;
+ *
+ */
+ BOTTOM;
+}
diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Above.java b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Above.java
new file mode 100644
index 000000000..6d8ee6c6b
--- /dev/null
+++ b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Above.java
@@ -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 {
+}
\ No newline at end of file
diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Bottom.java b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Bottom.java
new file mode 100644
index 000000000..b9e1133c2
--- /dev/null
+++ b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Bottom.java
@@ -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 {
+}
\ No newline at end of file
diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_InFlow.java b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_InFlow.java
new file mode 100644
index 000000000..8a0b5556d
--- /dev/null
+++ b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_InFlow.java
@@ -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 {
+}
\ No newline at end of file
diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Top.java b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Top.java
new file mode 100644
index 000000000..a27124d9d
--- /dev/null
+++ b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Top.java
@@ -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 {
+}
\ No newline at end of file
diff --git a/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Under.java b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Under.java
new file mode 100644
index 000000000..258695115
--- /dev/null
+++ b/src/testinputs/com/puppycrawl/tools/checkstyle/imports/InputImportOrder_Under.java
@@ -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 {
+}
\ No newline at end of file
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java
index cb9692db9..30c8eb9cd 100644
--- a/src/tests/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java
+++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/imports/ImportOrderCheckTest.java
@@ -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);
+ }
}
diff --git a/src/xdocs/config_imports.xml b/src/xdocs/config_imports.xml
index d5edbf06f..7137aa65a 100755
--- a/src/xdocs/config_imports.xml
+++ b/src/xdocs/config_imports.xml
@@ -323,12 +323,21 @@ class FooBar {
+
- 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: +
+ This property represents the policy for checking imports order. + The following table describes the valid options: +
+ +| Option | +Definition | +
| top | +All static imports are at the top. For example:
+ + import static a.b.C.*; + import static x.y.Z.*; + + import a.b.D; + import x.y.Z;+ |
+
| above | +All static imports are above the local group.. For example:
+ + import static a.b.C.*; + import a.b.D; + + import static x.y.Z.*; + import x.y.Z;+ |
+
| inflow | +All static imports are processed like non static
+ imports. For example:
+ + import static a.b.C.*; + import a.b.D; + + import x.y.Z; + import static x.y.Z.*;+ |
+
| under | +All static imports are under the local group. For example:
+ + import a.b.D; + import static a.b.C.*; + + import x.y.Z; + import static x.y.Z.*;+ |
+
| bottom | +All static imports are at the bottom. For example:
+ + import a.b.D; + import x.y.Z; + + import static a.b.C.*; + import static x.y.Z.*;+ |
+