summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-01-29 23:22:42 +0100
committerJulien HENRY <julien.henry@sonarsource.com>2014-01-29 23:31:56 +0100
commit0058d50600159ab128bb3c45d0b7438d20954109 (patch)
tree0de2f8fe6d0aa15bf6f0c88676274f8e475b16f1
parent7e627194938dfcba2c5ff60beb92a26e4a92ea7c (diff)
downloadsonarqube-0058d50600159ab128bb3c45d0b7438d20954109.tar.gz
sonarqube-0058d50600159ab128bb3c45d0b7438d20954109.zip
SONAR-5031 Provide line count as attribute of InputFile
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java29
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java51
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java5
3 files changed, 53 insertions, 32 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
index ad0064f565c..45224104444 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java
@@ -19,9 +19,7 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
-
-import org.sonar.api.scan.filesystem.InputFile;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.io.Files;
import org.apache.commons.lang.StringUtils;
@@ -37,6 +35,8 @@ import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.scan.filesystem.FileQuery;
+import org.sonar.api.scan.filesystem.InputFile;
+import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.index.ResourceKeyMigration;
import org.sonar.batch.scan.language.DefaultModuleLanguages;
@@ -57,9 +57,10 @@ public class ComponentIndexer implements BatchComponent {
private final Project module;
private final DefaultModuleLanguages moduleLanguages;
private final ResourceDao resourceDao;
+ private InputFileCache fileCache;
public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, Settings settings, ResourceKeyMigration migration,
- DefaultModuleLanguages moduleLanguages, ResourceDao resourceDao) {
+ DefaultModuleLanguages moduleLanguages, ResourceDao resourceDao, InputFileCache fileCache) {
this.module = module;
this.languages = languages;
this.sonarIndex = sonarIndex;
@@ -67,10 +68,11 @@ public class ComponentIndexer implements BatchComponent {
this.migration = migration;
this.moduleLanguages = moduleLanguages;
this.resourceDao = resourceDao;
+ this.fileCache = fileCache;
}
public void execute(DefaultModuleFileSystem fs) {
- boolean importSource = settings.getBoolean(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY);
+ boolean shouldImportSource = settings.getBoolean(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY);
Iterable<InputFile> inputFiles = fs.inputFiles(FileQuery.all());
migration.migrateIfNeeded(module, inputFiles);
for (InputFile inputFile : inputFiles) {
@@ -85,21 +87,28 @@ public class ComponentIndexer implements BatchComponent {
if (sonarFile != null) {
moduleLanguages.addLanguage(languageKey);
sonarIndex.index(sonarFile);
- if (importSource) {
- importSources(inputFile, sonarFile);
- }
+ importSources(shouldImportSource, inputFile, sonarFile);
}
}
updateModuleLanguage();
}
- private void importSources(InputFile inputFile, Resource sonarFile) {
+ @VisibleForTesting
+ void importSources(boolean shouldImportSource, InputFile inputFile, Resource sonarFile) {
try {
+ // TODO this part deserve optimization.
+ // No need to read full content in memory when shouldImportSource=false
+ // We should try to remove BOM and count lines in a single pass
String source = Files.toString(inputFile.file(), inputFile.encoding());
// SONAR-3860 Remove BOM character from source
source = CharMatcher.anyOf("\uFEFF").removeFrom(source);
- sonarIndex.setSource(sonarFile, source);
+ String[] lines = source.split("(\r)?\n|\r", -1);
+ inputFile.attributes().put(InputFile.ATTRIBUTE_LINE_COUNT, String.valueOf(lines.length));
+ fileCache.put(module.getKey(), inputFile);
+ if (shouldImportSource) {
+ sonarIndex.setSource(sonarFile, source);
+ }
} catch (Exception e) {
throw new SonarException("Unable to read and import the source file : '" + inputFile.absolutePath() + "' with the charset : '"
+ inputFile.encoding() + "'.", e);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
index c0945f0f570..69c01e7ffab 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java
@@ -19,8 +19,6 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.sonar.api.scan.filesystem.InputFile;
-
import com.google.common.base.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.CharEncoding;
@@ -41,6 +39,7 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.api.scan.filesystem.FileQuery;
+import org.sonar.api.scan.filesystem.InputFile;
import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
import org.sonar.api.scan.filesystem.internal.InputFileBuilder;
import org.sonar.batch.index.ResourceKeyMigration;
@@ -52,6 +51,7 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
+import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -96,10 +96,9 @@ public class ComponentIndexerTest {
newInputFile("src/main/java/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false),
newInputFile("src/main/java2/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false),
newInputFile("src/test/java/foo/bar/FooTest.java", "", "foo/bar/FooTest.java", "java", true)));
- when(project.getLanguageKey()).thenReturn(Java.KEY);
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
- mock(ResourceDao.class));
+ mock(ResourceDao.class), mock(InputFileCache.class));
indexer.execute(fs);
verify(sonarIndex).index(JavaFile.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", false));
@@ -121,11 +120,10 @@ public class ComponentIndexerTest {
newInputFile("src/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false),
newInputFile("src2/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false),
newInputFile("src/test/foo/bar/FooTest.cbl", "", "foo/bar/FooTest.cbl", "cobol", true)));
- when(project.getLanguageKey()).thenReturn("cobol");
Languages languages = new Languages(cobolLanguage);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
- mock(ResourceDao.class));
+ mock(ResourceDao.class), mock(InputFileCache.class));
indexer.execute(fs);
verify(sonarIndex).index(org.sonar.api.resources.File.create("/src/foo/bar/Foo.cbl", "foo/bar/Foo.cbl", cobolLanguage, false));
@@ -139,10 +137,9 @@ public class ComponentIndexerTest {
when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(
newInputFile("src/main/java/foo/bar/Foo.java", "sample code", "foo/bar/Foo.java", "java", false)));
- when(project.getLanguageKey()).thenReturn(Java.KEY);
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
- mock(ResourceDao.class));
+ mock(ResourceDao.class), mock(InputFileCache.class));
indexer.execute(fs);
Resource sonarFile = JavaFile.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", false);
@@ -150,16 +147,6 @@ public class ComponentIndexerTest {
verify(sonarIndex).setSource(sonarFile, "sample code");
}
- private DefaultInputFile newInputFile(String path, String content, String sourceRelativePath, String languageKey, boolean unitTest) throws IOException {
- File file = new File(baseDir, path);
- FileUtils.write(file, content);
- return new InputFileBuilder(file, Charsets.UTF_8, path)
- .attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, sourceRelativePath)
- .attribute(InputFile.ATTRIBUTE_LANGUAGE, languageKey)
- .attribute(InputFile.ATTRIBUTE_TYPE, unitTest ? InputFile.TYPE_TEST : InputFile.TYPE_MAIN)
- .build();
- }
-
@Test
public void should_use_mac_roman_charset_for_reading_source_files() throws Exception {
String encoding = "MacRoman";
@@ -192,10 +179,9 @@ public class ComponentIndexerTest {
.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "foo/bar/Foo.java")
.attribute(InputFile.ATTRIBUTE_LANGUAGE, "java")
.build()));
- when(project.getLanguageKey()).thenReturn(Java.KEY);
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
- mock(ResourceDao.class));
+ mock(ResourceDao.class), mock(InputFileCache.class));
indexer.execute(fs);
Resource sonarFile = JavaFile.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", false);
@@ -221,10 +207,9 @@ public class ComponentIndexerTest {
.attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, "foo/bar/Foo.java")
.attribute(InputFile.ATTRIBUTE_LANGUAGE, "java")
.build()));
- when(project.getLanguageKey()).thenReturn(Java.KEY);
Languages languages = new Languages(Java.INSTANCE);
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
- mock(ResourceDao.class));
+ mock(ResourceDao.class), mock(InputFileCache.class));
indexer.execute(fs);
Resource sonarFile = JavaFile.create("/src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", false);
@@ -238,8 +223,30 @@ public class ComponentIndexerTest {
}));
}
+ @Test
+ public void should_compute_line_count() throws IOException {
+ DefaultInputFile inputFile = newInputFile("src/main/java/foo/bar/Foo.java", "line1\nline2\nline3", "foo/bar/Foo.java", "java", false);
+ when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList(inputFile));
+ Languages languages = new Languages(Java.INSTANCE);
+ ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, settings, mock(ResourceKeyMigration.class), new DefaultModuleLanguages(settings, languages),
+ mock(ResourceDao.class), mock(InputFileCache.class));
+ indexer.execute(fs);
+
+ assertThat(inputFile.attribute(InputFile.ATTRIBUTE_LINE_COUNT)).isEqualTo("3");
+ }
+
private File getFile(String testFile) {
return new File("test-resources/org/sonar/batch/phases/FileIndexerTest/encoding/" + testFile);
}
+ private DefaultInputFile newInputFile(String path, String content, String sourceRelativePath, String languageKey, boolean unitTest) throws IOException {
+ File file = new File(baseDir, path);
+ FileUtils.write(file, content);
+ return new InputFileBuilder(file, Charsets.UTF_8, path)
+ .attribute(DefaultInputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH, sourceRelativePath)
+ .attribute(InputFile.ATTRIBUTE_LANGUAGE, languageKey)
+ .attribute(InputFile.ATTRIBUTE_TYPE, unitTest ? InputFile.TYPE_TEST : InputFile.TYPE_MAIN)
+ .build();
+ }
+
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java
index 91ed1c144c1..e811576ec2e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/InputFile.java
@@ -34,6 +34,11 @@ public interface InputFile extends Serializable {
String ATTRIBUTE_LANGUAGE = "LANG";
/**
+ * Number of lines in the file.
+ */
+ String ATTRIBUTE_LINE_COUNT = "LINE_COUNT";
+
+ /**
* Type of source file. For now only possible values are {@link #TYPE_MAIN} or {@link #TYPE_TEST}
*/
String ATTRIBUTE_TYPE = "TYPE";