@@ -20,7 +20,6 @@ | |||
package org.sonar.plugins.core.sensors; | |||
import com.google.common.collect.Maps; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.batch.Sensor; | |||
import org.sonar.api.batch.SensorContext; | |||
import org.sonar.api.resources.Project; | |||
@@ -28,6 +27,7 @@ import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.utils.KeyValueFormat; | |||
import org.sonar.batch.index.ComponentDataCache; | |||
import org.sonar.batch.scan.filesystem.InputFileCache; | |||
import org.sonar.core.DryRunIncompatible; | |||
import org.sonar.core.source.SnapshotDataTypes; | |||
import java.util.Map; | |||
@@ -36,8 +36,10 @@ import java.util.Map; | |||
* This sensor will retrieve hash of each file of the current module and store it in DB | |||
* in order to compare it during next analysis and see if the file was modified. | |||
* This is used by the incremental preview mode. | |||
* | |||
* @since 4.0 | |||
*/ | |||
@DryRunIncompatible | |||
public final class FileHashSensor implements Sensor { | |||
private final InputFileCache fileCache; | |||
@@ -56,10 +58,9 @@ public final class FileHashSensor implements Sensor { | |||
public void analyse(Project project, SensorContext context) { | |||
Map<String, String> map = Maps.newHashMap(); | |||
for (InputFile inputFile : fileCache.byModule(project.key())) { | |||
String baseRelativePath = inputFile.attribute(InputFile.ATTRIBUTE_BASE_RELATIVE_PATH); | |||
String hash = inputFile.attribute(InputFile.ATTRIBUTE_HASH); | |||
if (StringUtils.isNotEmpty(baseRelativePath) && StringUtils.isNotEmpty(hash)) { | |||
map.put(baseRelativePath, hash); | |||
if (hash != null) { | |||
map.put(inputFile.relativePath(), hash); | |||
} | |||
} | |||
if (!map.isEmpty()) { |
@@ -28,6 +28,7 @@ import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.SensorContext; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import org.sonar.batch.index.ComponentDataCache; | |||
import org.sonar.batch.scan.filesystem.InputFileCache; | |||
import org.sonar.core.source.SnapshotDataTypes; | |||
@@ -53,8 +54,8 @@ public class FileHashSensorTest { | |||
@Test | |||
public void store_file_hashes() throws Exception { | |||
when(fileCache.byModule("struts")).thenReturn(Lists.<InputFile>newArrayList( | |||
InputFile.create(temp.newFile(), "src/Foo.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "ABC")), | |||
InputFile.create(temp.newFile(), "src/Bar.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "DEF")) | |||
DefaultInputFile.create(temp.newFile(), "src/Foo.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "ABC")), | |||
DefaultInputFile.create(temp.newFile(), "src/Bar.java", ImmutableMap.of(InputFile.ATTRIBUTE_HASH, "DEF")) | |||
)); | |||
SensorContext sensorContext = mock(SensorContext.class); |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.batch.scan.filesystem; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.InputFileFilter; | |||
@@ -38,4 +39,14 @@ class AttributeFilter implements InputFileFilter { | |||
String value = inputFile.attribute(key); | |||
return values.contains(value); | |||
} | |||
@VisibleForTesting | |||
String key() { | |||
return key; | |||
} | |||
@VisibleForTesting | |||
Collection<String> values() { | |||
return values; | |||
} | |||
} |
@@ -27,8 +27,8 @@ import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.scan.filesystem.FileQuery; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.InputFiles; | |||
import org.sonar.api.scan.filesystem.ModuleFileSystem; | |||
import org.sonar.api.utils.SonarException; | |||
import javax.annotation.CheckForNull; | |||
import java.io.File; | |||
@@ -155,8 +155,8 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { | |||
/** | |||
* @since 4.0 | |||
* TODO move into API | |||
*/ | |||
@Override | |||
public Iterable<InputFile> inputFiles(FileQuery query) { | |||
List<InputFile> result = Lists.newArrayList(); | |||
@@ -172,7 +172,7 @@ public class DefaultModuleFileSystem implements ModuleFileSystem { | |||
@Override | |||
// TODO deprecate | |||
public List<File> files(FileQuery query) { | |||
return InputFile.toFiles(inputFiles(query)); | |||
return InputFiles.toFiles(inputFiles(query)); | |||
} | |||
public void resetDirs(File basedir, File buildDir, List<File> sourceDirs, List<File> testDirs, List<File> binaryDirs) { |
@@ -78,7 +78,7 @@ public class DeprecatedFileFilters implements InputFileFilter { | |||
@Override | |||
public String canonicalPath() { | |||
return inputFile.attribute(InputFile.ATTRIBUTE_CANONICAL_PATH); | |||
return inputFile.path(); | |||
} | |||
} | |||
} |
@@ -33,6 +33,7 @@ import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.InputFileFilter; | |||
import org.sonar.api.scan.filesystem.ModuleFileSystem; | |||
import org.sonar.api.scan.filesystem.PathResolver; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import javax.annotation.Nullable; | |||
import java.io.File; | |||
@@ -63,9 +64,10 @@ public class FileIndexer implements BatchComponent { | |||
this.fileHashes = fileHashes; | |||
} | |||
public void index(ModuleFileSystem fileSystem) { | |||
public void index(DefaultModuleFileSystem fileSystem) { | |||
Logger logger = LoggerFactory.getLogger(FileIndexer.class); | |||
logger.info("Index files"); | |||
// TODO log configuration too (replace FileSystemLogger) | |||
cache.removeModule(fileSystem.moduleKey()); | |||
int count = 0; | |||
@@ -102,7 +104,6 @@ public class FileIndexer implements BatchComponent { | |||
String baseRelativePath = pathResolver.relativePath(fileSystem.baseDir(), file); | |||
set(attributes, InputFile.ATTRIBUTE_SOURCEDIR_PATH, FilenameUtils.normalize(sourceDir.getCanonicalPath(), true)); | |||
set(attributes, InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, pathResolver.relativePath(sourceDir, file)); | |||
set(attributes, InputFile.ATTRIBUTE_CANONICAL_PATH, FilenameUtils.normalize(file.getCanonicalPath(), true)); | |||
// other metadata | |||
set(attributes, InputFile.ATTRIBUTE_TYPE, type); | |||
@@ -111,7 +112,7 @@ public class FileIndexer implements BatchComponent { | |||
set(attributes, InputFile.ATTRIBUTE_LANGUAGE, languageRecognizer.ofExtension(extension)); | |||
initStatus(file, fileSystem.sourceCharset(), baseRelativePath, attributes); | |||
return InputFile.create(file, baseRelativePath, attributes); | |||
return DefaultInputFile.create(file, baseRelativePath, attributes); | |||
} catch (Exception e) { | |||
throw new IllegalStateException("Fail to read file: " + file.getAbsolutePath(), e); |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.batch.scan.filesystem; | |||
import com.google.common.annotations.VisibleForTesting; | |||
import com.google.common.collect.Lists; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Settings; | |||
@@ -56,6 +57,11 @@ class FileQueryFilter { | |||
} | |||
} | |||
@VisibleForTesting | |||
List<InputFileFilter> filters() { | |||
return filters; | |||
} | |||
boolean accept(InputFile inputFile) { | |||
for (InputFileFilter filter : filters) { | |||
if (!filter.accept(inputFile)) { |
@@ -21,6 +21,7 @@ package org.sonar.batch.scan.filesystem; | |||
import com.google.common.collect.Maps; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.picocontainer.Startable; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.resources.Language; | |||
@@ -28,16 +29,26 @@ import javax.annotation.CheckForNull; | |||
import java.util.Map; | |||
/** | |||
* Based on file extensions. | |||
* Detect language of source files. Simplistic, based on file extensions. | |||
*/ | |||
public class LanguageRecognizer implements BatchComponent { | |||
public class LanguageRecognizer implements BatchComponent, Startable { | |||
private final Map<String, String> byExtensions = Maps.newHashMap(); | |||
/** | |||
* Lower-case extension -> language | |||
*/ | |||
private Map<String, String> byExtensions = Maps.newHashMap(); | |||
private final Language[] languages; | |||
public LanguageRecognizer(Language[] languages) { | |||
this.languages = languages; | |||
} | |||
@Override | |||
public void start() { | |||
for (Language language : languages) { | |||
for (String suffix : language.getFileSuffixes()) { | |||
String extension = StringUtils.removeStart(suffix, "."); | |||
String extension = sanitizeExtension(suffix); | |||
String s = byExtensions.get(extension); | |||
if (s != null) { | |||
@@ -50,12 +61,21 @@ public class LanguageRecognizer implements BatchComponent { | |||
} | |||
} | |||
@Override | |||
public void stop() { | |||
// do nothing | |||
} | |||
// TODO what about cobol files without extension ? | |||
@CheckForNull | |||
String ofExtension(String fileExtension) { | |||
if (StringUtils.isNotBlank(fileExtension)) { | |||
return byExtensions.get(fileExtension); | |||
return byExtensions.get(StringUtils.lowerCase(fileExtension)); | |||
} | |||
return null; | |||
} | |||
static String sanitizeExtension(String suffix) { | |||
return StringUtils.lowerCase(StringUtils.removeStart(suffix, ".")); | |||
} | |||
} |
@@ -61,7 +61,7 @@ abstract class PathPattern { | |||
@Override | |||
boolean match(InputFile inputFile) { | |||
return pattern.match(inputFile.attribute(InputFile.ATTRIBUTE_CANONICAL_PATH)); | |||
return pattern.match(inputFile.path()); | |||
} | |||
@Override |
@@ -24,7 +24,7 @@ import com.google.common.collect.Lists; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
@@ -37,9 +37,11 @@ public class AttributeFilterTest { | |||
public void should_check_attribute_value() throws Exception { | |||
AttributeFilter filter = new AttributeFilter("foo", Lists.newArrayList("one", "two")); | |||
assertThat(filter.accept(InputFile.create(temp.newFile(), "Why.java", ImmutableMap.of("foo", "two")))).isTrue(); | |||
assertThat(filter.accept(InputFile.create(temp.newFile(), "Where.java", ImmutableMap.of("foo", "three")))).isFalse(); | |||
assertThat(filter.accept(InputFile.create(temp.newFile(), "What.java", ImmutableMap.of("bar", "one")))).isFalse(); | |||
assertThat(filter.key()).isEqualTo("foo"); | |||
assertThat(filter.values()).containsOnly("one", "two"); | |||
assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), "Why.java", ImmutableMap.of("foo", "two")))).isTrue(); | |||
assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), "Where.java", ImmutableMap.of("foo", "three")))).isFalse(); | |||
assertThat(filter.accept(DefaultInputFile.create(temp.newFile(), "What.java", ImmutableMap.of("bar", "one")))).isFalse(); | |||
} | |||
} |
@@ -29,6 +29,7 @@ import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.scan.filesystem.FileQuery; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import java.io.File; | |||
import java.io.IOException; | |||
@@ -151,8 +152,8 @@ public class DefaultModuleFileSystemTest { | |||
DefaultModuleFileSystem fs = new DefaultModuleFileSystem("foo", settings, fileCache, fileIndexer); | |||
File mainFile = temp.newFile(); | |||
InputFile mainInput = InputFile.create(mainFile, "Main.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE)); | |||
InputFile testInput = InputFile.create(temp.newFile(), "Test.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST)); | |||
InputFile mainInput = DefaultInputFile.create(mainFile, "Main.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE)); | |||
InputFile testInput = DefaultInputFile.create(temp.newFile(), "Test.java", ImmutableMap.of(InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST)); | |||
when(fileCache.byModule("foo")).thenReturn(Lists.newArrayList(mainInput, testInput)); | |||
@@ -28,7 +28,7 @@ import org.mockito.ArgumentCaptor; | |||
import org.sonar.api.scan.filesystem.FileSystemFilter; | |||
import org.sonar.api.scan.filesystem.FileType; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.ModuleFileSystem; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import java.io.File; | |||
@@ -48,7 +48,7 @@ public class DeprecatedFileFiltersTest { | |||
public void no_filters() throws Exception { | |||
DeprecatedFileFilters filters = new DeprecatedFileFilters(); | |||
InputFile inputFile = InputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap()); | |||
InputFile inputFile = DefaultInputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap()); | |||
assertThat(filters.accept(inputFile)).isTrue(); | |||
} | |||
@@ -58,8 +58,7 @@ public class DeprecatedFileFiltersTest { | |||
File basedir = temp.newFolder(); | |||
File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, new File(basedir, "src/main/java/Foo.java").getAbsolutePath(), | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_SOURCEDIR_PATH, new File(basedir, "src/main/java").getAbsolutePath(), | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "Foo.java", | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST | |||
@@ -73,7 +72,7 @@ public class DeprecatedFileFiltersTest { | |||
verify(filter).accept(eq(file), argument.capture()); | |||
DeprecatedFileFilters.DeprecatedContext context = argument.getValue(); | |||
assertThat(context.canonicalPath()).isEqualTo(new File(basedir, "src/main/java/Foo.java").getAbsolutePath()); | |||
assertThat(context.canonicalPath()).isEqualTo(file.getAbsolutePath()); | |||
assertThat(context.relativeDir()).isEqualTo(new File(basedir, "src/main/java")); | |||
assertThat(context.relativePath()).isEqualTo("Foo.java"); | |||
assertThat(context.type()).isEqualTo(FileType.TEST); |
@@ -24,9 +24,9 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
@@ -40,17 +40,16 @@ public class ExclusionFilterTest { | |||
ExclusionFilter sourceRelativeFilter = new ExclusionFilter("**/*Foo.java"); | |||
ExclusionFilter absoluteFilter = new ExclusionFilter("file:**/src/main/**Foo.java"); | |||
File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/MyFoo.java", | |||
File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java" | |||
)); | |||
assertThat(sourceRelativeFilter.accept(inputFile)).isFalse(); | |||
assertThat(absoluteFilter.accept(inputFile)).isFalse(); | |||
inputFile = InputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/Other.java", | |||
file = new File(temp.newFolder(), "src/main/java/org/Other.java"); | |||
inputFile = DefaultInputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java" | |||
)); | |||
assertThat(sourceRelativeFilter.accept(inputFile)).isTrue(); |
@@ -30,6 +30,7 @@ import org.sonar.api.resources.JavaFile; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.api.scan.filesystem.FileExclusions; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import java.io.IOException; | |||
@@ -47,21 +48,21 @@ public class ExclusionFiltersTest { | |||
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings)); | |||
java.io.File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java" | |||
)); | |||
assertThat(filter.accept(inputFile)).isFalse(); | |||
inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java" | |||
)); | |||
assertThat(filter.accept(inputFile)).isTrue(); | |||
// source inclusions do not apply to tests | |||
inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java" | |||
)); | |||
@@ -75,14 +76,14 @@ public class ExclusionFiltersTest { | |||
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings)); | |||
java.io.File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java" | |||
)); | |||
assertThat(filter.accept(inputFile)).isFalse(); | |||
inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDto.java", ImmutableMap.of( | |||
inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/FooDto.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDto.java" | |||
)); | |||
@@ -96,20 +97,20 @@ public class ExclusionFiltersTest { | |||
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings)); | |||
java.io.File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java" | |||
)); | |||
assertThat(filter.accept(inputFile)).isFalse(); | |||
inputFile = InputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/Foo.java" | |||
)); | |||
assertThat(filter.accept(inputFile)).isTrue(); | |||
// source exclusions do not apply to tests | |||
inputFile = InputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
inputFile = DefaultInputFile.create(file, "src/main/java/com/mycompany/FooDao.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_TEST, | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "com/mycompany/FooDao.java" | |||
)); | |||
@@ -125,15 +126,13 @@ public class ExclusionFiltersTest { | |||
settings.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "file:" + excludedFile.getCanonicalPath()); | |||
ExclusionFilters filter = new ExclusionFilters(new FileExclusions(settings)); | |||
InputFile includedInput = InputFile.create(includedFile, "src/main/java/org/bar/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, includedFile.getCanonicalPath() | |||
InputFile includedInput = DefaultInputFile.create(includedFile, "src/main/java/org/bar/Foo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE | |||
)); | |||
assertThat(filter.accept(includedInput)).isTrue(); | |||
InputFile excludedInput = InputFile.create(excludedFile, "src/main/java/org/bar/Bar.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE, | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, excludedFile.getCanonicalPath() | |||
InputFile excludedInput = DefaultInputFile.create(excludedFile, "src/main/java/org/bar/Bar.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_TYPE, InputFile.TYPE_SOURCE | |||
)); | |||
assertThat(filter.accept(excludedInput)).isFalse(); | |||
} |
@@ -0,0 +1,101 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.filesystem; | |||
import org.junit.Test; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.scan.filesystem.FileQuery; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.InputFileFilter; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public class FileQueryFilterTest { | |||
Settings settings = new Settings(); | |||
@Test | |||
public void wrap_query_on_attributes() throws Exception { | |||
FileQuery query = FileQuery.onSource(); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).hasSize(1); | |||
InputFileFilter typeFilter = filter.filters().get(0); | |||
assertThat(typeFilter).isInstanceOf(AttributeFilter.class); | |||
assertThat(((AttributeFilter) typeFilter).key()).isEqualTo(InputFile.ATTRIBUTE_TYPE); | |||
assertThat(((AttributeFilter) typeFilter).values()).containsOnly(InputFile.TYPE_SOURCE); | |||
} | |||
@Test | |||
public void wrap_query_on_inclusions() throws Exception { | |||
FileQuery query = FileQuery.on().withInclusions("Foo*.java"); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).hasSize(1); | |||
InputFileFilter inclusionFilter = filter.filters().get(0); | |||
assertThat(inclusionFilter).isInstanceOf(InclusionFilter.class); | |||
assertThat(inclusionFilter.toString()).isEqualTo("Includes: Foo*.java"); | |||
} | |||
@Test | |||
public void wrap_query_on_exclusions() throws Exception { | |||
FileQuery query = FileQuery.on().withExclusions("Foo*.java"); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).hasSize(1); | |||
InputFileFilter exclusionFilter = filter.filters().get(0); | |||
assertThat(exclusionFilter).isInstanceOf(ExclusionFilter.class); | |||
assertThat(exclusionFilter.toString()).isEqualTo("Excludes: Foo*.java"); | |||
} | |||
@Test | |||
public void all_files_by_default() throws Exception { | |||
FileQuery query = FileQuery.on(); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).isEmpty(); | |||
} | |||
@Test | |||
public void only_changed_files_by_default_if_incremental_mode() throws Exception { | |||
settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); | |||
FileQuery query = FileQuery.on(); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).hasSize(1); | |||
AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); | |||
assertThat(statusFilter.key()).isEqualTo(InputFile.ATTRIBUTE_STATUS); | |||
assertThat(statusFilter.values()).containsOnly(InputFile.STATUS_ADDED, InputFile.STATUS_CHANGED); | |||
} | |||
@Test | |||
public void get_all_files_even_if_incremental_mode() throws Exception { | |||
settings.setProperty(CoreProperties.INCREMENTAL_PREVIEW, true); | |||
FileQuery query = FileQuery.on().on(InputFile.ATTRIBUTE_STATUS, InputFile.STATUS_SAME); | |||
FileQueryFilter filter = new FileQueryFilter(settings, query); | |||
assertThat(filter.filters()).hasSize(1); | |||
AttributeFilter statusFilter = (AttributeFilter) filter.filters().get(0); | |||
assertThat(statusFilter.key()).isEqualTo(InputFile.ATTRIBUTE_STATUS); | |||
assertThat(statusFilter.values()).containsOnly(InputFile.STATUS_SAME); | |||
} | |||
} |
@@ -24,6 +24,7 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import java.io.File; | |||
@@ -38,18 +39,16 @@ public class InclusionFilterTest { | |||
InclusionFilter sourceRelativeFilter = new InclusionFilter("**/*Foo.java"); | |||
InclusionFilter absoluteFilter = new InclusionFilter("file:**/src/main/**Foo.java"); | |||
File file = temp.newFile(); | |||
InputFile inputFile = InputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/MyFoo.java", | |||
File file = new File(temp.newFolder(), "src/main/java/org/MyFoo.java"); | |||
InputFile inputFile = DefaultInputFile.create(file, "src/main/java/org/MyFoo.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/MyFoo.java" | |||
)); | |||
assertThat(sourceRelativeFilter.accept(inputFile)).isTrue(); | |||
assertThat(absoluteFilter.accept(inputFile)).isTrue(); | |||
inputFile = InputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_CANONICAL_PATH, "/absolute/path/to/src/main/java/org/Other.java", | |||
file = new File(temp.newFolder(), "src/main/java/org/Other.java"); | |||
inputFile = DefaultInputFile.create(file, "src/main/java/org/Other.java", ImmutableMap.of( | |||
InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "org/Other.java" | |||
)); | |||
assertThat(sourceRelativeFilter.accept(inputFile)).isFalse(); |
@@ -25,7 +25,7 @@ import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import org.sonar.api.scan.filesystem.internal.DefaultInputFile; | |||
import org.sonar.batch.index.Caches; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
@@ -50,8 +50,8 @@ public class InputFileCacheTest { | |||
@Test | |||
public void should_add_input_file() throws Exception { | |||
InputFileCache cache = new InputFileCache(caches); | |||
cache.put("struts", InputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap())); | |||
cache.put("struts-core", InputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap())); | |||
cache.put("struts", DefaultInputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap())); | |||
cache.put("struts-core", DefaultInputFile.create(temp.newFile(), "src/main/java/Foo.java", Maps.<String, String>newHashMap())); | |||
assertThat(cache.byModule("struts")).hasSize(1); | |||
assertThat(cache.byModule("struts-core")).hasSize(1); |
@@ -0,0 +1,97 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.batch.scan.filesystem; | |||
import org.junit.Test; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.resources.Language; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
import static org.fest.assertions.Fail.fail; | |||
public class LanguageRecognizerTest { | |||
@Test | |||
public void test_sanitizeExtension() throws Exception { | |||
assertThat(LanguageRecognizer.sanitizeExtension(".cbl")).isEqualTo("cbl"); | |||
assertThat(LanguageRecognizer.sanitizeExtension(".CBL")).isEqualTo("cbl"); | |||
assertThat(LanguageRecognizer.sanitizeExtension("CBL")).isEqualTo("cbl"); | |||
assertThat(LanguageRecognizer.sanitizeExtension("cbl")).isEqualTo("cbl"); | |||
} | |||
@Test | |||
public void search_by_file_extension() throws Exception { | |||
Language[] languages = new Language[]{Java.INSTANCE, new Cobol()}; | |||
LanguageRecognizer recognizer = new LanguageRecognizer(languages); | |||
recognizer.start(); | |||
assertThat(recognizer.ofExtension("java")).isEqualTo(Java.KEY); | |||
assertThat(recognizer.ofExtension("cbl")).isEqualTo("cobol"); | |||
assertThat(recognizer.ofExtension("CBL")).isEqualTo("cobol"); | |||
assertThat(recognizer.ofExtension("php")).isNull(); | |||
assertThat(recognizer.ofExtension("")).isNull(); | |||
assertThat(recognizer.ofExtension(null)).isNull(); | |||
recognizer.stop(); | |||
} | |||
@Test | |||
public void fail_if_conflict_of_file_extensions() throws Exception { | |||
Language[] languages = new Language[]{Java.INSTANCE, new Language() { | |||
@Override | |||
public String getKey() { | |||
return "java2"; | |||
} | |||
@Override | |||
public String getName() { | |||
return "Java2"; | |||
} | |||
@Override | |||
public String[] getFileSuffixes() { | |||
return new String[]{"java2", "java"}; | |||
} | |||
}}; | |||
try { | |||
new LanguageRecognizer(languages).start(); | |||
fail(); | |||
} catch (IllegalStateException e) { | |||
assertThat(e.getMessage()).isEqualTo("File extension 'java' is declared by two languages: java and java2"); | |||
} | |||
} | |||
static class Cobol implements Language { | |||
@Override | |||
public String getKey() { | |||
return "cobol"; | |||
} | |||
@Override | |||
public String getName() { | |||
return "Cobol"; | |||
} | |||
@Override | |||
public String[] getFileSuffixes() { | |||
return new String[]{"cbl", "cob"}; | |||
} | |||
} | |||
} |
@@ -37,7 +37,7 @@ import java.util.Set; | |||
*/ | |||
public class FileQuery { | |||
// TODO better builders, for example FileQuery.ALL | |||
// TODO REFACTOR - better builders, for example FileQuery.ALL | |||
public static FileQuery on(FileType... types) { | |||
FileQuery query = new FileQuery(); | |||
@@ -62,7 +62,7 @@ public class FileQuery { | |||
private FileQuery() { | |||
} | |||
private FileQuery on(String attribute, String... values) { | |||
public FileQuery on(String attribute, String... values) { | |||
for (String value : values) { | |||
attributes.put(attribute, value); | |||
} |
@@ -21,7 +21,7 @@ package org.sonar.api.scan.filesystem; | |||
/** | |||
* @since 3.5 | |||
* @deprecated in 4.0. Replaced by more flexible {@link InputFile} attributes. | |||
* @deprecated in 4.0. Replaced by more flexible {@link org.sonar.api.scan.filesystem.InputFile} attributes. | |||
*/ | |||
@Deprecated | |||
public enum FileType { |
@@ -1,141 +1,94 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem; | |||
import com.google.common.collect.Lists; | |||
import com.google.common.collect.Maps; | |||
import org.apache.commons.lang.StringUtils; | |||
import javax.annotation.CheckForNull; | |||
import java.io.File; | |||
import java.io.Serializable; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* @since 4.0 | |||
*/ | |||
public class InputFile implements Serializable { | |||
public interface InputFile extends Serializable { | |||
/** | |||
* Canonical path of source directory. | |||
* Example: <code>/path/to/module/src/main/java</code> or <code>C:\path\to\module\src\main\java</code> | |||
*/ | |||
String ATTRIBUTE_SOURCEDIR_PATH = "srcDirPath"; | |||
// TODO refactor attribute constants as classes or enums ? | |||
/** | |||
* Relative path from source directory. File separator is the forward slash ('/'), | |||
* even on MSWindows. | |||
*/ | |||
String ATTRIBUTE_SOURCE_RELATIVE_PATH = "srcRelPath"; | |||
/** | |||
* Path relative to module base directory. | |||
* Detected language | |||
*/ | |||
public static final String ATTRIBUTE_BASE_RELATIVE_PATH = "baseRelPath"; | |||
// TODO ambiguity of term "source" with sourceDir versus testDir properties | |||
// Here it does not depend on type. | |||
public static final String ATTRIBUTE_SOURCEDIR_PATH = "srcDirPath"; | |||
public static final String ATTRIBUTE_SOURCE_RELATIVE_PATH = "srcRelPath"; | |||
public static final String ATTRIBUTE_CANONICAL_PATH = "canonicalPath"; | |||
public static final String ATTRIBUTE_LANGUAGE = "lang"; | |||
public static final String ATTRIBUTE_TYPE = "type"; | |||
public static final String ATTRIBUTE_STATUS = "status"; | |||
public static final String STATUS_SAME = "same"; | |||
public static final String STATUS_CHANGED = "changed"; | |||
public static final String STATUS_ADDED = "added"; | |||
public static final String ATTRIBUTE_HASH = "checksum"; | |||
public static final String ATTRIBUTE_EXTENSION = "extension"; | |||
public static final String TYPE_SOURCE = "source"; | |||
public static final String TYPE_TEST = "test"; | |||
// TODO limitation of persistit -> add unit test | |||
private transient File transientFile; | |||
private Map<String, String> attributes; | |||
private InputFile(File file, Map<String, String> attributes) { | |||
this.transientFile = file; | |||
this.attributes = attributes; | |||
} | |||
String ATTRIBUTE_LANGUAGE = "lang"; | |||
/** | |||
* Plugins should not build their own instances of {@link InputFile}. This method | |||
* aims to be used by unit tests. | |||
* // TODO provide builder ? | |||
* | |||
*/ | |||
public static InputFile create(File file, String baseRelativePath, Map<String, String> attributes) { | |||
Map<String,String> copy = new HashMap<String, String>(attributes); | |||
copy.put(InputFile.ATTRIBUTE_BASE_RELATIVE_PATH, baseRelativePath); | |||
return new InputFile(file, copy); | |||
} | |||
String ATTRIBUTE_TYPE = "type"; | |||
String TYPE_SOURCE = "source"; | |||
String TYPE_TEST = "test"; | |||
String ATTRIBUTE_STATUS = "status"; | |||
String STATUS_SAME = "same"; | |||
String STATUS_CHANGED = "changed"; | |||
String STATUS_ADDED = "added"; | |||
String ATTRIBUTE_HASH = "hash"; | |||
String ATTRIBUTE_EXTENSION = "extension"; | |||
/** | |||
* Path from module base directory. Path is unique and identifies file within given | |||
* <code>{@link ModuleFileSystem}</code>. File separator is the forward slash ('/'), | |||
* <code>{@link org.sonar.api.scan.filesystem.ModuleFileSystem}</code>. File separator is the forward slash ('/'), | |||
* even on MSWindows. | |||
* <p/> | |||
* If: | |||
* <ul> | |||
* <li>Module base dir is <code>/absolute/path/to/module</code></li> | |||
* <li>File is <code>/absolute/path/to/module/src/main/java/com/Foo.java</code></li> | |||
* </ul> | |||
* then the path is <code>src/main/java/com/Foo.java</code> | |||
* <p/> | |||
* On MSWindows, if: | |||
* <ul> | |||
* <li>Module base dir is <code>C:\absolute\path\to\module</code></li> | |||
* <li>File is <code>C:\absolute\path\to\module\src\main\java\com\Foo.java</code></li> | |||
* </ul> | |||
* then the path is <code>src/main/java/com/Foo.java</code>. | |||
* <p/> | |||
* Returned relative path is never null. | |||
*/ | |||
public String path() { | |||
return attribute(ATTRIBUTE_BASE_RELATIVE_PATH); | |||
} | |||
String relativePath(); | |||
public File file() { | |||
if (transientFile == null) { | |||
transientFile = new File(attribute(ATTRIBUTE_CANONICAL_PATH)); | |||
} | |||
return transientFile; | |||
} | |||
/** | |||
* Canonical path. | |||
*/ | |||
String path(); | |||
public String name() { | |||
return file().getName(); | |||
} | |||
/** | |||
* Not-null related {@link java.io.File} | |||
*/ | |||
File file(); | |||
public boolean has(String attribute, String value) { | |||
return StringUtils.equals(attributes.get(attribute), value); | |||
} | |||
/** | |||
* Not-null filename, including extension | |||
*/ | |||
@CheckForNull | |||
public String attribute(String key) { | |||
return attributes.get(key); | |||
} | |||
public Map<String, String> attributes() { | |||
return attributes; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
InputFile inputFile = (InputFile) o; | |||
return attribute(ATTRIBUTE_CANONICAL_PATH).equals(inputFile.attribute(ATTRIBUTE_CANONICAL_PATH)); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return path().hashCode(); | |||
} | |||
public static List<File> toFiles(Iterable<InputFile> inputFiles) { | |||
List<File> files = Lists.newArrayList(); | |||
for (InputFile inputFile : inputFiles) { | |||
files.add(inputFile.file()); | |||
} | |||
return files; | |||
} | |||
String name(); | |||
/** | |||
* Does the given attribute have the given value ? | |||
*/ | |||
boolean has(String attribute, String value); | |||
/** | |||
* See list of attribute keys in constants starting with ATTRIBUTE_. | |||
*/ | |||
@CheckForNull | |||
String attribute(String key); | |||
Map<String, String> attributes(); | |||
} |
@@ -23,6 +23,7 @@ import org.sonar.api.BatchExtension; | |||
/** | |||
* TODO document lifecycle -> executed when initializing project | |||
* | |||
* @since 4.0 | |||
*/ | |||
public interface InputFileFilter extends BatchExtension { |
@@ -0,0 +1,42 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem; | |||
import com.google.common.collect.Lists; | |||
import java.io.File; | |||
import java.util.List; | |||
/** | |||
* @since 4.0 | |||
*/ | |||
public class InputFiles { | |||
InputFiles() { | |||
// static methods only | |||
} | |||
public static List<File> toFiles(Iterable<InputFile> inputFiles) { | |||
List<File> files = Lists.newArrayList(); | |||
for (InputFile inputFile : inputFiles) { | |||
files.add(inputFile.file()); | |||
} | |||
return files; | |||
} | |||
} |
@@ -20,7 +20,6 @@ | |||
package org.sonar.api.scan.filesystem; | |||
import org.sonar.api.BatchComponent; | |||
import org.sonar.api.resources.InputFile; | |||
import javax.annotation.CheckForNull; | |||
import java.io.File; | |||
@@ -81,6 +80,11 @@ public interface ModuleFileSystem extends BatchComponent { | |||
*/ | |||
List<File> files(FileQuery query); | |||
/** | |||
* @since 4.0 | |||
*/ | |||
Iterable<InputFile> inputFiles(FileQuery query); | |||
/** | |||
* Charset of source and test files. If it's not defined, then return the platform default charset. | |||
*/ |
@@ -0,0 +1,114 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem.internal; | |||
import org.apache.commons.io.FilenameUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import javax.annotation.CheckForNull; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Map; | |||
/** | |||
* PLUGINS MUST NOT USE THIS CLASS. | |||
* | |||
* @since 4.0 | |||
*/ | |||
public class DefaultInputFile implements InputFile { | |||
private final String path; | |||
private final String relativePath; | |||
private final Map<String, String> attributes; | |||
private DefaultInputFile(File file, String relativePath, Map<String, String> attributes) { | |||
try { | |||
this.path = file.getCanonicalPath(); | |||
this.relativePath = FilenameUtils.separatorsToUnix(relativePath); | |||
this.attributes = attributes; | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to get canonical path of: " + file, e); | |||
} | |||
} | |||
/** | |||
* Plugins must not build their own instances of {@link InputFile}. | |||
* {@link org.sonar.api.scan.filesystem.ModuleFileSystem} must be used to search for files to scan. | |||
* <p/> | |||
* Usage: <code>InputFile.create(file, "src/main/java/com/Foo.java", attributes)</code> | |||
*/ | |||
public static DefaultInputFile create(File file, String relativePath, Map<String, String> attributes) { | |||
return new DefaultInputFile(file, relativePath, attributes); | |||
} | |||
@Override | |||
public String relativePath() { | |||
return relativePath; | |||
} | |||
@Override | |||
public String path() { | |||
return path; | |||
} | |||
@Override | |||
public File file() { | |||
return new File(path); | |||
} | |||
@Override | |||
public String name() { | |||
return file().getName(); | |||
} | |||
@Override | |||
public boolean has(String attribute, String value) { | |||
return StringUtils.equals(attributes.get(attribute), value); | |||
} | |||
@Override | |||
@CheckForNull | |||
public String attribute(String key) { | |||
return attributes.get(key); | |||
} | |||
@Override | |||
public Map<String, String> attributes() { | |||
return attributes; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
DefaultInputFile other = (DefaultInputFile) o; | |||
return path.equals(other.path); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return path.hashCode(); | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem.internal; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import javax.annotation.Nullable; | |||
import java.io.File; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* FOR UNIT-TESTING ONLY | |||
* | |||
* @since 4.0 | |||
*/ | |||
public class InputFileBuilder { | |||
private final Map<String, String> attributes = new HashMap<String, String>(); | |||
private final File file; | |||
private final String relativePath; | |||
public static void _FOR_UNIT_TESTING_ONLY_() { | |||
// For those who don't read javadoc | |||
} | |||
public InputFileBuilder(File file, String relativePath) { | |||
this.file = file; | |||
this.relativePath = relativePath; | |||
} | |||
public InputFileBuilder attribute(String key, @Nullable String value) { | |||
if (value != null) { | |||
attributes.put(key, value); | |||
} | |||
return this; | |||
} | |||
public InputFileBuilder type(@Nullable String type) { | |||
return attribute(InputFile.ATTRIBUTE_TYPE, type); | |||
} | |||
public InputFileBuilder extension(@Nullable String extension) { | |||
return attribute(InputFile.ATTRIBUTE_EXTENSION, extension); | |||
} | |||
public InputFileBuilder language(@Nullable String language) { | |||
return attribute(InputFile.ATTRIBUTE_LANGUAGE, language); | |||
} | |||
public InputFileBuilder hash(@Nullable String hash) { | |||
return attribute(InputFile.ATTRIBUTE_HASH, hash); | |||
} | |||
public InputFileBuilder status(@Nullable String status) { | |||
return attribute(InputFile.ATTRIBUTE_STATUS, status); | |||
} | |||
public InputFileBuilder sourceDir(File dir) { | |||
return sourceDir(dir.getAbsolutePath()); | |||
} | |||
public InputFileBuilder sourceDir(@Nullable String path) { | |||
return attribute(InputFile.ATTRIBUTE_SOURCEDIR_PATH, path); | |||
} | |||
public DefaultInputFile build() { | |||
return DefaultInputFile.create(file, relativePath, attributes); | |||
} | |||
} |
@@ -0,0 +1,23 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
@ParametersAreNonnullByDefault | |||
package org.sonar.api.scan.filesystem.internal; | |||
import javax.annotation.ParametersAreNonnullByDefault; |
@@ -0,0 +1,46 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem; | |||
import com.google.common.collect.Lists; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.internal.InputFileBuilder; | |||
import java.io.File; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public class InputFilesTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Test | |||
public void test_toFiles() throws Exception { | |||
File file1 = temp.newFile(); | |||
File file2 = temp.newFile(); | |||
InputFile input1 = new InputFileBuilder(file1, "src/main/java/Foo.java").build(); | |||
InputFile input2 = new InputFileBuilder(file2, "src/main/java/Bar.java").build(); | |||
assertThat(InputFiles.toFiles(Lists.newArrayList(input1, input2))).containsOnly(file1, file2); | |||
} | |||
} |
@@ -1,96 +0,0 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem; | |||
import com.google.common.collect.Lists; | |||
import org.apache.commons.lang.CharEncoding; | |||
import java.io.File; | |||
import java.nio.charset.Charset; | |||
import java.util.Collections; | |||
import java.util.List; | |||
/** | |||
* @since 3.5 | |||
*/ | |||
public class SimpleModuleFileSystem implements ModuleFileSystem { | |||
private File baseDir; | |||
private File buildDir; | |||
private List<File> sourceDirs = Lists.newArrayList(); | |||
private List<File> testDirs = Lists.newArrayList(); | |||
private List<File> binaryDirs = Lists.newArrayList(); | |||
public SimpleModuleFileSystem(File baseDir) { | |||
this.baseDir = baseDir; | |||
this.buildDir = new File(baseDir, "build"); | |||
} | |||
@Override | |||
public String moduleKey() { | |||
return null; | |||
} | |||
public File baseDir() { | |||
return baseDir; | |||
} | |||
public File buildDir() { | |||
return buildDir; | |||
} | |||
public List<File> sourceDirs() { | |||
return sourceDirs; | |||
} | |||
public List<File> testDirs() { | |||
return testDirs; | |||
} | |||
public List<File> binaryDirs() { | |||
return binaryDirs; | |||
} | |||
public SimpleModuleFileSystem addSourceDir(File d) { | |||
sourceDirs.add(d); | |||
return this; | |||
} | |||
public SimpleModuleFileSystem addTestDir(File d) { | |||
testDirs.add(d); | |||
return this; | |||
} | |||
public SimpleModuleFileSystem addBinaryDir(File d) { | |||
binaryDirs.add(d); | |||
return this; | |||
} | |||
public List<File> files(FileQuery query) { | |||
return Collections.emptyList(); | |||
} | |||
public Charset sourceCharset() { | |||
return Charset.forName(CharEncoding.UTF_8); | |||
} | |||
public File workingDir() { | |||
return new File(baseDir, "work"); | |||
} | |||
} |
@@ -0,0 +1,92 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem.internal; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.scan.filesystem.InputFile; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import static org.fest.assertions.Assertions.assertThat; | |||
public class DefaultInputFileTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
@Test | |||
public void test_attributes() throws IOException { | |||
File file = temp.newFile(); | |||
InputFile input = new InputFileBuilder(file, "src/main/java/Foo.java") | |||
.attribute("foo", "bar") | |||
.type(InputFile.TYPE_TEST) | |||
.extension("jav") | |||
.hash("ABC") | |||
.status(InputFile.STATUS_ADDED) | |||
.language("java") | |||
.build(); | |||
assertThat(input.attributes()).hasSize(6); | |||
assertThat(input.attribute("unknown")).isNull(); | |||
assertThat(input.attribute("foo")).isEqualTo("bar"); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_TYPE)).isEqualTo(InputFile.TYPE_TEST); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_EXTENSION)).isEqualTo("jav"); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_HASH)).isEqualTo("ABC"); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_LANGUAGE)).isEqualTo("java"); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_STATUS)).isEqualTo(InputFile.STATUS_ADDED); | |||
assertThat(input.has(InputFile.ATTRIBUTE_LANGUAGE, "java")).isTrue(); | |||
assertThat(input.has(InputFile.ATTRIBUTE_LANGUAGE, "php")).isFalse(); | |||
assertThat(input.has("unknown", "xxx")).isFalse(); | |||
} | |||
@Test | |||
public void test_file() throws Exception { | |||
File sourceDir = temp.newFolder(); | |||
File file = temp.newFile("Foo.java"); | |||
InputFile input = new InputFileBuilder(file, "src/main/java/Foo.java") | |||
.sourceDir(sourceDir) | |||
.build(); | |||
assertThat(input.name()).isEqualTo("Foo.java"); | |||
assertThat(input.file()).isEqualTo(file); | |||
assertThat(input.attribute(InputFile.ATTRIBUTE_SOURCEDIR_PATH)).isEqualTo(sourceDir.getAbsolutePath()); | |||
assertThat(input.relativePath()).isEqualTo("src/main/java/Foo.java"); | |||
assertThat(input.path()).isEqualTo(file.getCanonicalPath()); | |||
} | |||
@Test | |||
public void test_equals_and_hashCode() throws Exception { | |||
File file1 = temp.newFile(); | |||
InputFile input1 = new InputFileBuilder(file1, "src/main/java/Foo.java").build(); | |||
InputFile input1a = new InputFileBuilder(file1, "src/main/java/Foo.java").build(); | |||
InputFile input2 = new InputFileBuilder(temp.newFile(), "src/main/java/Bar.java").build(); | |||
assertThat(input1.equals(input1)).isTrue(); | |||
assertThat(input1.equals(input1a)).isTrue(); | |||
assertThat(input1.equals(input2)).isFalse(); | |||
assertThat(input1.hashCode()).isEqualTo(input1.hashCode()); | |||
assertThat(input1.hashCode()).isEqualTo(input1a.hashCode()); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube, open source software quality management tool. | |||
* Copyright (C) 2008-2013 SonarSource | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* SonarQube 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 3 of the License, or (at your option) any later version. | |||
* | |||
* SonarQube 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.api.scan.filesystem.internal; | |||
import org.junit.Test; | |||
public class InputFileBuilderTest { | |||
@Test | |||
public void just_for_coverage() throws Exception { | |||
InputFileBuilder._FOR_UNIT_TESTING_ONLY_(); | |||
// do not fail | |||
} | |||
} |