From 1d73764b9a1e81f66d3dbeebb2fd6bdc1e05952b Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 3 Jun 2011 14:51:14 +0200 Subject: [PATCH] Allow to manually define source files to analyze --- .../batch/DefaultProjectFileSystem2.java | 17 ++- .../batch/bootstrapper/ProjectDefinition.java | 4 +- .../batch/bootstrap/ProjectDefinition.java | 111 ++++++++++++++---- .../resources/DefaultProjectFileSystem.java | 50 ++++++-- .../bootstrap/ProjectDefinitionTest.java | 32 +++-- .../DefaultProjectFileSystemTest.java | 15 +++ 6 files changed, 182 insertions(+), 47 deletions(-) diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java index baa4e2394ec..632ee139c8c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java @@ -21,6 +21,7 @@ package org.sonar.batch; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import org.apache.commons.io.FileUtils; import org.apache.maven.project.MavenProject; import org.sonar.api.batch.bootstrap.ProjectDefinition; @@ -31,6 +32,7 @@ import org.sonar.api.utils.SonarException; import java.io.File; import java.io.IOException; +import java.util.Collections; import java.util.List; /** @@ -84,6 +86,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { } } + @Override public List getSourceDirs() { List unfiltered; if (pom != null) { @@ -106,7 +109,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { if (pom != null) { pom.getCompileSourceRoots().add(0, dir.getAbsolutePath()); } else { - def.addSourceDir(dir.getAbsolutePath()); + def.addSourceDirs(dir.getAbsolutePath()); } return this; } @@ -114,6 +117,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { /** * Maven can modify test directories during Sonar execution - see MavenPhaseExecutor. */ + @Override public List getTestDirs() { List unfiltered; if (pom != null) { @@ -136,7 +140,7 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { if (pom != null) { pom.getTestCompileSourceRoots().add(0, dir.getAbsolutePath()); } else { - def.addTestDir(dir.getAbsolutePath()); + def.addTestDirs(dir.getAbsolutePath()); } return this; } @@ -168,4 +172,13 @@ public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem { return dir; } + @Override + protected List getInitialSourceFiles() { + return resolvePaths(def.getSourceFiles()); + } + + @Override + protected List getInitialTestFiles() { + return resolvePaths(def.getTestFiles()); + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java index e24d078f172..f3fbe726c9f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java @@ -62,7 +62,7 @@ public class ProjectDefinition { } public void addSourceDir(String path) { - target.addSourceDir(path); + target.addSourceDirs(path); } public List getTestDirs() { @@ -74,7 +74,7 @@ public class ProjectDefinition { * It can be absolute or relative to project directory. */ public void addTestDir(String path) { - target.addTestDir(path); + target.addTestDirs(path); } public List getBinaries() { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java index 37764621c10..2282be26078 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java @@ -20,6 +20,7 @@ package org.sonar.api.batch.bootstrap; import com.google.common.collect.Lists; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.sonar.api.BatchComponent; import org.sonar.api.CoreProperties; @@ -32,13 +33,15 @@ import java.util.Properties; /** * Defines project metadata (key, name, source directories, ...). It's generally used by the * {@link org.sonar.api.batch.bootstrap.ProjectBuilder extension point} - * + * * @since 2.9 */ public final class ProjectDefinition implements BatchComponent { - public static final String SOURCES_PROPERTY = "sonar.sources"; - public static final String TESTS_PROPERTY = "sonar.tests"; + public static final String SOURCE_DIRS_PROPERTY = "sonar.sources"; + public static final String SOURCE_FILES_PROPERTY = "sonar.sourceFiles"; + public static final String TEST_DIRS_PROPERTY = "sonar.tests"; + public static final String TEST_FILES_PROPERTY = "sonar.testFiles"; public static final String BINARIES_PROPERTY = "sonar.binaries"; public static final String LIBRARIES_PROPERTY = "sonar.libraries"; @@ -132,26 +135,30 @@ public final class ProjectDefinition implements BatchComponent { } public List getSourceDirs() { - String sources = properties.getProperty(SOURCES_PROPERTY, ""); + String sources = properties.getProperty(SOURCE_DIRS_PROPERTY, ""); return Arrays.asList(StringUtils.split(sources, SEPARATOR)); } /** - * @param path path to directory with main sources. - * It can be absolute or relative to project directory. + * @param paths paths to directory with main sources. + * They can be absolute or relative to project base directory. */ - public ProjectDefinition addSourceDir(String path) { - appendProperty(SOURCES_PROPERTY, path); + public ProjectDefinition addSourceDirs(String... paths) { + for (String path : paths) { + appendProperty(SOURCE_DIRS_PROPERTY, FilenameUtils.normalize(path)); + } return this; } - public ProjectDefinition addSourceDir(File path) { - addSourceDir(path.getAbsolutePath()); + public ProjectDefinition addSourceDirs(File... dirs) { + for (File dir : dirs) { + addSourceDirs(dir); + } return this; } public ProjectDefinition setSourceDir(String path) { - properties.setProperty(SOURCES_PROPERTY, path); + properties.setProperty(SOURCE_DIRS_PROPERTY, FilenameUtils.normalize(path)); return this; } @@ -160,20 +167,84 @@ public final class ProjectDefinition implements BatchComponent { return this; } + /** + * Adding source files is possible only if no source directories have been set. + * Absolute path or relative path from project base dir. + */ + public ProjectDefinition addSourceFiles(String... paths) { + for (String path : paths) { + appendProperty(SOURCE_FILES_PROPERTY, FilenameUtils.normalize(path)); + } + return this; + } + + /** + * Adding source files is possible only if no source directories have been set. + */ + public ProjectDefinition addSourceFiles(File... files) { + for (File file : files) { + addSourceFiles(file.getAbsolutePath()); + } + return this; + } + + public List getSourceFiles() { + String sources = properties.getProperty(SOURCE_FILES_PROPERTY, ""); + return Arrays.asList(StringUtils.split(sources, SEPARATOR)); + } + + public List getTestDirs() { - String sources = properties.getProperty(TESTS_PROPERTY, ""); + String sources = properties.getProperty(TEST_DIRS_PROPERTY, ""); return Arrays.asList(StringUtils.split(sources, SEPARATOR)); } /** - * @param path path to directory with test sources. - * It can be absolute or relative to project directory. + * @param paths path to directory with test sources. + * It can be absolute or relative to project directory. */ - public ProjectDefinition addTestDir(String path) { - appendProperty(TESTS_PROPERTY, path); + public ProjectDefinition addTestDirs(String... paths) { + for (String path : paths) { + appendProperty(TEST_DIRS_PROPERTY, FilenameUtils.normalize(path)); + } return this; } + public ProjectDefinition addTestDirs(File... dirs) { + for (File dir : dirs) { + addTestDirs(dir.getAbsolutePath()); + } + return this; + } + + + /** + * Adding source files is possible only if no source directories have been set. + * Absolute path or relative path from project base dir. + */ + public ProjectDefinition addTestFiles(String... paths) { + for (String path : paths) { + appendProperty(TEST_FILES_PROPERTY, FilenameUtils.normalize(path)); + } + return this; + } + + /** + * Adding source files is possible only if no source directories have been set. + */ + public ProjectDefinition addTestFiles(File... files) { + for (File file : files) { + addTestFiles(file.getAbsolutePath()); + } + return this; + } + + public List getTestFiles() { + String sources = properties.getProperty(TEST_FILES_PROPERTY, ""); + return Arrays.asList(StringUtils.split(sources, SEPARATOR)); + } + + public List getBinaries() { String sources = properties.getProperty(BINARIES_PROPERTY, ""); return Arrays.asList(StringUtils.split(sources, SEPARATOR)); @@ -181,11 +252,11 @@ public final class ProjectDefinition implements BatchComponent { /** * @param path path to directory with compiled source. In case of Java this is directory with class files. - * It can be absolute or relative to project directory. + * It can be absolute or relative to project directory. * @TODO currently Sonar supports only one such directory due to dependency on MavenProject */ public ProjectDefinition addBinaryDir(String path) { - appendProperty(BINARIES_PROPERTY, path); + appendProperty(BINARIES_PROPERTY, FilenameUtils.normalize(path)); return this; } @@ -196,10 +267,10 @@ public final class ProjectDefinition implements BatchComponent { /** * @param path path to file with third-party library. In case of Java this is path to jar file. - * It can be absolute or relative to project directory. + * It can be absolute or relative to project directory. */ public void addLibrary(String path) { - appendProperty(LIBRARIES_PROPERTY, path); + appendProperty(LIBRARIES_PROPERTY, FilenameUtils.normalize(path)); } /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java index dd046681513..aa5e7a68ee5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/DefaultProjectFileSystem.java @@ -20,9 +20,7 @@ package org.sonar.api.resources; import com.google.common.base.Predicate; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; +import com.google.common.collect.*; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.filefilter.*; @@ -37,9 +35,7 @@ import org.sonar.api.utils.WildcardPattern; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; /** * An implementation of {@link ProjectFileSystem}. @@ -196,7 +192,7 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { return !testFiles(lang.getKey()).isEmpty(); } - private List getFiles(List directories, boolean applyExclusionPatterns, String... langs) { + private List getFiles(List directories, List initialFiles, boolean applyExclusionPatterns, String... langs) { List result = Lists.newArrayList(); if (directories == null) { return result; @@ -205,13 +201,19 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { IOFileFilter suffixFilter = getFileSuffixFilter(langs); WildcardPattern[] exclusionPatterns = getExclusionPatterns(applyExclusionPatterns); + IOFileFilter initialFilesFilter = TrueFileFilter.INSTANCE; + if (initialFiles!=null && !initialFiles.isEmpty()) { + initialFilesFilter = new FileSelectionFilter(initialFiles); + } + for (File dir : directories) { if (dir.exists()) { IOFileFilter exclusionFilter = new ExclusionFilter(dir, exclusionPatterns); IOFileFilter visibleFileFilter = HiddenFileFilter.VISIBLE; - List dirFilters = Lists.newArrayList(visibleFileFilter, suffixFilter, exclusionFilter); - dirFilters.addAll(this.filters); - List files = (List) FileUtils.listFiles(dir, new AndFileFilter(dirFilters), HiddenFileFilter.VISIBLE); + List fileFilters = Lists.newArrayList(visibleFileFilter, suffixFilter, exclusionFilter, initialFilesFilter); + fileFilters.addAll(this.filters); + + List files = (List) FileUtils.listFiles(dir, new AndFileFilter(fileFilters), HiddenFileFilter.VISIBLE); for (File file : files) { String relativePath = DefaultProjectFileSystem.getRelativePath(file, dir); result.add(InputFileUtils.create(dir, relativePath)); @@ -269,6 +271,22 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { } } + static class FileSelectionFilter implements IOFileFilter { + private Set files; + + public FileSelectionFilter(List f) { + files = Sets.newHashSet(f); + } + + public boolean accept(File file) { + return files.contains(file); + } + + public boolean accept(File file, String name) { + return accept(file); + } + } + public File writeToWorkingDirectory(String content, String fileName) throws IOException { return writeToFile(content, getSonarWorkingDirectory(), fileName); } @@ -363,13 +381,21 @@ public class DefaultProjectFileSystem implements ProjectFileSystem { * @since 2.6 */ public List mainFiles(String... langs) { - return getFiles(getSourceDirs(), true, langs); + return getFiles(getSourceDirs(), getInitialSourceFiles(), true, langs); } /** * @since 2.6 */ public List testFiles(String... langs) { - return getFiles(getTestDirs(), false /* FIXME should be true? */, langs); + return getFiles(getTestDirs(), getInitialTestFiles(), false /* FIXME should be true? */, langs); + } + + protected List getInitialSourceFiles() { + return Collections.emptyList(); + } + + protected List getInitialTestFiles() { + return Collections.emptyList(); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java index 49f1e1c916a..9b92b37e880 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java @@ -74,19 +74,29 @@ public class ProjectDefinitionTest { @Test public void shouldAddDirectories() { ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties()); - def.addSourceDir("src/main/java"); - def.addSourceDir("src/main/java2"); - def.addTestDir("src/test/java"); - def.addTestDir("src/test/java2"); + def.addSourceDirs("src/main/java", "src/main/java2"); + def.addTestDirs("src/test/java"); + def.addTestDirs("src/test/java2"); def.addBinaryDir("target/classes"); def.addBinaryDir("target/classes2"); def.addLibrary("junit.jar"); def.addLibrary("mockito.jar"); - assertDirs(def.getSourceDirs(), "src/main/java", "src/main/java2"); - assertDirs(def.getTestDirs(), "src/test/java", "src/test/java2"); - assertDirs(def.getBinaries(), "target/classes", "target/classes2"); - assertDirs(def.getLibraries(), "junit.jar", "mockito.jar"); + assertFiles(def.getSourceDirs(), "src/main/java", "src/main/java2"); + assertFiles(def.getTestDirs(), "src/test/java", "src/test/java2"); + assertFiles(def.getBinaries(), "target/classes", "target/classes2"); + assertFiles(def.getLibraries(), "junit.jar", "mockito.jar"); + } + + @Test + public void shouldAddFiles() { + ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties()); + def.addSourceFiles("src/main/java/foo/Bar.java", "src/main/java/hello/World.java"); + def.addTestFiles("src/test/java/foo/BarTest.java", "src/test/java/hello/WorldTest.java"); + + assertFiles(def.getSourceFiles(), "src/main/java/foo/Bar.java", "src/main/java/hello/World.java"); + assertFiles(def.getTestFiles(), "src/test/java/foo/BarTest.java", "src/test/java/hello/WorldTest.java"); + } @Test @@ -102,10 +112,10 @@ public class ProjectDefinitionTest { assertThat(child.getParent(), is(root)); } - private static void assertDirs(List dirs, String... values) { - assertThat(dirs.size(), is(values.length)); + private static void assertFiles(List paths, String... values) { + assertThat(paths.size(), is(values.length)); for (int i = 0; i < values.length; i++) { - assertThat(dirs.get(i), is(values[i])); + assertThat(paths.get(i), is(values[i])); } } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/resources/DefaultProjectFileSystemTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/resources/DefaultProjectFileSystemTest.java index a867392245b..22731536df3 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/resources/DefaultProjectFileSystemTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/resources/DefaultProjectFileSystemTest.java @@ -32,6 +32,7 @@ import org.apache.commons.lang.SystemUtils; import org.apache.maven.project.MavenProject; import org.hamcrest.Description; import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Test; @@ -39,6 +40,7 @@ import org.sonar.api.batch.FileFilter; import org.sonar.api.test.MavenTestUtils; import java.io.File; +import java.util.Arrays; import java.util.List; public class DefaultProjectFileSystemTest { @@ -205,6 +207,19 @@ public class DefaultProjectFileSystemTest { assertThat(fsWithFilter.getSourceFiles(), not(hasItem(named("Bar.java")))); } + @Test + public void testSelectiveFileFilter() { + DefaultProjectFileSystem.FileSelectionFilter filter = new DefaultProjectFileSystem.FileSelectionFilter( + Arrays.asList(new File("foo/Bar.java"), new File("hello/Bar.java"), new File("hello/World.java"))); + assertThat(filter.accept(new File("foo/Bar.java")), Matchers.is(true)); + assertThat(filter.accept(new File("hello/Bar.java")), Matchers.is(true)); + assertThat(filter.accept(new File("hello/World.java")), Matchers.is(true)); + + assertThat(filter.accept(new File("foo/Unknown.java")), Matchers.is(false)); + assertThat(filter.accept(new File("foo/bar/Bar.java")), Matchers.is(false)); + assertThat(filter.accept(new File("foo/World.java")), Matchers.is(false)); + } + private DefaultProjectFileSystem newDefaultProjectFileSystem(Project project) { return (DefaultProjectFileSystem) project.getFileSystem(); } -- 2.39.5