Skip to content

Commit

Permalink
Issue checkstyle#3312: Add sourcepath property to Ant task
Browse files Browse the repository at this point in the history
  • Loading branch information
soon committed Apr 15, 2017
1 parent c873e56 commit 175b794
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 18 deletions.
1 change: 1 addition & 0 deletions config/suppressions.xml
Expand Up @@ -78,6 +78,7 @@
<suppress checks="ClassDataAbstractionCoupling" files="(CheckerTest|TreeWalkerTest|BaseCheckTestSupport|XdocsPagesTest|CheckstyleAntTaskTest)\.java"/>
<suppress checks="ClassDataAbstractionCoupling" files="PropertyCacheFile\.java"/>
<suppress checks="ClassFanOutComplexity" files="[\\/]Main\.java"/>
<suppress checks="ClassFanOutComplexity" files="CheckstyleAntTask\.java"/>
<!-- a lot of GUI elements is OK -->
<suppress checks="ClassDataAbstractionCoupling" files="(TreeTable|MainFrame)\.java"/>

Expand Down
129 changes: 112 additions & 17 deletions src/main/java/com/puppycrawl/tools/checkstyle/ant/CheckstyleAntTask.java
Expand Up @@ -26,11 +26,13 @@
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.stream.Collectors;

import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
Expand Down Expand Up @@ -72,6 +74,9 @@ public class CheckstyleAntTask extends Task {
/** Suffix for time string. */
private static final String TIME_SUFFIX = " ms.";

/** Contains the paths to process. */
private final List<Path> paths = new ArrayList<>();

/** Contains the filesets to process. */
private final List<FileSet> fileSets = new ArrayList<>();

Expand Down Expand Up @@ -151,6 +156,14 @@ public void setMaxWarnings(int maxWarnings) {
this.maxWarnings = maxWarnings;
}

/**
* Adds a path.
* @param path the path to add.
*/
public void addPath(Path path) {
paths.add(path);
}

/**
* Adds set of files (nested fileset attribute).
* @param fileSet the file set to add
Expand Down Expand Up @@ -296,9 +309,11 @@ public void execute() {
log("compiled on " + compileTimestamp, Project.MSG_VERBOSE);

// Check for no arguments
if (fileName == null && fileSets.isEmpty()) {
if (fileName == null
&& fileSets.isEmpty()
&& paths.isEmpty()) {
throw new BuildException(
"Must specify at least one of 'file' or nested 'fileset'.",
"Must specify at least one of 'file' or nested 'fileset' or 'path'.",
getLocation());
}
if (configLocation == null) {
Expand Down Expand Up @@ -359,7 +374,7 @@ private static void destroyRootModule(RootModule rootModule) {
private void processFiles(RootModule rootModule, final SeverityLevelCounter warningCounter,
final String checkstyleVersion) {
final long startTime = System.currentTimeMillis();
final List<File> files = scanFileSets();
final List<File> files = getFilesToCheck();
final long endTime = System.currentTimeMillis();
log("To locate the files took " + (endTime - startTime) + TIME_SUFFIX,
Project.MSG_VERBOSE);
Expand Down Expand Up @@ -509,33 +524,113 @@ private AuditListener[] getListeners() {

/**
* Returns the list of files (full path name) to process.
* @return the list of files included via the filesets.
* @return the list of files included via the filesets and paths.
*/
protected List<File> scanFileSets() {
final List<File> list = new ArrayList<>();
protected List<File> getFilesToCheck() {
final List<File> allFiles = new ArrayList<>();
if (fileName != null) {
// oops we've got an additional one to process, don't
// forget it. No sweat, it's fully resolved via the setter.
log("Adding standalone file for audit", Project.MSG_VERBOSE);
list.add(new File(fileName));
allFiles.add(new File(fileName));
}

final List<File> filesFromFileSets = scanFileSets();
allFiles.addAll(filesFromFileSets);

final List<File> filesFromPaths = scanPaths();
allFiles.addAll(filesFromPaths);

return allFiles;
}

/**
* Retrieves all files from the defined paths.
* @return a list of files defined via paths.
*/
protected List<File> scanPaths() {
final List<File> allFiles = new ArrayList<>();

for (int i = 0; i < paths.size(); i++) {
final Path currentPath = paths.get(i);
final List<File> pathFiles = scanPath(currentPath, i + 1);
allFiles.addAll(pathFiles);
}

return allFiles;
}

/**
* Scans the given path and retrieves all files for the given path.
*
* @param path A path to scan.
* @param pathIndex The index of the given path. Used in log messages only.
* @return A list of files, extracted from the given path.
*/
private List<File> scanPath(Path path, int pathIndex) {
final String[] resources = path.list();
log(pathIndex + ") Scanning path " + path, Project.MSG_VERBOSE);
final List<File> allFiles = new ArrayList<>();
final List<File> concreteFiles = new ArrayList<>();

for (String resource : resources) {
final File file = new File(resource);
if (file.isFile()) {
concreteFiles.add(file);
} else {
final DirectoryScanner scanner = new DirectoryScanner();
scanner.setBasedir(file);
scanner.scan();
final List<File> scannedFiles = retrieveAllScannedFiles(scanner, pathIndex);
allFiles.addAll(scannedFiles);
}
}

if (!concreteFiles.isEmpty()) {
log(String.format(Locale.ROOT, "%d) Adding %d files from path %s",
pathIndex, concreteFiles.size(), path), Project.MSG_VERBOSE);
allFiles.addAll(concreteFiles);
}

return allFiles;
}

/**
* Returns the list of files (full path name) to process.
* @return the list of files included via the filesets.
*/
protected List<File> scanFileSets() {
final List<File> allFiles = new ArrayList<>();

for (int i = 0; i < fileSets.size(); i++) {
final FileSet fileSet = fileSets.get(i);
final DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
scanner.scan();

final String[] names = scanner.getIncludedFiles();
log(i + ") Adding " + names.length + " files from directory "
+ scanner.getBasedir(), Project.MSG_VERBOSE);

for (String element : names) {
final String pathname = scanner.getBasedir() + File.separator
+ element;
list.add(new File(pathname));
}
final List<File> scannedFiles = retrieveAllScannedFiles(scanner, i);
allFiles.addAll(scannedFiles);
}

return list;
return allFiles;
}

/**
* Retrieves all matched files from the given scanner.
*
* @param scanner A directory scanner. Note, that {@link DirectoryScanner#scan()}
* must be called before calling this method.
* @param logIndex A log entry index. Used only for log messages.
* @return A list of files, retrieved from the given scanner.
*/
private List<File> retrieveAllScannedFiles(DirectoryScanner scanner, int logIndex) {
final String[] fileNames = scanner.getIncludedFiles();
log(String.format(Locale.ROOT, "%d) Adding %d files from directory %s",
logIndex, fileNames.length, scanner.getBasedir()), Project.MSG_VERBOSE);

return Arrays.stream(fileNames)
.map(name -> scanner.getBasedir() + File.separator + name)
.map(File::new)
.collect(Collectors.toList());
}

/**
Expand Down
Expand Up @@ -37,6 +37,7 @@
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.resources.FileResource;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;

Expand Down Expand Up @@ -75,6 +76,28 @@ public final void testDefaultFlawless() throws IOException {
antTask.execute();
}

@Test
public final void testSourcePathsOneFile() throws IOException {
final CheckstyleAntTask antTask = getCheckstyleAntTask();
final FileSet examinationFileSet = new FileSet();
examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
final Path sourcePath = new Path(antTask.getProject());
sourcePath.addFileset(examinationFileSet);
antTask.addPath(sourcePath);
antTask.execute();
}

@Test
public final void testSourcePathsDirectoryWithNestedFile() throws IOException {
final CheckstyleAntTask antTask = getCheckstyleAntTask();
final FileResource fileResource = new FileResource(
antTask.getProject(), getPath(FLAWLESS_INPUT_DIR));
final Path sourcePath = new Path(antTask.getProject());
sourcePath.add(fileResource);
antTask.addPath(sourcePath);
antTask.execute();
}

@Test
public final void testCustomRootModule() throws IOException {
TestRootModuleChecker.reset();
Expand Down Expand Up @@ -147,7 +170,7 @@ public final void testNoFile() throws IOException {
fail("Exception is expected");
}
catch (BuildException ex) {
assertEquals("Must specify at least one of 'file' or nested 'fileset' or 'sourcepath'.",
assertEquals("Must specify at least one of 'file' or nested 'fileset' or 'path'.",
ex.getMessage());
}
}
Expand Down

0 comments on commit 175b794

Please sign in to comment.