diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
index d3bcc59a3..138d03d85 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java
@@ -284,6 +284,20 @@ public abstract class Check
log(aLineNo, aColNo, aKey, EMPTY_OBJECT_ARRAY);
}
+ /**
+ * Helper method to log a LocalizedMessage.
+ *
+ * @param aLineNo line number to associate with the message
+ * @param aColNo column number to associate with the message
+ * @param aKey key to locale message format
+ * @param aArg0 an Object value
+ */
+ public void log(int aLineNo, int aColNo, String aKey,
+ Object aArg0)
+ {
+ log(aLineNo, aColNo, aKey, new Object[] {aArg0});
+ }
+
/**
* Helper method to log a LocalizedMessage.
*
@@ -309,6 +323,7 @@ public abstract class Check
*/
public void log(int aLineNo, int aColNo, String aKey, Object[] aArgs)
{
+ // TODO: need to fix this ugly hack below!!!!!!
final int col = aColNo + 1;
// final int col = 1 + Utils.lengthExpandedTabs(
// mLines[aLineNo - 1], aColNo, mTabWidth);
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FullIdent.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FullIdent.java
new file mode 100644
index 000000000..21b3e25ce
--- /dev/null
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/FullIdent.java
@@ -0,0 +1,100 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2002 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.api;
+
+import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
+
+/**
+ * Represents a string with an associated line number.
+ * @author Oliver Burn
+ **/
+public class FullIdent
+{
+ /** the string **/
+ private final StringBuffer mBuffer = new StringBuffer();
+ /** the line number **/
+ private int mLineNo;
+ /** the column number **/
+ private int mColNo;
+
+ /** @return the text **/
+ public String getText()
+ {
+ return mBuffer.toString();
+ }
+
+ /** @return the line number **/
+ public int getLineNo()
+ {
+ return mLineNo;
+ }
+
+ /** @return the column number **/
+ public int getColumnNo()
+ {
+ return mColNo;
+ }
+
+ public void append(String aText)
+ {
+ mBuffer.append(".");
+ }
+ public void append(DetailAST aAST)
+ {
+ mBuffer.append(aAST.getText());
+ if (mLineNo == 0) {
+ mLineNo = aAST.getLineNo();
+ }
+ else if (aAST.getLineNo() > 0) {
+ mLineNo = Math.min(mLineNo, aAST.getLineNo());
+ }
+ // TODO: make a function
+ if (mColNo == 0) {
+ mColNo = aAST.getColumnNo();
+ }
+ else if (aAST.getColumnNo() > 0) {
+ mColNo = Math.min(mColNo, aAST.getColumnNo());
+ }
+ }
+
+ public static FullIdent createFullIdent(DetailAST aAST)
+ {
+ final FullIdent fi = new FullIdent();
+ extractFullIdent(fi, aAST);
+ return fi;
+ }
+
+ public static void extractFullIdent(FullIdent aFull, DetailAST aAST)
+ {
+ // A guard to be paranoid
+ if (aAST == null) {
+ return;
+ }
+
+ if (aAST.getType() == JavaTokenTypes.DOT) {
+ extractFullIdent(aFull, (DetailAST) aAST.getFirstChild());
+ aFull.append(".");
+ extractFullIdent(
+ aFull, (DetailAST) aAST.getFirstChild().getNextSibling());
+ }
+ else {
+ aFull.append(aAST);
+ }
+ }
+}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AvoidStarImport.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AvoidStarImport.java
index 6cf672c53..7b30dbfa7 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AvoidStarImport.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/AvoidStarImport.java
@@ -21,6 +21,7 @@ package com.puppycrawl.tools.checkstyle.checks;
import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
/**
* Check that finds import statement that use the * notation.
@@ -44,8 +45,8 @@ public class AvoidStarImport
/** @see com.puppycrawl.tools.checkstyle.api.Check */
public void visitToken(DetailAST aAST)
{
- final String name = getImportText(aAST);
- if ((name != null) && name.endsWith(".*")) {
+ final FullIdent name = getImportText(aAST);
+ if ((name != null) && name.getText().endsWith(".*")) {
log(aAST.getLineNo(), "import.avoidStar");
}
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ImportCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ImportCheck.java
index f76aff81f..08080c608 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ImportCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ImportCheck.java
@@ -21,6 +21,8 @@ package com.puppycrawl.tools.checkstyle.checks;
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.Utils;
import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
/**
@@ -41,47 +43,15 @@ public abstract class ImportCheck
* @param aAST the node containing the import
* @return a String value
*/
- protected String getImportText(DetailAST aAST)
+ protected FullIdent getImportText(DetailAST aAST)
{
- String text = (String) getTokenContext().get(TEXT_KEY);
+ FullIdent text = (FullIdent) getTokenContext().get(TEXT_KEY);
if (text != null) {
return text;
}
- final StringBuffer buf = new StringBuffer();
- extractIdent(buf, (DetailAST) aAST.getFirstChild());
- text = buf.toString();
+ text = FullIdent.createFullIdent((DetailAST) aAST.getFirstChild());
getTokenContext().put(TEXT_KEY, text);
return text;
}
-
- /**
- * Fills in the name of an import.
- *
- * @param aBuf the StringBuffer to add the name to
- * @param aAST the node to operate on
- */
- private static void extractIdent(StringBuffer aBuf, DetailAST aAST)
- {
- if (aAST == null) {
- System.out.println("CALLED WITH NULL");
- return;
- }
-
- if (aAST.getType() == JavaTokenTypes.DOT) {
- extractIdent(aBuf, (DetailAST) aAST.getFirstChild());
- aBuf.append(".");
- extractIdent(aBuf,
- (DetailAST) aAST.getFirstChild().getNextSibling());
- }
- else if ((aAST.getType() == JavaTokenTypes.IDENT)
- || (aAST.getType() == JavaTokenTypes.STAR))
- {
- aBuf.append(aAST.getText());
- }
- else {
- System.out.println("********* Got the string " + aAST.getText());
- aBuf.append(aAST.getText());
- }
- }
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/PackageNameCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/PackageNameCheck.java
index b377127da..9f9d09ff1 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/PackageNameCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/PackageNameCheck.java
@@ -19,6 +19,7 @@
package com.puppycrawl.tools.checkstyle.checks;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
public class PackageNameCheck
@@ -45,35 +46,13 @@ public class PackageNameCheck
public void visitToken(DetailAST aAST)
{
final DetailAST nameAST = (DetailAST) aAST.getFirstChild();
- final StringBuffer buf = new StringBuffer();
- extractIdent(buf, nameAST);
- final String text = buf.toString();
-
- if (!getRegexp().match(text)) {
- log(nameAST.getLineNo(),
+ final FullIdent full = FullIdent.createFullIdent(nameAST);
+ if (!getRegexp().match(full.getText())) {
+ log(full.getLineNo(),
+ full.getColumnNo(),
"name.invalidPattern",
- text,
+ full.getText(),
getFormat());
}
}
-
- // TODO: refactor to Utils. It should return the text, plus the starting
- // line and column
- private static void extractIdent(StringBuffer aBuf, DetailAST aAST)
- {
- if (aAST == null) {
- System.out.println("CALLED WITH NULL");
- return;
- }
-
- if (aAST.getType() == JavaTokenTypes.DOT) {
- extractIdent(aBuf, (DetailAST) aAST.getFirstChild());
- aBuf.append(".");
- extractIdent(aBuf,
- (DetailAST) aAST.getFirstChild().getNextSibling());
- }
- else {
- aBuf.append(aAST.getText());
- }
- }
}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/RedundantImportCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/RedundantImportCheck.java
new file mode 100644
index 000000000..6a1ddf83a
--- /dev/null
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/RedundantImportCheck.java
@@ -0,0 +1,77 @@
+////////////////////////////////////////////////////////////////////////////////
+// checkstyle: Checks Java source code for adherence to a set of rules.
+// Copyright (C) 2001-2002 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;
+
+import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
+
+public class RedundantImportCheck
+ extends ImportCheck
+{
+ private String mPkgName;
+
+ /** @see com.puppycrawl.tools.checkstyle.api.Check */
+ public int[] getDefaultTokens()
+ {
+ return new int[] {JavaTokenTypes.IMPORT, JavaTokenTypes.PACKAGE_DEF};
+ }
+
+ /** @see com.puppycrawl.tools.checkstyle.api.Check */
+ public void visitToken(DetailAST aAST)
+ {
+ if (aAST.getType() == JavaTokenTypes.PACKAGE_DEF) {
+ final DetailAST nameAST = (DetailAST) aAST.getFirstChild();
+ mPkgName = FullIdent.createFullIdent(nameAST).getText();
+ }
+ else {
+ final FullIdent imp = getImportText(aAST);
+ if (fromPackage(imp.getText(), "java.lang")) {
+ log(aAST.getLineNo(), aAST.getColumnNo(), "import.lang");
+ }
+ else if (fromPackage(imp.getText(), mPkgName)) {
+ log(aAST.getLineNo(), aAST.getColumnNo(), "import.same");
+ }
+ }
+ }
+
+ /**
+ * Determines in an import statement is for types from a specified package.
+ * @param aImport the import name
+ * @param aPkg the package name
+ * @return whether from the package
+ */
+ private static boolean fromPackage(String aImport, String aPkg)
+ {
+ boolean retVal = false;
+ if (aPkg == null) {
+ // If not package, then check for no package in the import.
+ retVal = (aImport.indexOf('.') == -1);
+ }
+ else {
+ final int index = aImport.lastIndexOf('.');
+ if (index != -1) {
+ final String front = aImport.substring(0, index);
+ retVal = front.equals(aPkg);
+ }
+ }
+ return retVal;
+ }
+}
diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/UnusedImportsCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/UnusedImportsCheck.java
index 6dc4303a0..8ff16d8d9 100644
--- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/UnusedImportsCheck.java
+++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/UnusedImportsCheck.java
@@ -21,6 +21,7 @@ package com.puppycrawl.tools.checkstyle.checks;
import com.puppycrawl.tools.checkstyle.JavaTokenTypes;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.FullIdent;
import java.util.HashSet;
import java.util.Set;
@@ -31,7 +32,8 @@ import java.util.Iterator;
* @author Oliver Burn
* @version 1.0
*/
-public class UnusedImportsCheck extends ImportCheck
+public class UnusedImportsCheck
+ extends ImportCheck
{
/** flag to indicate when time to start collecting references */
private boolean mCollect;
@@ -54,10 +56,16 @@ public class UnusedImportsCheck extends ImportCheck
// loop over all the imports to see if referenced.
final Iterator it = mImports.iterator();
while (it.hasNext()) {
- final String imp = (String) it.next();
- if (!mReferenced.contains(basename(imp))) {
- log(666, "unused import " + imp);
+ final FullIdent imp = (FullIdent) it.next();
+
+ if (!mReferenced.contains(basename(imp.getText()))) {
+ log(imp.getLineNo(),
+ imp.getColumnNo(),
+ "import.unused", imp.getText());
}
+// else if (isIllegalImport(imp.getText())) {
+// mMessages.add(imp.getLineNo(), "import.illegal", imp.getText());
+// }
}
}
@@ -113,8 +121,8 @@ public class UnusedImportsCheck extends ImportCheck
*/
private void processImport(DetailAST aAST)
{
- final String name = getImportText(aAST);
- if ((name != null) && !name.endsWith(".*")) {
+ final FullIdent name = getImportText(aAST);
+ if ((name != null) && !name.getText().endsWith(".*")) {
mImports.add(name);
}
}
@@ -128,4 +136,5 @@ public class UnusedImportsCheck extends ImportCheck
final int i = aType.lastIndexOf(".");
return (i == -1) ? aType : aType.substring(i + 1);
}
+
}
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/PackageNameCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/PackageNameCheckTest.java
index a66f51d11..7540e73b9 100644
--- a/src/tests/com/puppycrawl/tools/checkstyle/PackageNameCheckTest.java
+++ b/src/tests/com/puppycrawl/tools/checkstyle/PackageNameCheckTest.java
@@ -23,7 +23,7 @@ public class PackageNameCheckTest
final Checker c = createChecker(checkConfig);
final String fname = getPath("InputSimple.java");
final String[] expected = {
- "6:1: Name 'com.puppycrawl.tools.checkstyle' must match pattern '[A-Z]+'.",
+ "6:9: Name 'com.puppycrawl.tools.checkstyle' must match pattern '[A-Z]+'.",
};
verify(c, fname, expected);
}
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/RedundantImportCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/RedundantImportCheckTest.java
new file mode 100644
index 000000000..cb80325f4
--- /dev/null
+++ b/src/tests/com/puppycrawl/tools/checkstyle/RedundantImportCheckTest.java
@@ -0,0 +1,28 @@
+package com.puppycrawl.tools.checkstyle;
+
+import com.puppycrawl.tools.checkstyle.checks.RedundantImportCheck;
+
+public class RedundantImportCheckTest
+ extends BaseCheckTestCase
+{
+ public RedundantImportCheckTest(String aName)
+ {
+ super(aName);
+ }
+
+ public void testWithChecker()
+ throws Exception
+ {
+ final CheckConfiguration checkConfig = new CheckConfiguration();
+ checkConfig.setClassname(RedundantImportCheck.class.getName());
+ final Checker c = createChecker(checkConfig);
+ final String fname = getPath("InputImport.java");
+ final String[] expected = {
+ "7:1: Redundant import from the same package.",
+ "8:38: Redundant import from the same package.",
+ "10:1: Redundant import from the java.lang package.",
+ "11:1: Redundant import from the java.lang package.",
+ };
+ verify(c, fname, expected);
+ }
+}
diff --git a/src/tests/com/puppycrawl/tools/checkstyle/UnusedImportsCheckTest.java b/src/tests/com/puppycrawl/tools/checkstyle/UnusedImportsCheckTest.java
new file mode 100644
index 000000000..403571c62
--- /dev/null
+++ b/src/tests/com/puppycrawl/tools/checkstyle/UnusedImportsCheckTest.java
@@ -0,0 +1,31 @@
+package com.puppycrawl.tools.checkstyle;
+
+import com.puppycrawl.tools.checkstyle.checks.UnusedImportsCheck;
+
+public class UnusedImportsCheckTest
+ extends BaseCheckTestCase
+{
+ public UnusedImportsCheckTest(String aName)
+ {
+ super(aName);
+ }
+
+ public void testDefault()
+ throws Exception
+ {
+ final CheckConfiguration checkConfig = new CheckConfiguration();
+ checkConfig.setClassname(UnusedImportsCheck.class.getName());
+ final Checker c = createChecker(checkConfig);
+ final String fname = getPath("InputImport.java");
+ final String[] expected = {
+ "8:45: Unused import - com.puppycrawl.tools.checkstyle.Configuration.",
+ "11:8: Unused import - java.lang.String.",
+ "13:8: Unused import - java.util.List.",
+ "14:8: Unused import - java.util.List.",
+ "17:8: Unused import - java.util.Enumeration.",
+ "20:8: Unused import - javax.swing.JToggleButton.",
+ "22:8: Unused import - javax.swing.BorderFactory.",
+ };
+ verify(c, fname, expected);
+ }
+}