aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java8
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java6
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java4
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java4
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java4
-rw-r--r--plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/deprecated/InputFileComponent.java (renamed from sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRuleValueCoder.java)49
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/deprecated/perspectives/BatchPerspectives.java (renamed from sonar-core/src/main/java/org/sonar/core/component/ScanPerspectives.java)11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingData.java61
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java84
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataValueCoder.java52
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java59
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java169
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java19
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java101
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/BatchReportUtils.java83
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java180
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java159
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisherStep.java (renamed from sonar-batch/src/main/java/org/sonar/batch/highlighting/package-info.java)14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ComponentIndexer.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java18
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileMetadata.java73
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java26
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java106
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizerSensor.java73
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizers.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/DefaultHighlightable.java43
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbol.java27
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java43
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/HighlightableBuilder.java27
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/HighlightingCodeBuilder.java15
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/HighlightingRenderer.java9
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/source/SymbolizableBuilder.java35
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java89
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java68
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilderTest.java86
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataTest.java50
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java87
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java180
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java18
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java)6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ComponentIndexerTest.java13
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java3
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java11
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java46
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/CodeColorizersTest.java57
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/DefaultHighlightableTest.java42
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java25
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolizableTest.java29
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/HighlightableBuilderTest.java16
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/source/SymbolizableBuilderTest.java32
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java108
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/GraphPerspectiveBuilder.java6
-rw-r--r--sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java4
-rw-r--r--sonar-core/src/test/java/org/sonar/core/component/PerspectiveBuilderTest.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java26
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextPointer.java (renamed from sonar-batch/src/main/java/org/sonar/batch/symbol/package-info.java)22
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextRange.java46
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java116
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java74
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java74
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java (renamed from sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java)113
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java26
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java29
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java13
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java3
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/component/Perspectives.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java7
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/source/Symbol.java9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java4
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java107
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileMetadataTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java)43
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java65
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java10
-rw-r--r--sonar-plugin-api/src/test/resources/org/sonar/api/batch/fs/internal/glyphicons-halflings-regular.woff (renamed from sonar-batch/src/test/resources/org/sonar/batch/scan/filesystem/glyphicons-halflings-regular.woff)bin16448 -> 16448 bytes
96 files changed, 1677 insertions, 1862 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
index 1ac4c1a4f3a..c6ecc1ba900 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
@@ -36,7 +36,7 @@ import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.output.BatchReport.Scm;
import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
import org.sonar.batch.protocol.output.BatchReportReader;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import javax.annotation.Nullable;
@@ -53,17 +53,17 @@ import java.util.Map;
public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
private final List<PeriodStruct> structs;
- private final PublishReportJob publishReportJob;
+ private final ReportPublisher publishReportJob;
private final ResourceCache resourceCache;
- public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, ResourceCache resourceCache) {
this(Lists.<PeriodStruct>newArrayList(), publishReportJob, resourceCache);
for (Period period : timeMachineConfiguration.periods()) {
structs.add(new PeriodStruct(period.getIndex(), period.getDate()));
}
}
- AbstractNewCoverageFileAnalyzer(List<PeriodStruct> structs, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ AbstractNewCoverageFileAnalyzer(List<PeriodStruct> structs, ReportPublisher publishReportJob, ResourceCache resourceCache) {
this.resourceCache = resourceCache;
this.publishReportJob = publishReportJob;
this.structs = structs;
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
index 38aac00f0ea..d13df7224ef 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
@@ -23,17 +23,17 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import java.util.List;
public class NewCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, ResourceCache resourceCache) {
super(timeMachineConfiguration, publishReportJob, resourceCache);
}
- NewCoverageFileAnalyzer(List<PeriodStruct> structs, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ NewCoverageFileAnalyzer(List<PeriodStruct> structs, ReportPublisher publishReportJob, ResourceCache resourceCache) {
super(structs, publishReportJob, resourceCache);
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
index 48222f59ce2..f069a633b4e 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
@@ -23,11 +23,11 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
public class NewItCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, ResourceCache resourceCache) {
super(timeMachineConfiguration, publishReportJob, resourceCache);
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
index 75a1a83686c..fc61e4eafe3 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
@@ -23,11 +23,11 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.index.ResourceCache;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
public class NewOverallCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, ReportPublisher publishReportJob, ResourceCache resourceCache) {
super(timeMachineConfiguration, publishReportJob, resourceCache);
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
index af6d25828a6..6f02ac2f626 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
@@ -35,7 +35,7 @@ import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.output.BatchReport.Scm;
import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
import org.sonar.batch.protocol.output.BatchReportWriter;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -69,7 +69,7 @@ public class NewCoverageFileAnalyzerTest {
List<AbstractNewCoverageFileAnalyzer.PeriodStruct> structs = Arrays.asList(
new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")),
new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18")));
- PublishReportJob publishReportJob = mock(PublishReportJob.class);
+ ReportPublisher publishReportJob = mock(ReportPublisher.class);
java.io.File reportBaseDir = temp.newFolder();
when(publishReportJob.getReportDir()).thenReturn(reportBaseDir);
writer = new BatchReportWriter(reportBaseDir);
diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
index d31724c73e8..9d27f526e33 100644
--- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
+++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/lang/SyntaxHighlightingSensorTest.java
@@ -25,12 +25,14 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.batch.sensor.internal.SensorContextTester;
import java.io.File;
import java.io.IOException;
+import java.io.StringReader;
import static org.assertj.core.api.Assertions.assertThat;
@@ -66,12 +68,13 @@ public class SyntaxHighlightingSensorTest {
public void testExecution() throws IOException {
File symbol = new File(baseDir, "src/foo.xoo.highlighting");
FileUtils.write(symbol, "1:4:k\n12:15:cppd\n\n#comment");
- DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setLanguage("xoo").setLastValidOffset(100);
+ DefaultInputFile inputFile = new DefaultInputFile("foo", "src/foo.xoo").setLanguage("xoo")
+ .initMetadata(new FileMetadata().readMetadata(new StringReader(" xoo\nazertyazer\nfoo")));
context.fileSystem().add(inputFile);
sensor.execute(context);
- assertThat(context.highlightingTypeFor("foo:src/foo.xoo", 2)).containsOnly(TypeOfText.KEYWORD);
- assertThat(context.highlightingTypeFor("foo:src/foo.xoo", 13)).containsOnly(TypeOfText.CPP_DOC);
+ assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 1, 2)).containsOnly(TypeOfText.KEYWORD);
+ assertThat(context.highlightingTypeAt("foo:src/foo.xoo", 2, 8)).containsOnly(TypeOfText.CPP_DOC);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
index 0358d1428f6..6a19dc49ab7 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
@@ -29,6 +29,7 @@ import org.sonar.batch.maven.MavenProjectConverter;
import org.sonar.batch.scan.report.*;
import org.sonar.batch.scm.ScmConfiguration;
import org.sonar.batch.scm.ScmSensor;
+import org.sonar.batch.source.CodeColorizerSensor;
import org.sonar.batch.source.LinesSensor;
import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
@@ -59,6 +60,7 @@ public class BatchComponents {
ScmSensor.class,
LinesSensor.class,
+ CodeColorizerSensor.class,
// Issues tracking
IssueTracking.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRuleValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/deprecated/InputFileComponent.java
index 8700c81f345..c79b9afd6b6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRuleValueCoder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/deprecated/InputFileComponent.java
@@ -17,29 +17,44 @@
* 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.highlighting;
+package org.sonar.batch.deprecated;
-import com.persistit.Value;
-import com.persistit.encoding.CoderContext;
-import com.persistit.encoding.ValueCoder;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
+import org.sonar.api.batch.fs.InputFile.Type;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.component.Component;
+import org.sonar.api.resources.Qualifiers;
-class SyntaxHighlightingRuleValueCoder implements ValueCoder {
+public class InputFileComponent implements Component {
+
+ private final DefaultInputFile inputFile;
+
+ public InputFileComponent(DefaultInputFile inputFile) {
+ this.inputFile = inputFile;
+ }
@Override
- public void put(Value value, Object object, CoderContext context) {
- SyntaxHighlightingRule rule = (SyntaxHighlightingRule) object;
- value.put(rule.getStartPosition());
- value.put(rule.getEndPosition());
- value.put(rule.getTextType().ordinal());
+ public String key() {
+ return inputFile.key();
}
@Override
- public Object get(Value value, Class clazz, CoderContext context) {
- int startPosition = value.getInt();
- int endPosition = value.getInt();
- TypeOfText type = TypeOfText.values()[value.getInt()];
- return SyntaxHighlightingRule.create(startPosition, endPosition, type);
+ public String path() {
+ return inputFile.relativePath();
}
+
+ @Override
+ public String name() {
+ return inputFile.file().getName();
+ }
+
+ @Override
+ public String longName() {
+ return inputFile.relativePath();
+ }
+
+ @Override
+ public String qualifier() {
+ return inputFile.type() == Type.MAIN ? Qualifiers.FILE : Qualifiers.UNIT_TEST_FILE;
+ }
+
}
diff --git a/sonar-core/src/main/java/org/sonar/core/component/ScanPerspectives.java b/sonar-batch/src/main/java/org/sonar/batch/deprecated/perspectives/BatchPerspectives.java
index 09cf4c72b54..d743cca7301 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/ScanPerspectives.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/deprecated/perspectives/BatchPerspectives.java
@@ -17,7 +17,11 @@
* 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.core.component;
+package org.sonar.batch.deprecated.perspectives;
+
+import org.sonar.core.component.PerspectiveBuilder;
+import org.sonar.core.component.PerspectiveNotFoundException;
+import org.sonar.core.component.ResourceComponent;
import com.google.common.collect.Maps;
import org.sonar.api.batch.SonarIndex;
@@ -32,14 +36,15 @@ import org.sonar.api.resources.File;
import org.sonar.api.resources.Resource;
import javax.annotation.CheckForNull;
+
import java.util.Map;
-public class ScanPerspectives implements ResourcePerspectives {
+public class BatchPerspectives implements ResourcePerspectives {
private final Map<Class<?>, PerspectiveBuilder<?>> builders = Maps.newHashMap();
private final SonarIndex resourceIndex;
- public ScanPerspectives(PerspectiveBuilder[] builders, SonarIndex resourceIndex) {
+ public BatchPerspectives(PerspectiveBuilder[] builders, SonarIndex resourceIndex) {
this.resourceIndex = resourceIndex;
for (PerspectiveBuilder builder : builders) {
// TODO check duplications
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingData.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingData.java
deleted file mode 100644
index 7b9b334e15a..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingData.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.highlighting;
-
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
-import org.sonar.batch.index.Data;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-public class SyntaxHighlightingData implements Data {
-
- public static final String FIELD_SEPARATOR = ",";
- public static final String RULE_SEPARATOR = ";";
-
- private List<SyntaxHighlightingRule> syntaxHighlightingRuleSet;
-
- public SyntaxHighlightingData(Collection<SyntaxHighlightingRule> syntaxHighlightingRuleSet) {
- this.syntaxHighlightingRuleSet = new ArrayList<SyntaxHighlightingRule>(syntaxHighlightingRuleSet);
- }
-
- public List<SyntaxHighlightingRule> syntaxHighlightingRuleSet() {
- return syntaxHighlightingRuleSet;
- }
-
- @Override
- public String writeString() {
- StringBuilder sb = new StringBuilder();
- for (SyntaxHighlightingRule highlightingRule : syntaxHighlightingRuleSet) {
- if (sb.length() > 0) {
- sb.append(RULE_SEPARATOR);
- }
- sb.append(highlightingRule.getStartPosition())
- .append(FIELD_SEPARATOR)
- .append(highlightingRule.getEndPosition())
- .append(FIELD_SEPARATOR)
- .append(highlightingRule.getTextType().cssClass());
- }
-
- return sb.toString();
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
deleted file mode 100644
index be0fa73a3e9..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.highlighting;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
-
-import javax.annotation.Nullable;
-
-import java.util.Iterator;
-import java.util.Set;
-
-public class SyntaxHighlightingDataBuilder {
-
- private Set<SyntaxHighlightingRule> syntaxHighlightingRuleSet;
-
- public SyntaxHighlightingDataBuilder() {
- syntaxHighlightingRuleSet = Sets.newTreeSet(new Ordering<SyntaxHighlightingRule>() {
- @Override
- public int compare(@Nullable SyntaxHighlightingRule left,
- @Nullable SyntaxHighlightingRule right) {
- int result = left.getStartPosition() - right.getStartPosition();
- if (result == 0) {
- result = right.getEndPosition() - left.getEndPosition();
- }
- return result;
- }
- });
- }
-
- @VisibleForTesting
- public Set<SyntaxHighlightingRule> getSyntaxHighlightingRuleSet() {
- return syntaxHighlightingRuleSet;
- }
-
- public SyntaxHighlightingDataBuilder registerHighlightingRule(int startOffset, int endOffset, TypeOfText typeOfText) {
- SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(startOffset, endOffset,
- typeOfText);
- this.syntaxHighlightingRuleSet.add(syntaxHighlightingRule);
- return this;
- }
-
- public SyntaxHighlightingData build() {
- checkOverlappingBoudaries();
- return new SyntaxHighlightingData(syntaxHighlightingRuleSet);
- }
-
- private void checkOverlappingBoudaries() {
- if (syntaxHighlightingRuleSet.size() > 1) {
- Iterator<SyntaxHighlightingRule> it = syntaxHighlightingRuleSet.iterator();
- SyntaxHighlightingRule previous = it.next();
- while (it.hasNext()) {
- SyntaxHighlightingRule current = it.next();
- if (previous.getEndPosition() > current.getStartPosition() && !(previous.getEndPosition() >= current.getEndPosition())) {
- String errorMsg = String.format("Cannot register highlighting rule for characters from %s to %s as it " +
- "overlaps at least one existing rule", current.getStartPosition(), current.getEndPosition());
- throw new IllegalStateException(errorMsg);
- }
- previous = current;
- }
- }
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataValueCoder.java
deleted file mode 100644
index a748b499d57..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataValueCoder.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.highlighting;
-
-import com.persistit.Value;
-import com.persistit.encoding.CoderContext;
-import com.persistit.encoding.ValueCoder;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class SyntaxHighlightingDataValueCoder implements ValueCoder {
-
- private SyntaxHighlightingRuleValueCoder rulesCoder = new SyntaxHighlightingRuleValueCoder();
-
- @Override
- public void put(Value value, Object object, CoderContext context) {
- SyntaxHighlightingData data = (SyntaxHighlightingData) object;
- value.put(data.syntaxHighlightingRuleSet().size());
- for (SyntaxHighlightingRule rule : data.syntaxHighlightingRuleSet()) {
- rulesCoder.put(value, rule, context);
- }
- }
-
- @Override
- public Object get(Value value, Class clazz, CoderContext context) {
- int count = value.getInt();
- List<SyntaxHighlightingRule> rules = new ArrayList<SyntaxHighlightingRule>(count);
- for (int i = 0; i < count; i++) {
- rules.add((SyntaxHighlightingRule) rulesCoder.get(value, SyntaxHighlightingRule.class, context));
- }
- return new SyntaxHighlightingData(rules);
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java b/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java
index a07eded789c..ff8af997c2f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/BatchResource.java
@@ -19,6 +19,7 @@
*/
package org.sonar.batch.index;
+import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
@@ -36,6 +37,7 @@ public class BatchResource {
private Snapshot s;
private final BatchResource parent;
private final Collection<BatchResource> children = new ArrayList<BatchResource>();
+ private InputPath inputPath;
public BatchResource(int batchId, Resource r, @Nullable BatchResource parent) {
this.batchId = batchId;
@@ -91,4 +93,14 @@ public class BatchResource {
public boolean isDir() {
return ResourceUtils.isDirectory(r);
}
+
+ public BatchResource setInputPath(InputPath inputPath) {
+ this.inputPath = inputPath;
+ return this;
+ }
+
+ @CheckForNull
+ public InputPath inputPath() {
+ return inputPath;
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java
deleted file mode 100644
index b94aa0973b1..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/index/ComponentDataCache.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.index;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.batch.highlighting.SyntaxHighlightingDataValueCoder;
-
-import javax.annotation.CheckForNull;
-
-public class ComponentDataCache implements BatchComponent {
- private final Cache cache;
-
- public ComponentDataCache(Caches caches) {
- caches.registerValueCoder(SyntaxHighlightingData.class, new SyntaxHighlightingDataValueCoder());
- cache = caches.createCache("componentData");
- }
-
- public <D extends Data> ComponentDataCache setData(String componentKey, String dataType, D data) {
- cache.put(componentKey, dataType, data);
- return this;
- }
-
- public ComponentDataCache setStringData(String componentKey, String dataType, String data) {
- return setData(componentKey, dataType, new StringData(data));
- }
-
- @CheckForNull
- public <D extends Data> D getData(String componentKey, String dataType) {
- return (D) cache.get(componentKey, dataType);
- }
-
- @CheckForNull
- public String getStringData(String componentKey, String dataType) {
- Data data = (Data) cache.get(componentKey, dataType);
- return data == null ? null : ((StringData) data).data();
- }
-
- public <D extends Data> Iterable<Cache.Entry<D>> entries(String componentKey) {
- return cache.entries(componentKey);
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
index d2197170309..8a0184be3e3 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
@@ -26,22 +26,19 @@ import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
-import org.sonar.api.source.Symbol;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
+import org.sonar.batch.protocol.output.BatchReport.Range;
import org.sonar.batch.protocol.output.BatchReport.Scm;
import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
-import org.sonar.batch.protocol.output.BatchReportReader;
-import org.sonar.batch.report.PublishReportJob;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
+import org.sonar.batch.protocol.output.BatchReport.Symbols;
+import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting.HighlightingRule;
+import org.sonar.batch.protocol.output.*;
+import org.sonar.batch.report.BatchReportUtils;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.batch.source.CodeColorizers;
-import org.sonar.batch.symbol.SymbolData;
-import org.sonar.core.source.SnapshotDataTypes;
import org.sonar.core.source.db.FileSourceDto;
import org.sonar.server.source.db.FileSourceDb;
import org.sonar.server.source.db.FileSourceDb.Data.Builder;
@@ -58,30 +55,25 @@ public class SourceDataFactory implements BatchComponent {
private static final String BOM = "\uFEFF";
private final MeasureCache measureCache;
- private final ComponentDataCache componentDataCache;
private final DuplicationCache duplicationCache;
- private final CodeColorizers codeColorizers;
- private final PublishReportJob publishReportJob;
+ private final ReportPublisher reportPublisher;
private final ResourceCache resourceCache;
- public SourceDataFactory(MeasureCache measureCache, ComponentDataCache componentDataCache,
- DuplicationCache duplicationCache, CodeColorizers codeColorizers, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ public SourceDataFactory(MeasureCache measureCache, DuplicationCache duplicationCache, ReportPublisher reportPublisher, ResourceCache resourceCache) {
this.measureCache = measureCache;
- this.componentDataCache = componentDataCache;
this.duplicationCache = duplicationCache;
- this.codeColorizers = codeColorizers;
- this.publishReportJob = publishReportJob;
+ this.reportPublisher = reportPublisher;
this.resourceCache = resourceCache;
}
- public byte[] consolidateData(DefaultInputFile inputFile, InputFileMetadata metadata) throws IOException {
+ public byte[] consolidateData(DefaultInputFile inputFile) throws IOException {
FileSourceDb.Data.Builder dataBuilder = createForSource(inputFile);
applyLineMeasures(inputFile, dataBuilder);
applyScm(inputFile, dataBuilder);
applyDuplications(inputFile.key(), dataBuilder);
- applyHighlighting(inputFile, metadata, dataBuilder);
- applySymbolReferences(inputFile, metadata, dataBuilder);
+ applyHighlighting(inputFile, dataBuilder);
+ applySymbolReferences(inputFile, dataBuilder);
return FileSourceDto.encodeData(dataBuilder.build());
}
@@ -101,7 +93,7 @@ public class SourceDataFactory implements BatchComponent {
}
void applyScm(DefaultInputFile inputFile, Builder dataBuilder) {
- BatchReportReader reader = new BatchReportReader(publishReportJob.getReportDir());
+ BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
Scm componentScm = reader.readComponentScm(resourceCache.get(inputFile).batchId());
if (componentScm != null) {
for (int i = 0; i < componentScm.getChangesetIndexByLineCount(); i++) {
@@ -202,25 +194,22 @@ public class SourceDataFactory implements BatchComponent {
void apply(String value, FileSourceDb.Line.Builder lineBuilder);
}
- void applyHighlighting(DefaultInputFile inputFile, InputFileMetadata metadata, FileSourceDb.Data.Builder to) {
- SyntaxHighlightingData highlighting = componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING);
- String language = inputFile.language();
- if (highlighting == null && language != null) {
- highlighting = codeColorizers.toSyntaxHighlighting(inputFile.file(), inputFile.charset(), language);
- }
- if (highlighting == null) {
+ void applyHighlighting(DefaultInputFile inputFile, FileSourceDb.Data.Builder to) {
+ BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
+ List<HighlightingRule> highlightingRules = reader.readComponentSyntaxHighlighting(resourceCache.get(inputFile).batchId());
+ if (highlightingRules.isEmpty()) {
return;
}
StringBuilder[] highlightingPerLine = new StringBuilder[inputFile.lines()];
RuleItemWriter ruleItemWriter = new RuleItemWriter();
int currentLineIdx = 1;
- for (SyntaxHighlightingRule rule : highlighting.syntaxHighlightingRuleSet()) {
- while (currentLineIdx < inputFile.lines() && rule.getStartPosition() >= metadata.originalLineOffsets()[currentLineIdx]) {
+ for (HighlightingRule rule : highlightingRules) {
+ while (currentLineIdx < inputFile.lines() && rule.getRange().getStartLine() > currentLineIdx) {
// This rule starts on another line so advance
currentLineIdx++;
}
// Now we know current rule starts on current line
- writeDataPerLine(metadata.originalLineOffsets(), rule, rule.getStartPosition(), rule.getEndPosition(), highlightingPerLine, currentLineIdx, ruleItemWriter);
+ writeDataPerLine(inputFile.originalLineOffsets(), rule, rule.getRange(), highlightingPerLine, ruleItemWriter);
}
for (int i = 0; i < highlightingPerLine.length; i++) {
StringBuilder sb = highlightingPerLine[i];
@@ -230,76 +219,60 @@ public class SourceDataFactory implements BatchComponent {
}
}
- void applySymbolReferences(DefaultInputFile file, InputFileMetadata metadata, FileSourceDb.Data.Builder to) {
- SymbolData symbolRefs = componentDataCache.getData(file.key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING);
- if (symbolRefs != null) {
- StringBuilder[] refsPerLine = new StringBuilder[file.lines()];
- int symbolId = 1;
- List<Symbol> symbols = new ArrayList<Symbol>(symbolRefs.referencesBySymbol().keySet());
- // Sort symbols to avoid false variation that would lead to an unnecessary update
- Collections.sort(symbols, new Comparator<Symbol>() {
- @Override
- public int compare(Symbol o1, Symbol o2) {
- return o1.getDeclarationStartOffset() - o2.getDeclarationStartOffset();
- }
- });
- for (Symbol symbol : symbols) {
- int declarationStartOffset = symbol.getDeclarationStartOffset();
- int declarationEndOffset = symbol.getDeclarationEndOffset();
- int length = declarationEndOffset - declarationStartOffset;
- addSymbol(symbolId, declarationStartOffset, declarationEndOffset, metadata.originalLineOffsets(), refsPerLine);
- for (Integer referenceStartOffset : symbolRefs.referencesBySymbol().get(symbol)) {
- if (referenceStartOffset == declarationStartOffset) {
- // Ignore old API that used to store reference as first declaration
- continue;
- }
- addSymbol(symbolId, referenceStartOffset, referenceStartOffset + length, metadata.originalLineOffsets(), refsPerLine);
+ void applySymbolReferences(DefaultInputFile inputFile, FileSourceDb.Data.Builder to) {
+ BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
+ List<Symbols.Symbol> symbols = new ArrayList<Symbols.Symbol>(reader.readComponentSymbols(resourceCache.get(inputFile).batchId()));
+ if (symbols.isEmpty()) {
+ return;
+ }
+ StringBuilder[] refsPerLine = new StringBuilder[inputFile.lines()];
+ int symbolId = 1;
+ // Sort symbols to avoid false variation that would lead to an unnecessary update
+ Collections.sort(symbols, new Comparator<Symbols.Symbol>() {
+ @Override
+ public int compare(Symbols.Symbol o1, Symbols.Symbol o2) {
+ if (o1.getDeclaration().getStartLine() == o2.getDeclaration().getStartLine()) {
+ return Integer.compare(o1.getDeclaration().getStartOffset(), o2.getDeclaration().getStartOffset());
+ } else {
+ return Integer.compare(o1.getDeclaration().getStartLine(), o2.getDeclaration().getStartLine());
}
- symbolId++;
}
- for (int i = 0; i < refsPerLine.length; i++) {
- StringBuilder sb = refsPerLine[i];
- if (sb != null) {
- to.getLinesBuilder(i).setSymbols(sb.toString());
- }
+ });
+ for (Symbols.Symbol symbol : symbols) {
+ addSymbol(symbolId, symbol.getDeclaration(), inputFile.originalLineOffsets(), refsPerLine);
+ for (Range reference : symbol.getReferenceList()) {
+ addSymbol(symbolId, reference, inputFile.originalLineOffsets(), refsPerLine);
}
+ symbolId++;
}
- }
-
- private void addSymbol(int symbolId, int startOffset, int endOffset, int[] originalLineOffsets, StringBuilder[] result) {
- int startLine = binarySearchLine(startOffset, originalLineOffsets);
- writeDataPerLine(originalLineOffsets, symbolId, startOffset, endOffset, result, startLine, new SymbolItemWriter());
- }
-
- private int binarySearchLine(int declarationStartOffset, int[] originalLineOffsets) {
- int begin = 0;
- int end = originalLineOffsets.length - 1;
- while (begin < end) {
- int mid = (int) Math.round((begin + end) / 2D);
- if (declarationStartOffset < originalLineOffsets[mid]) {
- end = mid - 1;
- } else {
- begin = mid;
+ for (int i = 0; i < refsPerLine.length; i++) {
+ StringBuilder sb = refsPerLine[i];
+ if (sb != null) {
+ to.getLinesBuilder(i).setSymbols(sb.toString());
}
}
- return begin + 1;
}
- private <G> void writeDataPerLine(int[] originalLineOffsets, G item, int globalStartOffset, int globalEndOffset, StringBuilder[] dataPerLine, int startLine,
- RangeItemWriter<G> writer) {
- int currentLineIdx = startLine;
- // We know current item starts on current line
- long ruleStartOffsetCurrentLine = globalStartOffset;
- while (currentLineIdx < originalLineOffsets.length && globalEndOffset >= originalLineOffsets[currentLineIdx]) {
+ private void addSymbol(int symbolId, Range range, int[] originalLineOffsets, StringBuilder[] result) {
+ writeDataPerLine(originalLineOffsets, symbolId, range, result, new SymbolItemWriter());
+ }
+
+ private <G> void writeDataPerLine(int[] originalLineOffsets, G item, Range range, StringBuilder[] dataPerLine, RangeItemWriter<G> writer) {
+ int currentLineIdx = range.getStartLine();
+ long ruleStartOffsetCurrentLine = range.getStartOffset();
+ while (currentLineIdx < dataPerLine.length && range.getEndLine() > currentLineIdx) {
// item continue on next line so write current line and continue on next line with same item
- writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine - originalLineOffsets[currentLineIdx - 1], originalLineOffsets[currentLineIdx]
- - originalLineOffsets[currentLineIdx - 1], writer);
+ writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine, lineLength(originalLineOffsets, currentLineIdx), writer);
currentLineIdx++;
- ruleStartOffsetCurrentLine = originalLineOffsets[currentLineIdx - 1];
+ ruleStartOffsetCurrentLine = 0;
}
// item ends on current line
- writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine - originalLineOffsets[currentLineIdx - 1], globalEndOffset
- - originalLineOffsets[currentLineIdx - 1], writer);
+ writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine, range.getEndOffset(), writer);
+ }
+
+ private int lineLength(int[] originalLineOffsets, int currentLineIdx) {
+ return originalLineOffsets[currentLineIdx]
+ - originalLineOffsets[currentLineIdx - 1];
}
private <G> void writeItem(G item, StringBuilder[] dataPerLine, int currentLineIdx, long startLineOffset, long endLineOffset, RangeItemWriter<G> writer) {
@@ -321,17 +294,17 @@ public class SourceDataFactory implements BatchComponent {
void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, G item);
}
- private static class RuleItemWriter implements RangeItemWriter<SyntaxHighlightingRule> {
+ private static class RuleItemWriter implements RangeItemWriter<HighlightingRule> {
@Override
- public void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, SyntaxHighlightingRule item) {
+ public void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, HighlightingRule item) {
if (currentLineSb.length() > 0) {
- currentLineSb.append(SyntaxHighlightingData.RULE_SEPARATOR);
+ currentLineSb.append(';');
}
currentLineSb.append(startLineOffset)
- .append(SyntaxHighlightingData.FIELD_SEPARATOR)
+ .append(',')
.append(endLineOffset)
- .append(SyntaxHighlightingData.FIELD_SEPARATOR)
- .append(item.getTextType().cssClass());
+ .append(',')
+ .append(BatchReportUtils.toCssClass(item.getType()));
}
}
@@ -340,12 +313,12 @@ public class SourceDataFactory implements BatchComponent {
@Override
public void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, Integer symbolId) {
if (currentLineSb.length() > 0) {
- currentLineSb.append(SymbolData.SYMBOL_SEPARATOR);
+ currentLineSb.append(";");
}
currentLineSb.append(startLineOffset)
- .append(SymbolData.FIELD_SEPARATOR)
+ .append(",")
.append(endLineOffset)
- .append(SymbolData.FIELD_SEPARATOR)
+ .append(",")
.append(symbolId);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
index bf537550a8c..a55562c88f2 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
@@ -19,6 +19,9 @@
*/
package org.sonar.batch.index;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
+
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.session.ResultContext;
@@ -27,9 +30,6 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.System2;
import org.sonar.batch.ProjectTree;
-import org.sonar.batch.scan.filesystem.FileMetadata;
-import org.sonar.batch.scan.filesystem.FileMetadata.LineHashConsumer;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
import org.sonar.batch.scan.filesystem.InputPathCache;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
@@ -89,8 +89,7 @@ public class SourcePersister implements ScanPersister {
private void persist(DbSession session, FileSourceMapper mapper, DefaultInputFile inputFile, Map<String, FileSourceDto> previousDtosByUuid) {
String fileUuid = resourceCache.get(inputFile).resource().getUuid();
- InputFileMetadata metadata = inputPathCache.getFileMetadata(inputFile);
- byte[] data = computeData(inputFile, metadata);
+ byte[] data = computeData(inputFile);
String dataHash = DigestUtils.md5Hex(data);
FileSourceDto previousDto = previousDtosByUuid.get(fileUuid);
if (previousDto == null) {
@@ -99,7 +98,7 @@ public class SourcePersister implements ScanPersister {
.setFileUuid(fileUuid)
.setBinaryData(data)
.setDataHash(dataHash)
- .setSrcHash(metadata.hash())
+ .setSrcHash(inputFile.hash())
.setLineHashes(lineHashesAsMd5Hex(inputFile))
.setCreatedAt(system2.now())
.setUpdatedAt(0L);
@@ -108,12 +107,12 @@ public class SourcePersister implements ScanPersister {
} else {
// Update only if data_hash has changed or if src_hash is missing (progressive migration)
boolean binaryDataUpdated = !dataHash.equals(previousDto.getDataHash());
- boolean srcHashUpdated = !metadata.hash().equals(previousDto.getSrcHash());
+ boolean srcHashUpdated = !inputFile.hash().equals(previousDto.getSrcHash());
if (binaryDataUpdated || srcHashUpdated) {
previousDto
.setBinaryData(data)
.setDataHash(dataHash)
- .setSrcHash(metadata.hash())
+ .setSrcHash(inputFile.hash())
.setLineHashes(lineHashesAsMd5Hex(inputFile));
// Optimization only change updated at when updating binary data to avoid unecessary indexation by E/S
if (binaryDataUpdated) {
@@ -147,9 +146,9 @@ public class SourcePersister implements ScanPersister {
return result.toString();
}
- private byte[] computeData(DefaultInputFile inputFile, InputFileMetadata metadata) {
+ private byte[] computeData(DefaultInputFile inputFile) {
try {
- return dataFactory.consolidateData(inputFile, metadata);
+ return dataFactory.consolidateData(inputFile);
} catch (IOException e) {
throw new IllegalStateException("Fail to read file " + inputFile, e);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java
index 7491bbb7814..d287364b046 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssuableFactory.java
@@ -47,7 +47,7 @@ public class IssuableFactory extends PerspectiveBuilder<Issuable> {
@CheckForNull
@Override
- protected Issuable loadPerspective(Class<Issuable> perspectiveClass, Component component) {
+ public Issuable loadPerspective(Class<Issuable> perspectiveClass, Component component) {
boolean supported = true;
if (component instanceof ResourceComponent) {
supported = Scopes.isHigherThanOrEquals(((ResourceComponent) component).scope(), Scopes.FILE);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java
index 996351c26f6..9f50e3abbfb 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java
@@ -19,13 +19,14 @@
*/
package org.sonar.batch.issue.tracking;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
+
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.ObjectUtils;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.batch.scan.filesystem.FileMetadata;
-import org.sonar.batch.scan.filesystem.FileMetadata.LineHashConsumer;
import javax.annotation.Nullable;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index 6200c172993..e274375076b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -36,7 +36,7 @@ import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
import org.sonar.batch.protocol.input.*;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.repository.GlobalRepositoriesLoader;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
@@ -62,7 +62,7 @@ public class BatchMediumTester {
public static BatchMediumTesterBuilder builder() {
BatchMediumTesterBuilder builder = new BatchMediumTesterBuilder().registerCoreMetrics();
builder.bootstrapProperties.put(MEDIUM_TEST_ENABLED, "true");
- builder.bootstrapProperties.put(PublishReportJob.KEEP_REPORT_PROP_KEY, "true");
+ builder.bootstrapProperties.put(ReportPublisher.KEEP_REPORT_PROP_KEY, "true");
builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, Files.createTempDir().getAbsolutePath());
return builder;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
index 3dc913b005b..423f430c14f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java
@@ -23,31 +23,37 @@ import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.AnalysisMode;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.measures.Measure;
-import org.sonar.api.source.Symbol;
import org.sonar.batch.dependency.DependencyCache;
import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
import org.sonar.batch.index.Cache.Entry;
-import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.issue.IssueCache;
+import org.sonar.batch.protocol.output.BatchReport.Component;
+import org.sonar.batch.protocol.output.BatchReport.Metadata;
+import org.sonar.batch.protocol.output.BatchReport.Range;
+import org.sonar.batch.protocol.output.BatchReport.Symbols.Symbol;
+import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting.HighlightingRule;
+import org.sonar.batch.protocol.output.*;
+import org.sonar.batch.report.BatchReportUtils;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.scan.ProjectScanContainer;
import org.sonar.batch.scan.filesystem.InputPathCache;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.batch.symbol.SymbolData;
-import org.sonar.core.source.SnapshotDataTypes;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import java.io.Serializable;
import java.util.*;
@@ -60,10 +66,10 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
private List<org.sonar.api.batch.sensor.measure.Measure> measures = new ArrayList<>();
private Map<String, List<Duplication>> duplications = new HashMap<>();
private Map<String, InputFile> inputFiles = new HashMap<>();
+ private Map<String, Component> reportComponents = new HashMap<>();
private Map<String, InputDir> inputDirs = new HashMap<>();
- private Map<InputFile, SyntaxHighlightingData> highlightingPerFile = new HashMap<>();
- private Map<InputFile, SymbolData> symbolTablePerFile = new HashMap<>();
private Map<String, Map<String, Integer>> dependencies = new HashMap<>();
+ private BatchReportReader reader;
@Override
public void scanTaskCompleted(ProjectScanContainer container) {
@@ -72,16 +78,37 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
issues.add(issue);
}
+ if (!container.getComponentByType(AnalysisMode.class).isPreview()) {
+ ReportPublisher reportPublisher = container.getComponentByType(ReportPublisher.class);
+ reader = new BatchReportReader(reportPublisher.getReportDir());
+ Metadata readMetadata = getReportReader().readMetadata();
+ int rootComponentRef = readMetadata.getRootComponentRef();
+ storeReportComponents(rootComponentRef, null, readMetadata.hasBranch() ? readMetadata.getBranch() : null);
+ }
+
storeFs(container);
storeMeasures(container);
- storeComponentData(container);
storeDuplication(container);
- // storeTestCases(container);
- // storeCoveragePerTest(container);
storeDependencies(container);
+ }
+
+ private void storeReportComponents(int componentRef, String parentModuleKey, @Nullable String branch) {
+ Component component = getReportReader().readComponent(componentRef);
+ if (component.hasKey()) {
+ reportComponents.put(component.getKey() + (branch != null ? ":" + branch : ""), component);
+ } else {
+ reportComponents.put(parentModuleKey + (branch != null ? ":" + branch : "") + ":" + component.getPath(), component);
+ }
+ for (int childId : component.getChildRefList()) {
+ storeReportComponents(childId, component.hasKey() ? component.getKey() : parentModuleKey, branch);
+ }
+
+ }
+ public BatchReportReader getReportReader() {
+ return reader;
}
private void storeMeasures(ProjectScanContainer container) {
@@ -108,20 +135,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
}
}
- private void storeComponentData(ProjectScanContainer container) {
- ComponentDataCache componentDataCache = container.getComponentByType(ComponentDataCache.class);
- for (InputFile file : inputFiles.values()) {
- SyntaxHighlightingData highlighting = componentDataCache.getData(((DefaultInputFile) file).key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING);
- if (highlighting != null) {
- highlightingPerFile.put(file, highlighting);
- }
- SymbolData symbolTable = componentDataCache.getData(((DefaultInputFile) file).key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING);
- if (symbolTable != null) {
- symbolTablePerFile.put(file, symbolTable);
- }
- }
- }
-
private void storeFs(ProjectScanContainer container) {
InputPathCache inputFileCache = container.getComponentByType(InputPathCache.class);
for (InputFile inputPath : inputFileCache.allFiles()) {
@@ -178,37 +191,45 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
* Get highlighting types at a given position in an inputfile
* @param charIndex 0-based offset in file
*/
- public List<TypeOfText> highlightingTypeFor(InputFile file, int charIndex) {
- SyntaxHighlightingData syntaxHighlightingData = highlightingPerFile.get(file);
- if (syntaxHighlightingData == null) {
+ public List<TypeOfText> highlightingTypeFor(InputFile file, int line, int lineOffset) {
+ int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef();
+ List<HighlightingRule> syntaxHighlightingRules = getReportReader().readComponentSyntaxHighlighting(ref);
+ if (syntaxHighlightingRules.isEmpty()) {
return Collections.emptyList();
}
+ TextPointer pointer = file.newPointer(line, lineOffset);
List<TypeOfText> result = new ArrayList<TypeOfText>();
- for (SyntaxHighlightingRule sortedRule : syntaxHighlightingData.syntaxHighlightingRuleSet()) {
- if (sortedRule.getStartPosition() <= charIndex && sortedRule.getEndPosition() > charIndex) {
- result.add(sortedRule.getTextType());
+ for (HighlightingRule sortedRule : syntaxHighlightingRules) {
+ TextRange ruleRange = toRange(file, sortedRule.getRange());
+ if (ruleRange.start().compareTo(pointer) <= 0 && ruleRange.end().compareTo(pointer) > 0) {
+ result.add(BatchReportUtils.toBatchType(sortedRule.getType()));
}
}
return result;
}
+ private static TextRange toRange(InputFile file, Range reportRange) {
+ return file.newRange(file.newPointer(reportRange.getStartLine(), reportRange.getStartOffset()), file.newPointer(reportRange.getEndLine(), reportRange.getEndOffset()));
+ }
+
/**
- * Get list of all positions of a symbol in an inputfile
+ * Get list of all start positions of a symbol in an inputfile
* @param symbolStartOffset 0-based start offset for the symbol in file
* @param symbolEndOffset 0-based end offset for the symbol in file
*/
@CheckForNull
- public Set<Integer> symbolReferencesFor(InputFile file, int symbolStartOffset, int symbolEndOffset) {
- SymbolData data = symbolTablePerFile.get(file);
- if (data == null) {
- return null;
+ public List<Range> symbolReferencesFor(InputFile file, int symbolStartLine, int symbolStartLineOffset) {
+ int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef();
+ List<Symbol> symbols = getReportReader().readComponentSymbols(ref);
+ if (symbols.isEmpty()) {
+ return Collections.emptyList();
}
- for (Symbol symbol : data.referencesBySymbol().keySet()) {
- if (symbol.getDeclarationStartOffset() == symbolStartOffset && symbol.getDeclarationEndOffset() == symbolEndOffset) {
- return data.referencesBySymbol().get(symbol);
+ for (Symbol symbol : symbols) {
+ if (symbol.getDeclaration().getStartLine() == symbolStartLine && symbol.getDeclaration().getStartOffset() == symbolStartLineOffset) {
+ return symbol.getReferenceList();
}
}
- return null;
+ return Collections.emptyList();
}
/**
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java
index f53ce1b715e..644cf8bf724 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseLessPhaseExecutor.java
@@ -26,7 +26,7 @@ import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
import org.sonar.batch.issue.tracking.LocalIssueTracking;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.rule.QProfileVerifier;
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.batch.scan.filesystem.FileSystemLogger;
@@ -47,12 +47,12 @@ public final class DatabaseLessPhaseExecutor implements PhaseExecutor {
private final IssueExclusionsLoader issueExclusionsLoader;
private final IssuesReports issuesReport;
private final LocalIssueTracking localIssueTracking;
- private final PublishReportJob publishReportJob;
+ private final ReportPublisher publishReportJob;
public DatabaseLessPhaseExecutor(Phases phases, InitializersExecutor initializersExecutor, SensorsExecutor sensorsExecutor,
SensorContext sensorContext, DefaultIndex index,
EventBus eventBus, ProjectInitializer pi, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
- IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking, PublishReportJob publishReportJob) {
+ IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking, ReportPublisher publishReportJob) {
this.phases = phases;
this.initializersExecutor = initializersExecutor;
this.sensorsExecutor = sensorsExecutor;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
index 13ec298b8d4..657a58083f2 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DatabaseModePhaseExecutor.java
@@ -31,7 +31,7 @@ import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.ResourcePersister;
import org.sonar.batch.index.ScanPersister;
import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader;
-import org.sonar.batch.report.PublishReportJob;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.rule.QProfileVerifier;
import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.batch.scan.filesystem.FileSystemLogger;
@@ -49,7 +49,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
private final PostJobsExecutor postJobsExecutor;
private final InitializersExecutor initializersExecutor;
private final SensorsExecutor sensorsExecutor;
- private final PublishReportJob publishReportJob;
+ private final ReportPublisher publishReportJob;
private final SensorContext sensorContext;
private final DefaultIndex index;
private final ProjectInitializer pi;
@@ -66,7 +66,7 @@ public final class DatabaseModePhaseExecutor implements PhaseExecutor {
public DatabaseModePhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor,
InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
SensorContext sensorContext, DefaultIndex index,
- EventBus eventBus, PublishReportJob publishReportJob, ProjectInitializer pi,
+ EventBus eventBus, ReportPublisher publishReportJob, ProjectInitializer pi,
ScanPersister[] persisters, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
IssueExclusionsLoader issueExclusionsLoader, DefaultAnalysisMode analysisMode, DatabaseSession session, ResourcePersister resourcePersister) {
this.phases = phases;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/BatchReportUtils.java b/sonar-batch/src/main/java/org/sonar/batch/report/BatchReportUtils.java
new file mode 100644
index 00000000000..4e20cd508c2
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/BatchReportUtils.java
@@ -0,0 +1,83 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.report;
+
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.batch.protocol.Constants.HighlightingType;
+
+public class BatchReportUtils {
+
+ private BatchReportUtils() {
+ }
+
+ public static HighlightingType toProtocolType(TypeOfText textType) {
+ switch (textType) {
+ case ANNOTATION:
+ return HighlightingType.ANNOTATION;
+ case COMMENT:
+ return HighlightingType.COMMENT;
+ case CONSTANT:
+ return HighlightingType.CONSTANT;
+ case CPP_DOC:
+ return HighlightingType.CPP_DOC;
+ case KEYWORD:
+ return HighlightingType.KEYWORD;
+ case KEYWORD_LIGHT:
+ return HighlightingType.KEYWORD_LIGHT;
+ case PREPROCESS_DIRECTIVE:
+ return HighlightingType.PREPROCESS_DIRECTIVE;
+ case STRING:
+ return HighlightingType.HIGHLIGHTING_STRING;
+ case STRUCTURED_COMMENT:
+ return HighlightingType.STRUCTURED_COMMENT;
+ default:
+ throw new IllegalArgumentException("Unknow highlighting type: " + textType);
+ }
+ }
+
+ public static TypeOfText toBatchType(HighlightingType type) {
+ switch (type) {
+ case ANNOTATION:
+ return TypeOfText.ANNOTATION;
+ case COMMENT:
+ return TypeOfText.COMMENT;
+ case CONSTANT:
+ return TypeOfText.CONSTANT;
+ case CPP_DOC:
+ return TypeOfText.CPP_DOC;
+ case HIGHLIGHTING_STRING:
+ return TypeOfText.STRING;
+ case KEYWORD:
+ return TypeOfText.KEYWORD;
+ case KEYWORD_LIGHT:
+ return TypeOfText.KEYWORD_LIGHT;
+ case PREPROCESS_DIRECTIVE:
+ return TypeOfText.PREPROCESS_DIRECTIVE;
+ case STRUCTURED_COMMENT:
+ return TypeOfText.STRUCTURED_COMMENT;
+ default:
+ throw new IllegalArgumentException(type + " is not a valid type");
+ }
+ }
+
+ public static String toCssClass(HighlightingType type) {
+ return toBatchType(type).cssClass();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
index 28dabefe4ad..7bed3e9db12 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
@@ -40,7 +40,7 @@ import javax.annotation.CheckForNull;
/**
* Adds components and analysis metadata to output report
*/
-public class ComponentsPublisher implements ReportPublisher {
+public class ComponentsPublisher implements ReportPublisherStep {
private final ResourceCache resourceCache;
private final ProjectReactor reactor;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java
index 896ef5aba08..0295e13bb2b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java
@@ -31,7 +31,7 @@ import org.sonar.batch.protocol.output.BatchReport.Duplicate;
import org.sonar.batch.protocol.output.BatchReport.Duplication;
import org.sonar.batch.protocol.output.BatchReport.Range;
-public class DuplicationsPublisher implements ReportPublisher {
+public class DuplicationsPublisher implements ReportPublisherStep {
private final ResourceCache resourceCache;
private final DuplicationCache duplicationCache;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
index 640552eccfe..f2268cd20a9 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
@@ -39,7 +39,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
-public class IssuesPublisher implements ReportPublisher {
+public class IssuesPublisher implements ReportPublisherStep {
private final ResourceCache resourceCache;
private final IssueCache issueCache;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
index 8aadc2180ee..0613432376b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java
@@ -43,7 +43,7 @@ import javax.annotation.Nullable;
import java.io.Serializable;
-public class MeasuresPublisher implements ReportPublisher {
+public class MeasuresPublisher implements ReportPublisherStep {
private final ResourceCache resourceCache;
private final MeasureCache measureCache;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
deleted file mode 100644
index 9fe5d4bbd8b..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.report;
-
-import com.github.kevinsawicki.http.HttpRequest;
-import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.io.FileUtils;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
-import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
-import org.sonar.api.platform.Server;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.batch.bootstrap.DefaultAnalysisMode;
-import org.sonar.batch.bootstrap.ServerClient;
-import org.sonar.batch.protocol.output.BatchReportWriter;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-public class PublishReportJob implements BatchComponent, Startable {
-
- private static final Logger LOG = LoggerFactory.getLogger(PublishReportJob.class);
- public static final String KEEP_REPORT_PROP_KEY = "sonar.batch.keepReport";
-
- private final ServerClient serverClient;
- private final Server server;
- private final Settings settings;
- private final ProjectReactor projectReactor;
- private final DefaultAnalysisMode analysisMode;
- private final TempFolder temp;
-
- private ReportPublisher[] publishers;
-
- private File reportDir;
- private BatchReportWriter writer;
-
- public PublishReportJob(Settings settings, ServerClient serverClient, Server server,
- ProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisher[] publishers) {
- this.serverClient = serverClient;
- this.server = server;
- this.projectReactor = projectReactor;
- this.settings = settings;
- this.analysisMode = analysisMode;
- this.temp = temp;
- this.publishers = publishers;
- }
-
- @Override
- public void start() throws StartingException {
- reportDir = new File(projectReactor.getRoot().getWorkDir(), "batch-report");
- writer = new BatchReportWriter(reportDir);
- }
-
- @Override
- public void stop() throws StoppingException {
- if (!settings.getBoolean(KEEP_REPORT_PROP_KEY)) {
- FileUtils.deleteQuietly(reportDir);
- } else {
- LOG.info("Batch report generated in " + reportDir);
- }
- }
-
- public File getReportDir() {
- return reportDir;
- }
-
- public BatchReportWriter getWriter() {
- return writer;
- }
-
- public void execute() {
- // If this is a preview analysis then we should not upload reports
- if (!analysisMode.isPreview()) {
- File report = prepareReport();
- if (!analysisMode.isMediumTest()) {
- uploadMultiPartReport(report);
- }
- }
- logSuccess(LoggerFactory.getLogger(getClass()));
- }
-
- private File prepareReport() {
- try {
- long startTime = System.currentTimeMillis();
- for (ReportPublisher publisher : publishers) {
- publisher.publish(writer);
- }
- long stopTime = System.currentTimeMillis();
- LOG.info("Analysis reports generated in " + (stopTime - startTime) + "ms, dir size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(reportDir)));
-
- startTime = System.currentTimeMillis();
- File reportZip = temp.newFile("batch-report", ".zip");
- ZipUtils.zipDir(reportDir, reportZip);
- stopTime = System.currentTimeMillis();
- LOG.info("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
- return reportZip;
- } catch (IOException e) {
- throw new IllegalStateException("Unable to prepare batch report", e);
- }
- }
-
- @VisibleForTesting
- void uploadMultiPartReport(File report) {
- LOG.debug("Publish results");
- long startTime = System.currentTimeMillis();
- URL url;
- try {
- String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
- url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + effectiveKey);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Invalid URL", e);
- }
- HttpRequest request = HttpRequest.post(url);
- request.trustAllCerts();
- request.trustAllHosts();
- request.header("User-Agent", String.format("SonarQube %s", server.getVersion()));
- request.basic(serverClient.getLogin(), serverClient.getPassword());
- request.part("report", null, "application/octet-stream", report);
- if (!request.ok()) {
- int responseCode = request.code();
- if (responseCode == 401) {
- throw new IllegalStateException(String.format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
- }
- if (responseCode == 403) {
- // SONAR-4397 Details are in response content
- throw new IllegalStateException(request.body());
- }
- throw new IllegalStateException(String.format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
- }
- long stopTime = System.currentTimeMillis();
- LOG.info("Analysis reports sent to server in " + (stopTime - startTime) + "ms");
- }
-
- @VisibleForTesting
- void logSuccess(Logger logger) {
- if (analysisMode.isPreview() || analysisMode.isMediumTest()) {
- logger.info("ANALYSIS SUCCESSFUL");
-
- } else {
- String baseUrl = settings.getString(CoreProperties.SERVER_BASE_URL);
- if (baseUrl.equals(settings.getDefaultValue(CoreProperties.SERVER_BASE_URL))) {
- // If server base URL was not configured in Sonar server then is is better to take URL configured on batch side
- baseUrl = serverClient.getURL();
- }
- if (!baseUrl.endsWith("/")) {
- baseUrl += "/";
- }
- String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
- String url = baseUrl + "dashboard/index/" + effectiveKey;
- logger.info("ANALYSIS SUCCESSFUL, you can browse {}", url);
- logger.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
- }
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
index 07aa03fccbe..2043fcd7f01 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisher.java
@@ -19,13 +19,162 @@
*/
package org.sonar.batch.report;
+import com.github.kevinsawicki.http.HttpRequest;
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.io.FileUtils;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.batch.bootstrap.DefaultAnalysisMode;
+import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.protocol.output.BatchReportWriter;
-/**
- * Adds a sub-part of data to output report
- */
-public interface ReportPublisher {
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+public class ReportPublisher implements BatchComponent, Startable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ReportPublisher.class);
+ public static final String KEEP_REPORT_PROP_KEY = "sonar.batch.keepReport";
+
+ private final ServerClient serverClient;
+ private final Server server;
+ private final Settings settings;
+ private final ProjectReactor projectReactor;
+ private final DefaultAnalysisMode analysisMode;
+ private final TempFolder temp;
+
+ private ReportPublisherStep[] publishers;
+
+ private File reportDir;
+ private BatchReportWriter writer;
+
+ public ReportPublisher(Settings settings, ServerClient serverClient, Server server,
+ ProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisherStep[] publishers) {
+ this.serverClient = serverClient;
+ this.server = server;
+ this.projectReactor = projectReactor;
+ this.settings = settings;
+ this.analysisMode = analysisMode;
+ this.temp = temp;
+ this.publishers = publishers;
+ }
+
+ @Override
+ public void start() throws StartingException {
+ reportDir = new File(projectReactor.getRoot().getWorkDir(), "batch-report");
+ writer = new BatchReportWriter(reportDir);
+ }
+
+ @Override
+ public void stop() throws StoppingException {
+ if (!settings.getBoolean(KEEP_REPORT_PROP_KEY)) {
+ FileUtils.deleteQuietly(reportDir);
+ } else {
+ LOG.info("Batch report generated in " + reportDir);
+ }
+ }
+
+ public File getReportDir() {
+ return reportDir;
+ }
+
+ public BatchReportWriter getWriter() {
+ return writer;
+ }
+
+ public void execute() {
+ // If this is a preview analysis then we should not upload reports
+ if (!analysisMode.isPreview()) {
+ File report = prepareReport();
+ if (!analysisMode.isMediumTest()) {
+ uploadMultiPartReport(report);
+ }
+ }
+ logSuccess(LoggerFactory.getLogger(getClass()));
+ }
+
+ private File prepareReport() {
+ try {
+ long startTime = System.currentTimeMillis();
+ for (ReportPublisherStep publisher : publishers) {
+ publisher.publish(writer);
+ }
+ long stopTime = System.currentTimeMillis();
+ LOG.info("Analysis reports generated in " + (stopTime - startTime) + "ms, dir size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOfDirectory(reportDir)));
+
+ startTime = System.currentTimeMillis();
+ File reportZip = temp.newFile("batch-report", ".zip");
+ ZipUtils.zipDir(reportDir, reportZip);
+ stopTime = System.currentTimeMillis();
+ LOG.info("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
+ return reportZip;
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to prepare batch report", e);
+ }
+ }
+
+ @VisibleForTesting
+ void uploadMultiPartReport(File report) {
+ LOG.debug("Publish results");
+ long startTime = System.currentTimeMillis();
+ URL url;
+ try {
+ String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
+ url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + effectiveKey);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Invalid URL", e);
+ }
+ HttpRequest request = HttpRequest.post(url);
+ request.trustAllCerts();
+ request.trustAllHosts();
+ request.header("User-Agent", String.format("SonarQube %s", server.getVersion()));
+ request.basic(serverClient.getLogin(), serverClient.getPassword());
+ request.part("report", null, "application/octet-stream", report);
+ if (!request.ok()) {
+ int responseCode = request.code();
+ if (responseCode == 401) {
+ throw new IllegalStateException(String.format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD));
+ }
+ if (responseCode == 403) {
+ // SONAR-4397 Details are in response content
+ throw new IllegalStateException(request.body());
+ }
+ throw new IllegalStateException(String.format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body()));
+ }
+ long stopTime = System.currentTimeMillis();
+ LOG.info("Analysis reports sent to server in " + (stopTime - startTime) + "ms");
+ }
- void publish(BatchReportWriter writer);
+ @VisibleForTesting
+ void logSuccess(Logger logger) {
+ if (analysisMode.isPreview() || analysisMode.isMediumTest()) {
+ logger.info("ANALYSIS SUCCESSFUL");
+ } else {
+ String baseUrl = settings.getString(CoreProperties.SERVER_BASE_URL);
+ if (baseUrl.equals(settings.getDefaultValue(CoreProperties.SERVER_BASE_URL))) {
+ // If server base URL was not configured in Sonar server then is is better to take URL configured on batch side
+ baseUrl = serverClient.getURL();
+ }
+ if (!baseUrl.endsWith("/")) {
+ baseUrl += "/";
+ }
+ String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
+ String url = baseUrl + "dashboard/index/" + effectiveKey;
+ logger.info("ANALYSIS SUCCESSFUL, you can browse {}", url);
+ logger.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
+ }
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisherStep.java
index 93b92f3e9ae..eb771b3d009 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/package-info.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/ReportPublisherStep.java
@@ -17,7 +17,15 @@
* 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.batch.highlighting;
+package org.sonar.batch.report;
-import javax.annotation.ParametersAreNonnullByDefault;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+
+/**
+ * Adds a sub-part of data to output report
+ */
+public interface ReportPublisherStep {
+
+ void publish(BatchReportWriter writer);
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index 5df7f4c665d..6e724866c67 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.rule.CheckFactory;
import org.sonar.api.checks.NoSonarFilter;
import org.sonar.api.platform.ComponentContainer;
@@ -37,6 +38,7 @@ import org.sonar.batch.deprecated.DeprecatedSensorContext;
import org.sonar.batch.deprecated.ResourceFilters;
import org.sonar.batch.deprecated.components.DefaultProjectClasspath;
import org.sonar.batch.deprecated.components.DefaultTimeMachine;
+import org.sonar.batch.deprecated.perspectives.BatchPerspectives;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.issue.IssuableFactory;
@@ -63,7 +65,8 @@ import org.sonar.batch.sensor.AnalyzerOptimizer;
import org.sonar.batch.sensor.DefaultSensorContext;
import org.sonar.batch.sensor.DefaultSensorStorage;
import org.sonar.batch.sensor.coverage.CoverageExclusions;
-import org.sonar.core.component.ScanPerspectives;
+import org.sonar.batch.source.HighlightableBuilder;
+import org.sonar.batch.source.SymbolizableBuilder;
public class ModuleScanContainer extends ComponentContainer {
private static final Logger LOG = LoggerFactory.getLogger(ModuleScanContainer.class);
@@ -111,7 +114,7 @@ public class ModuleScanContainer extends ComponentContainer {
SensorsExecutor.class,
InitializersExecutor.class,
ProjectInitializer.class,
- PublishReportJob.class,
+ ReportPublisher.class,
ComponentsPublisher.class,
IssuesPublisher.class,
MeasuresPublisher.class,
@@ -172,7 +175,10 @@ public class ModuleScanContainer extends ComponentContainer {
IgnoreIssuesFilter.class,
NoSonarFilter.class,
- ScanPerspectives.class);
+ // Perspectives
+ BatchPerspectives.class,
+ HighlightableBuilder.class,
+ SymbolizableBuilder.class);
}
private void addDataBaseComponents() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index aaa63f0d328..30bfafa9793 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -59,8 +59,6 @@ import org.sonar.batch.rule.RulesProvider;
import org.sonar.batch.scan.filesystem.InputPathCache;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.batch.source.CodeColorizers;
-import org.sonar.batch.source.HighlightableBuilder;
-import org.sonar.batch.source.SymbolizableBuilder;
import org.sonar.core.component.ScanGraph;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.core.issue.workflow.FunctionExecutor;
@@ -131,7 +129,6 @@ public class ProjectScanContainer extends ComponentContainer {
DefaultFileLinesContextFactory.class,
Caches.class,
ResourceCache.class,
- ComponentDataCache.class,
SourceDataFactory.class,
// file system
@@ -162,8 +159,6 @@ public class ProjectScanContainer extends ComponentContainer {
// lang
Languages.class,
DefaultLanguagesRepository.class,
- HighlightableBuilder.class,
- SymbolizableBuilder.class,
// Differential periods
PeriodsDefinition.class,
@@ -187,7 +182,7 @@ public class ProjectScanContainer extends ComponentContainer {
ProjectSettings.class,
// Report
- PublishReportJob.class,
+ ReportPublisher.class,
ComponentsPublisher.class,
IssuesPublisher.class,
MeasuresPublisher.class,
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 460a08831b3..a30037a1c00 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
@@ -26,6 +26,7 @@ import org.sonar.api.resources.File;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
+import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.index.ResourceKeyMigration;
import org.sonar.batch.index.ResourcePersister;
@@ -43,18 +44,20 @@ public class ComponentIndexer implements BatchComponent {
private final ResourceKeyMigration migration;
private final Project module;
private final ResourcePersister resourcePersister;
+ private final ResourceCache resourceCache;
- public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, @Nullable ResourceKeyMigration migration,
+ public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceCache resourceCache, @Nullable ResourceKeyMigration migration,
@Nullable ResourcePersister resourcePersister) {
this.module = module;
this.languages = languages;
this.sonarIndex = sonarIndex;
+ this.resourceCache = resourceCache;
this.migration = migration;
this.resourcePersister = resourcePersister;
}
- public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex) {
- this(module, languages, sonarIndex, null, null);
+ public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceCache resourceCache) {
+ this(module, languages, sonarIndex, resourceCache, null, null);
}
public void execute(DefaultModuleFileSystem fs) {
@@ -74,6 +77,7 @@ public class ComponentIndexer implements BatchComponent {
boolean unitTest = InputFile.Type.TEST == inputFile.type();
Resource sonarFile = File.create(inputFile.relativePath(), languages.get(languageKey), unitTest);
sonarIndex.index(sonarFile);
+ resourceCache.get(sonarFile).setInputPath(inputFile);
}
if (resourcePersister != null) {
@@ -81,5 +85,4 @@ public class ComponentIndexer implements BatchComponent {
resourcePersister.persist();
}
}
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
index c5eb6bef9b4..fbc40556475 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileIndexer.java
@@ -37,17 +37,8 @@ import org.sonar.batch.util.ProgressReport;
import java.io.File;
import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
+import java.util.*;
+import java.util.concurrent.*;
/**
* Index input files into {@link InputPathCache}.
@@ -63,15 +54,13 @@ public class FileIndexer implements BatchComponent {
private final boolean isAggregator;
private final ExclusionFilters exclusionFilters;
private final InputFileBuilderFactory inputFileBuilderFactory;
- private final InputPathCache inputPathCache;
private ProgressReport progressReport;
private ExecutorService executorService;
private List<Future<Void>> tasks;
public FileIndexer(List<InputFileFilter> filters, ExclusionFilters exclusionFilters, InputFileBuilderFactory inputFileBuilderFactory,
- ProjectDefinition def, InputPathCache inputPathCache) {
- this.inputPathCache = inputPathCache;
+ ProjectDefinition def) {
this.filters = filters;
this.exclusionFilters = exclusionFilters;
this.inputFileBuilderFactory = inputFileBuilderFactory;
@@ -154,12 +143,11 @@ public class FileIndexer implements BatchComponent {
tasks.add(executorService.submit(new Callable<Void>() {
@Override
public Void call() {
- InputFileMetadata metadata = inputFileBuilder.completeAndComputeMetadata(inputFile, type);
- if (metadata != null && accept(inputFile)) {
- fs.add(inputFile);
- status.markAsIndexed(inputFile);
- inputPathCache.put(inputFile.moduleKey(), inputFile.relativePath(), metadata);
- File parentDir = inputFile.file().getParentFile();
+ DeprecatedDefaultInputFile completedInputFile = inputFileBuilder.completeAndComputeMetadata(inputFile, type);
+ if (completedInputFile != null && accept(completedInputFile)) {
+ fs.add(completedInputFile);
+ status.markAsIndexed(completedInputFile);
+ File parentDir = completedInputFile.file().getParentFile();
String relativePath = new PathResolver().relativePath(fs.baseDir(), parentDir);
if (relativePath != null) {
DefaultInputDir inputDir = new DefaultInputDir(fs.moduleKey(), relativePath);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
index 2077e91d578..e58d5625296 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilder.java
@@ -25,6 +25,7 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@@ -92,7 +93,7 @@ class InputFileBuilder {
* Optimization to not compute InputFile metadata if the file is excluded from analysis.
*/
@CheckForNull
- InputFileMetadata completeAndComputeMetadata(DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
+ DeprecatedDefaultInputFile completeAndComputeMetadata(DeprecatedDefaultInputFile inputFile, InputFile.Type type) {
inputFile.setType(type);
inputFile.setModuleBaseDir(fs.baseDir().toPath());
inputFile.setCharset(fs.encoding());
@@ -103,22 +104,13 @@ class InputFileBuilder {
}
inputFile.setLanguage(lang);
- InputFileMetadata result = new InputFileMetadata();
+ inputFile.initMetadata(fileMetadata.readMetadata(inputFile.file(), fs.encoding()));
- FileMetadata.Metadata metadata = fileMetadata.read(inputFile.file(), fs.encoding());
- inputFile.setLines(metadata.lines);
- inputFile.setLastValidOffset(metadata.lastValidOffset);
-
- result.setNonBlankLines(metadata.nonBlankLines);
- result.setHash(metadata.hash);
- result.setOriginalLineOffsets(metadata.originalLineOffsets);
- result.setEmpty(metadata.empty);
-
- inputFile.setStatus(statusDetection.status(inputFile.moduleKey(), inputFile.relativePath(), metadata.hash));
+ inputFile.setStatus(statusDetection.status(inputFile.moduleKey(), inputFile.relativePath(), inputFile.hash()));
if (analysisMode.isIncremental() && inputFile.status() == InputFile.Status.SAME) {
return null;
}
- return result;
+ return inputFile;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
index c173975fc53..74685bd7955 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactory.java
@@ -19,6 +19,8 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileMetadata.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileMetadata.java
deleted file mode 100644
index f37c672d101..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputFileMetadata.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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 java.io.Serializable;
-
-/**
- * Additional input file metadata that are stored in a disk storage to save memory
- */
-public class InputFileMetadata implements Serializable {
-
- private String hash;
- private int nonBlankLines;
- private int[] originalLineOffsets;
- private boolean empty;
-
- /**
- * Digest hash of the file.
- */
- public String hash() {
- return hash;
- }
-
- public int nonBlankLines() {
- return nonBlankLines;
- }
-
- public int[] originalLineOffsets() {
- return originalLineOffsets;
- }
-
- public InputFileMetadata setHash(String hash) {
- this.hash = hash;
- return this;
- }
-
- public InputFileMetadata setNonBlankLines(int nonBlankLines) {
- this.nonBlankLines = nonBlankLines;
- return this;
- }
-
- public InputFileMetadata setOriginalLineOffsets(int[] originalLineOffsets) {
- this.originalLineOffsets = originalLineOffsets;
- return this;
- }
-
- public boolean isEmpty() {
- return this.empty;
- }
-
- public InputFileMetadata setEmpty(boolean empty) {
- this.empty = empty;
- return this;
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
index 22cbe41124f..92423f3a25d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
@@ -25,7 +25,6 @@ import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputPath;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.batch.index.BatchResource;
import javax.annotation.CheckForNull;
@@ -40,7 +39,6 @@ public class InputPathCache implements BatchComponent {
private final Map<String, SortedMap<String, InputFile>> inputFileCache = new LinkedHashMap<>();
private final Map<String, SortedMap<String, InputDir>> inputDirCache = new LinkedHashMap<>();
- private final Map<String, Map<String, InputFileMetadata>> inputFileMetadataCache = new LinkedHashMap<>();
public Iterable<InputFile> allFiles() {
return Iterables.concat(Iterables.transform(inputFileCache.values(), new Function<Map<String, InputFile>, Collection<InputFile>>() {
@@ -77,7 +75,6 @@ public class InputPathCache implements BatchComponent {
public InputPathCache removeModule(String moduleKey) {
inputFileCache.remove(moduleKey);
inputDirCache.remove(moduleKey);
- inputFileMetadataCache.remove(moduleKey);
return this;
}
@@ -85,9 +82,6 @@ public class InputPathCache implements BatchComponent {
if (inputFileCache.containsKey(moduleKey)) {
inputFileCache.get(moduleKey).remove(inputFile.relativePath());
}
- if (inputFileMetadataCache.containsKey(moduleKey)) {
- inputFileMetadataCache.get(moduleKey).remove(inputFile.relativePath());
- }
return this;
}
@@ -106,14 +100,6 @@ public class InputPathCache implements BatchComponent {
return this;
}
- public synchronized InputPathCache put(String moduleKey, String relativePath, InputFileMetadata metadata) {
- if (!inputFileMetadataCache.containsKey(moduleKey)) {
- inputFileMetadataCache.put(moduleKey, new HashMap<String, InputFileMetadata>());
- }
- inputFileMetadataCache.get(moduleKey).put(relativePath, metadata);
- return this;
- }
-
public InputPathCache put(String moduleKey, InputDir inputDir) {
if (!inputDirCache.containsKey(moduleKey)) {
inputDirCache.put(moduleKey, new TreeMap<String, InputDir>());
@@ -131,18 +117,6 @@ public class InputPathCache implements BatchComponent {
}
@CheckForNull
- public InputFileMetadata getFileMetadata(String moduleKey, String relativePath) {
- if (inputFileMetadataCache.containsKey(moduleKey)) {
- return inputFileMetadataCache.get(moduleKey).get(relativePath);
- }
- return null;
- }
-
- public InputFileMetadata getFileMetadata(DefaultInputFile inputFile) {
- return getFileMetadata(inputFile.moduleKey(), inputFile.relativePath());
- }
-
- @CheckForNull
public InputDir getDir(String moduleKey, String relativePath) {
if (inputDirCache.containsKey(moduleKey)) {
return inputDirCache.get(moduleKey).get(relativePath);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
index 8795742ba5b..54fd33a6f40 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
@@ -33,8 +33,7 @@ import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.input.FileData;
import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.batch.report.PublishReportJob;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.scan.filesystem.InputPathCache;
import java.util.LinkedList;
@@ -48,18 +47,16 @@ public final class ScmSensor implements Sensor {
private final ScmConfiguration configuration;
private final FileSystem fs;
private final ProjectRepositories projectReferentials;
- private final InputPathCache inputPathCache;
private final ResourceCache resourceCache;
- private final PublishReportJob publishReportJob;
+ private final ReportPublisher publishReportJob;
public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration,
ProjectRepositories projectReferentials, FileSystem fs, InputPathCache inputPathCache, ResourceCache resourceCache,
- PublishReportJob publishReportJob) {
+ ReportPublisher publishReportJob) {
this.projectDefinition = projectDefinition;
this.configuration = configuration;
this.projectReferentials = projectReferentials;
this.fs = fs;
- this.inputPathCache = inputPathCache;
this.resourceCache = resourceCache;
this.publishReportJob = publishReportJob;
}
@@ -96,7 +93,7 @@ public final class ScmSensor implements Sensor {
LOG.warn("Forced reloading of SCM data for all files.");
}
List<InputFile> filesToBlame = new LinkedList<InputFile>();
- for (InputFile f : inputPathCache.allFiles()) {
+ for (InputFile f : fs.inputFiles(fs.predicates().all())) {
if (configuration.forceReloadAll()) {
addIfNotEmpty(filesToBlame, (DefaultInputFile) f);
} else {
@@ -110,8 +107,7 @@ public final class ScmSensor implements Sensor {
}
private void addIfNotEmpty(List<InputFile> filesToBlame, DefaultInputFile f) {
- InputFileMetadata metadata = inputPathCache.getFileMetadata(f);
- if (!metadata.isEmpty()) {
+ if (!f.isEmpty()) {
filesToBlame.add(f);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
index cf2930a72fe..724c900176e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java
@@ -19,73 +19,74 @@
*/
package org.sonar.batch.sensor;
+import com.google.common.base.Function;
import com.google.common.base.Preconditions;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputDir;
+import com.google.common.collect.Iterables;
+import org.sonar.api.batch.fs.*;
import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
+import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.Issue.Severity;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.measures.Formula;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.measures.SumChildDistributionFormula;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.Scopes;
+import org.sonar.api.resources.*;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.source.Symbol;
import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
import org.sonar.batch.index.BatchResource;
-import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.issue.ModuleIssues;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.Range;
+import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting.HighlightingRule;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.report.BatchReportUtils;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.sensor.coverage.CoverageExclusions;
+import org.sonar.batch.source.DefaultSymbol;
import org.sonar.core.component.ComponentKeys;
-import org.sonar.core.source.SnapshotDataTypes;
+
+import java.util.Map;
+import java.util.Set;
public class DefaultSensorStorage implements SensorStorage {
private static final String USES = "USES";
private final MetricFinder metricFinder;
private final Project project;
- private final ResourcePerspectives perspectives;
+ private final ModuleIssues moduleIssues;
private final DefaultIndex sonarIndex;
private final CoverageExclusions coverageExclusions;
private final DuplicationCache duplicationCache;
private final ResourceCache resourceCache;
- private final ComponentDataCache componentDataCache;
+ private final ReportPublisher reportPublisher;
- public DefaultSensorStorage(MetricFinder metricFinder, Project project,
- ResourcePerspectives perspectives,
- Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache,
- DuplicationCache duplicationCache, DefaultIndex sonarIndex, CoverageExclusions coverageExclusions,
- ResourceCache resourceCache) {
+ public DefaultSensorStorage(MetricFinder metricFinder, Project project, ModuleIssues moduleIssues,
+ Settings settings, FileSystem fs, ActiveRules activeRules, DuplicationCache duplicationCache, DefaultIndex sonarIndex,
+ CoverageExclusions coverageExclusions, ResourceCache resourceCache, ReportPublisher reportPublisher) {
this.metricFinder = metricFinder;
this.project = project;
- this.perspectives = perspectives;
- this.componentDataCache = componentDataCache;
+ this.moduleIssues = moduleIssues;
this.sonarIndex = sonarIndex;
this.coverageExclusions = coverageExclusions;
this.duplicationCache = duplicationCache;
this.resourceCache = resourceCache;
+ this.reportPublisher = reportPublisher;
}
private Metric findMetricOrFail(String metricKey) {
@@ -161,11 +162,7 @@ public class DefaultSensorStorage implements SensorStorage {
} else {
r = project;
}
- Issuable issuable = perspectives.as(Issuable.class, r);
- if (issuable == null) {
- return;
- }
- issuable.addIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
+ moduleIssues.initAndAddIssue(toDefaultIssue(project.getKey(), ComponentKeys.createEffectiveKey(project, r), issue));
}
public static DefaultIssue toDefaultIssue(String projectKey, String componentKey, Issue issue) {
@@ -246,7 +243,56 @@ public class DefaultSensorStorage implements SensorStorage {
@Override
public void store(DefaultHighlighting highlighting) {
- String componentKey = ((DefaultInputFile) highlighting.inputFile()).key();
- componentDataCache.setData(componentKey, SnapshotDataTypes.SYNTAX_HIGHLIGHTING, new SyntaxHighlightingData(highlighting.getSyntaxHighlightingRuleSet()));
+ BatchReportWriter writer = reportPublisher.getWriter();
+ DefaultInputFile inputFile = (DefaultInputFile) highlighting.inputFile();
+ writer.writeComponentSyntaxHighlighting(resourceCache.get(inputFile).batchId(),
+ Iterables.transform(highlighting.getSyntaxHighlightingRuleSet(), new Function<SyntaxHighlightingRule, HighlightingRule>() {
+ private HighlightingRule.Builder builder = HighlightingRule.newBuilder();
+ private Range.Builder rangeBuilder = Range.newBuilder();
+
+ @Override
+ public HighlightingRule apply(SyntaxHighlightingRule input) {
+ builder.clear();
+ rangeBuilder.clear();
+ builder.setRange(rangeBuilder.setStartLine(input.range().start().line())
+ .setStartOffset(input.range().start().lineOffset())
+ .setEndLine(input.range().end().line())
+ .setEndOffset(input.range().end().lineOffset())
+ .build());
+ builder.setType(BatchReportUtils.toProtocolType(input.getTextType()));
+ return builder.build();
+ }
+
+ }));
+ }
+
+ public void store(DefaultInputFile inputFile, Map<Symbol, Set<TextRange>> referencesBySymbol) {
+ BatchReportWriter writer = reportPublisher.getWriter();
+ writer.writeComponentSymbols(resourceCache.get(inputFile).batchId(),
+ Iterables.transform(referencesBySymbol.entrySet(), new Function<Map.Entry<Symbol, Set<TextRange>>, BatchReport.Symbols.Symbol>() {
+ private BatchReport.Symbols.Symbol.Builder builder = BatchReport.Symbols.Symbol.newBuilder();
+ private Range.Builder rangeBuilder = Range.newBuilder();
+
+ @Override
+ public BatchReport.Symbols.Symbol apply(Map.Entry<Symbol, Set<TextRange>> input) {
+ builder.clear();
+ rangeBuilder.clear();
+ DefaultSymbol symbol = (DefaultSymbol) input.getKey();
+ builder.setDeclaration(rangeBuilder.setStartLine(symbol.range().start().line())
+ .setStartOffset(symbol.range().start().lineOffset())
+ .setEndLine(symbol.range().end().line())
+ .setEndOffset(symbol.range().end().lineOffset())
+ .build());
+ for (TextRange reference : input.getValue()) {
+ builder.addReference(rangeBuilder.setStartLine(reference.start().line())
+ .setStartOffset(reference.start().lineOffset())
+ .setEndLine(reference.end().line())
+ .setEndOffset(reference.end().lineOffset())
+ .build());
+ }
+ return builder.build();
+ }
+
+ }));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizerSensor.java b/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizerSensor.java
new file mode 100644
index 00000000000..ea2314398c5
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizerSensor.java
@@ -0,0 +1,73 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.source;
+
+import org.sonar.api.batch.Phase;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting.HighlightingRule;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.report.ReportPublisher;
+import org.sonar.colorizer.CodeColorizer;
+
+import java.util.List;
+
+/**
+ * Execute deprecated {@link CodeColorizer} if necessary.
+ */
+@Phase(name = Phase.Name.POST)
+public final class CodeColorizerSensor implements Sensor {
+
+ private final ReportPublisher reportPublisher;
+ private final ResourceCache resourceCache;
+ private final CodeColorizers codeColorizers;
+
+ public CodeColorizerSensor(ReportPublisher reportPublisher, ResourceCache resourceCache, CodeColorizers codeColorizers) {
+ this.reportPublisher = reportPublisher;
+ this.resourceCache = resourceCache;
+ this.codeColorizers = codeColorizers;
+ }
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor.name("Code Colorizer Sensor")
+ .disabledInPreview();
+ }
+
+ @Override
+ public void execute(final SensorContext context) {
+ FileSystem fs = context.fileSystem();
+ for (InputFile f : fs.inputFiles(fs.predicates().all())) {
+ BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
+ int batchId = resourceCache.get(f).batchId();
+ List<HighlightingRule> highlightingRules = reader.readComponentSyntaxHighlighting(batchId);
+ String language = f.language();
+ if (!highlightingRules.isEmpty() || language == null) {
+ continue;
+ }
+ codeColorizers.toSyntaxHighlighting(f.file(), fs.encoding(), language, context.newHighlighting().onFile(f));
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizers.java b/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizers.java
index 4b99191538a..9f38c69c63f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizers.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/CodeColorizers.java
@@ -25,18 +25,14 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.web.CodeColorizerFormat;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
import org.sonar.colorizer.CodeColorizer;
import org.sonar.colorizer.Tokenizer;
import javax.annotation.CheckForNull;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
+import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
@@ -68,7 +64,7 @@ public class CodeColorizers implements BatchComponent {
}
@CheckForNull
- public SyntaxHighlightingData toSyntaxHighlighting(File file, Charset charset, String language) {
+ public void toSyntaxHighlighting(File file, Charset charset, String language, NewHighlighting highlighting) {
CodeColorizerFormat format = byLang.get(language);
List<Tokenizer> tokenizers;
if (format == null) {
@@ -77,13 +73,13 @@ public class CodeColorizers implements BatchComponent {
if ("java".equals(language)) {
tokenizers = CodeColorizer.Format.JAVA.getTokenizers();
} else {
- return null;
+ return;
}
} else {
tokenizers = format.getTokenizers();
}
try (Reader reader = new BufferedReader(new InputStreamReader(new BOMInputStream(new FileInputStream(file)), charset))) {
- return new HighlightingRenderer().render(reader, tokenizers);
+ new HighlightingRenderer().render(reader, tokenizers, highlighting);
} catch (Exception e) {
throw new IllegalStateException("Unable to read source file for colorization", e);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultHighlightable.java b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultHighlightable.java
index bef343b872a..741346dd99b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultHighlightable.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultHighlightable.java
@@ -19,64 +19,57 @@
*/
package org.sonar.batch.source;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.component.Component;
import org.sonar.api.source.Highlightable;
-import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.core.source.SnapshotDataTypes;
+import org.sonar.batch.deprecated.InputFileComponent;
/**
* @since 3.6
*/
public class DefaultHighlightable implements Highlightable {
- private final Component component;
- private final ComponentDataCache cache;
- private final SyntaxHighlightingDataBuilder builder;
+ private final DefaultInputFile inputFile;
+ private final SensorStorage sensorStorage;
- public DefaultHighlightable(Component component, ComponentDataCache cache) {
- this.component = component;
- this.cache = cache;
- this.builder = new SyntaxHighlightingDataBuilder();
+ public DefaultHighlightable(DefaultInputFile inputFile, SensorStorage sensorStorage) {
+ this.inputFile = inputFile;
+ this.sensorStorage = sensorStorage;
}
@Override
public HighlightingBuilder newHighlighting() {
- return new DefaultHighlightingBuilder(component.key(), cache, builder);
+ DefaultHighlighting defaultHighlighting = new DefaultHighlighting(sensorStorage);
+ defaultHighlighting.onFile(inputFile);
+ return new DefaultHighlightingBuilder(defaultHighlighting);
}
@Override
public Component component() {
- return component;
- }
-
- public SyntaxHighlightingDataBuilder getHighlightingRules() {
- return builder;
+ return new InputFileComponent(inputFile);
}
private static class DefaultHighlightingBuilder implements HighlightingBuilder {
- private final SyntaxHighlightingDataBuilder builder;
- private String componentKey;
- private ComponentDataCache cache;
+ private final DefaultHighlighting defaultHighlighting;
- public DefaultHighlightingBuilder(String componentKey, ComponentDataCache cache, SyntaxHighlightingDataBuilder builder) {
- this.componentKey = componentKey;
- this.cache = cache;
- this.builder = builder;
+ public DefaultHighlightingBuilder(DefaultHighlighting defaultHighlighting) {
+ this.defaultHighlighting = defaultHighlighting;
}
@Override
public HighlightingBuilder highlight(int startOffset, int endOffset, String typeOfText) {
TypeOfText type = org.sonar.api.batch.sensor.highlighting.TypeOfText.forCssClass(typeOfText);
- builder.registerHighlightingRule(startOffset, endOffset, type);
+ defaultHighlighting.highlight(startOffset, endOffset, type);
return this;
}
@Override
public void done() {
- cache.setData(componentKey, SnapshotDataTypes.SYNTAX_HIGHLIGHTING, builder.build());
+ defaultHighlighting.save();
}
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbol.java b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbol.java
index 0bca8bd9997..2ca34b67a9a 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbol.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbol.java
@@ -21,38 +21,47 @@
package org.sonar.batch.source;
import com.google.common.base.Objects;
+import org.sonar.api.batch.fs.TextRange;
import java.io.Serializable;
public class DefaultSymbol implements org.sonar.api.source.Symbol, Serializable {
- private final int declarationStartOffset;
- private final int declarationEndOffset;
+ private TextRange range;
+ private int length;
- public DefaultSymbol(int startOffset, int endOffset) {
- this.declarationStartOffset = startOffset;
- this.declarationEndOffset = endOffset;
+ public DefaultSymbol(TextRange range, int length) {
+ this.range = range;
+ this.length = length;
}
@Override
public int getDeclarationStartOffset() {
- return declarationStartOffset;
+ throw new UnsupportedOperationException("getDeclarationStartOffset");
}
@Override
public int getDeclarationEndOffset() {
- return declarationEndOffset;
+ throw new UnsupportedOperationException("getDeclarationEndOffset");
}
@Override
public String getFullyQualifiedName() {
- return null;
+ throw new UnsupportedOperationException("getFullyQualifiedName");
+ }
+
+ public TextRange range() {
+ return range;
+ }
+
+ public int getLength() {
+ return length;
}
@Override
public String toString() {
return Objects.toStringHelper("Symbol")
- .add("offset", String.format("%d-%d", declarationStartOffset, declarationEndOffset))
+ .add("range", range)
.toString();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java
index 18b3e06df6b..2ab9999bf1b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolTable.java
@@ -20,25 +20,22 @@
package org.sonar.batch.source;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.source.Symbol;
import org.sonar.api.source.Symbolizable;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import java.util.*;
public class DefaultSymbolTable implements Symbolizable.SymbolTable {
- private Map<Symbol, Set<Integer>> referencesBySymbol;
+ private Map<Symbol, Set<TextRange>> referencesBySymbol;
- private DefaultSymbolTable(Map<Symbol, Set<Integer>> referencesBySymbol) {
+ private DefaultSymbolTable(Map<Symbol, Set<TextRange>> referencesBySymbol) {
this.referencesBySymbol = referencesBySymbol;
}
- public Map<Symbol, Set<Integer>> getReferencesBySymbol() {
+ public Map<Symbol, Set<TextRange>> getReferencesBySymbol() {
return referencesBySymbol;
}
@@ -53,22 +50,28 @@ public class DefaultSymbolTable implements Symbolizable.SymbolTable {
@Override
public List<Integer> references(Symbol symbol) {
- return new ArrayList<Integer>(referencesBySymbol.get(symbol));
+ throw new UnsupportedOperationException("references");
}
public static class Builder implements Symbolizable.SymbolTableBuilder {
- private final Map<Symbol, Set<Integer>> referencesBySymbol = new LinkedHashMap<Symbol, Set<Integer>>();
- private final String componentKey;
+ private final Map<Symbol, Set<TextRange>> referencesBySymbol = new LinkedHashMap<Symbol, Set<TextRange>>();
+ private final DefaultInputFile inputFile;
- public Builder(String componentKey) {
- this.componentKey = componentKey;
+ public Builder(DefaultInputFile inputFile) {
+ this.inputFile = inputFile;
}
@Override
public Symbol newSymbol(int fromOffset, int toOffset) {
- Symbol symbol = new DefaultSymbol(fromOffset, toOffset);
- referencesBySymbol.put(symbol, new TreeSet<Integer>());
+ TextRange declarationRange = inputFile.newRange(fromOffset, toOffset);
+ DefaultSymbol symbol = new DefaultSymbol(declarationRange, toOffset - fromOffset);
+ referencesBySymbol.put(symbol, new TreeSet<TextRange>(new Comparator<TextRange>() {
+ @Override
+ public int compare(TextRange o1, TextRange o2) {
+ return o1.start().compareTo(o2.start());
+ }
+ }));
return symbol;
}
@@ -77,10 +80,12 @@ public class DefaultSymbolTable implements Symbolizable.SymbolTable {
if (!referencesBySymbol.containsKey(symbol)) {
throw new UnsupportedOperationException("Cannot add reference to a symbol in another file");
}
- if (fromOffset >= symbol.getDeclarationStartOffset() && fromOffset < symbol.getDeclarationEndOffset()) {
- throw new UnsupportedOperationException("Cannot add reference (" + fromOffset + ") overlapping " + symbol + " in " + componentKey);
+ TextRange referenceRange = inputFile.newRange(fromOffset, fromOffset + ((DefaultSymbol) symbol).getLength());
+
+ if (referenceRange.overlap(((DefaultSymbol) symbol).range())) {
+ throw new UnsupportedOperationException("Cannot add reference (" + fromOffset + ") overlapping " + symbol + " in " + inputFile.key());
}
- referencesBySymbol.get(symbol).add(fromOffset);
+ referencesBySymbol.get(symbol).add(referenceRange);
}
@Override
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java
index 8a6f6421408..037913f06cd 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/DefaultSymbolizable.java
@@ -20,35 +20,34 @@
package org.sonar.batch.source;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.component.Component;
import org.sonar.api.source.Symbolizable;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.symbol.SymbolData;
-import org.sonar.core.source.SnapshotDataTypes;
+import org.sonar.batch.deprecated.InputFileComponent;
+import org.sonar.batch.sensor.DefaultSensorStorage;
public class DefaultSymbolizable implements Symbolizable {
- private final ComponentDataCache cache;
- private final Component component;
+ private final DefaultInputFile inputFile;
+ private final DefaultSensorStorage sensorStorage;
- public DefaultSymbolizable(ComponentDataCache cache, Component component) {
- this.cache = cache;
- this.component = component;
+ public DefaultSymbolizable(DefaultInputFile inputFile, DefaultSensorStorage sensorStorage) {
+ this.inputFile = inputFile;
+ this.sensorStorage = sensorStorage;
}
@Override
public Component component() {
- return component;
+ return new InputFileComponent(inputFile);
}
@Override
public SymbolTableBuilder newSymbolTableBuilder() {
- return new DefaultSymbolTable.Builder(component.key());
+ return new DefaultSymbolTable.Builder(inputFile);
}
@Override
public void setSymbolTable(SymbolTable symbolTable) {
- SymbolData symbolData = new SymbolData(((DefaultSymbolTable) symbolTable).getReferencesBySymbol());
- cache.setData(component().key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING, symbolData);
+ sensorStorage.store(inputFile, ((DefaultSymbolTable) symbolTable).getReferencesBySymbol());
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightableBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightableBuilder.java
index d20fbebb147..fa9326a1604 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightableBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightableBuilder.java
@@ -20,10 +20,14 @@
package org.sonar.batch.source;
import com.google.common.collect.ImmutableSet;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.component.Component;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.source.Highlightable;
-import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
import org.sonar.core.component.PerspectiveBuilder;
import org.sonar.core.component.ResourceComponent;
@@ -31,27 +35,30 @@ import javax.annotation.CheckForNull;
import java.util.Set;
-/**
- * @since 3.6
- * @deprecated since 4.5 no more used in batch 2.0
- */
-@Deprecated
public class HighlightableBuilder extends PerspectiveBuilder<Highlightable> {
private static final Set<String> SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE);
- private final ComponentDataCache cache;
+ private final ResourceCache cache;
+ private final SensorStorage sensorStorage;
- public HighlightableBuilder(ComponentDataCache cache) {
+ public HighlightableBuilder(ResourceCache cache, SensorStorage sensorStorage) {
super(Highlightable.class);
this.cache = cache;
+ this.sensorStorage = sensorStorage;
}
@CheckForNull
@Override
- protected Highlightable loadPerspective(Class<Highlightable> perspectiveClass, Component component) {
+ public Highlightable loadPerspective(Class<Highlightable> perspectiveClass, Component component) {
boolean supported = SUPPORTED_QUALIFIERS.contains(component.qualifier());
if (supported && component instanceof ResourceComponent) {
- return new DefaultHighlightable(component, cache);
+ BatchResource batchComponent = cache.get(component.key());
+ if (batchComponent != null) {
+ InputFile path = (InputFile) batchComponent.inputPath();
+ if (path != null) {
+ return new DefaultHighlightable((DefaultInputFile) path, sensorStorage);
+ }
+ }
}
return null;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingCodeBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingCodeBuilder.java
index 8da5515fdaa..687f2fecc2d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingCodeBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingCodeBuilder.java
@@ -21,9 +21,8 @@ package org.sonar.batch.source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
import org.sonar.colorizer.HtmlCodeBuilder;
import java.util.regex.Matcher;
@@ -33,12 +32,16 @@ public class HighlightingCodeBuilder extends HtmlCodeBuilder {
private static final Logger LOG = LoggerFactory.getLogger(HighlightingCodeBuilder.class);
- private SyntaxHighlightingDataBuilder highlightingBuilder = new SyntaxHighlightingDataBuilder();
private int currentOffset = 0;
private static final Pattern START_TAG_PATTERN = Pattern.compile("<span class=\"(.+)\">");
private static final Pattern END_TAG_PATTERN = Pattern.compile("</span>");
private int startOffset = -1;
private String cssClass;
+ private final NewHighlighting highlighting;
+
+ public HighlightingCodeBuilder(NewHighlighting highlighting) {
+ this.highlighting = highlighting;
+ }
@Override
public Appendable append(CharSequence csq) {
@@ -67,7 +70,7 @@ public class HighlightingCodeBuilder extends HtmlCodeBuilder {
} else {
Matcher endMatcher = END_TAG_PATTERN.matcher(htmlTag);
if (endMatcher.matches()) {
- highlightingBuilder.registerHighlightingRule(startOffset, currentOffset, TypeOfText.forCssClass(cssClass));
+ highlighting.highlight(startOffset, currentOffset, TypeOfText.forCssClass(cssClass));
startOffset = -1;
} else {
LOG.warn("Expected to match highlighting end html tag but was: " + htmlTag);
@@ -85,8 +88,4 @@ public class HighlightingCodeBuilder extends HtmlCodeBuilder {
throw new UnsupportedOperationException();
}
- public SyntaxHighlightingData getHighlightingData() {
- return highlightingBuilder.build();
- }
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingRenderer.java b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingRenderer.java
index e2a5faa592e..6858d6de1f0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingRenderer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/HighlightingRenderer.java
@@ -19,7 +19,7 @@
*/
package org.sonar.batch.source;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
import org.sonar.channel.Channel;
import org.sonar.channel.CodeReader;
import org.sonar.colorizer.HtmlCodeBuilder;
@@ -31,14 +31,13 @@ import java.util.List;
public class HighlightingRenderer {
- public SyntaxHighlightingData render(Reader code, List<? extends Channel<HtmlCodeBuilder>> tokenizers) {
+ public void render(Reader code, List<? extends Channel<HtmlCodeBuilder>> tokenizers, NewHighlighting highlighting) {
List<Channel<HtmlCodeBuilder>> allTokenizers = new ArrayList<Channel<HtmlCodeBuilder>>();
- HighlightingCodeBuilder codeBuilder = new HighlightingCodeBuilder();
+ HighlightingCodeBuilder codeBuilder = new HighlightingCodeBuilder(highlighting);
allTokenizers.addAll(tokenizers);
new TokenizerDispatcher(allTokenizers).colorize(new CodeReader(code), codeBuilder);
-
- return codeBuilder.getHighlightingData();
+ highlighting.save();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java b/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java
index 5851824f169..a38d5c2df4f 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/LinesSensor.java
@@ -29,18 +29,10 @@ import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
-import org.sonar.batch.scan.filesystem.InputPathCache;
@Phase(name = Phase.Name.PRE)
public final class LinesSensor implements Sensor {
- private final InputPathCache inputPathCache;
-
- public LinesSensor(InputPathCache inputPathCache) {
- this.inputPathCache = inputPathCache;
- }
-
@Override
public void describe(SensorDescriptor descriptor) {
descriptor.name("Lines Sensor");
@@ -58,11 +50,10 @@ public final class LinesSensor implements Sensor {
.save();
if (f.language() == null) {
// As an approximation for files with no language plugin we consider every non blank line as ncloc
- InputFileMetadata metadata = inputPathCache.getFileMetadata((DefaultInputFile) f);
((DefaultMeasure<Integer>) context.<Integer>newMeasure()
.onFile(f)
.forMetric(CoreMetrics.NCLOC)
- .withValue(metadata.nonBlankLines()))
+ .withValue(((DefaultInputFile) f).nonBlankLines()))
.save();
// No test and no coverage on those files
((DefaultMeasure<Integer>) context.<Integer>newMeasure()
diff --git a/sonar-batch/src/main/java/org/sonar/batch/source/SymbolizableBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/source/SymbolizableBuilder.java
index 915dc285fa6..212c31d87b4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/source/SymbolizableBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/source/SymbolizableBuilder.java
@@ -20,22 +20,47 @@
package org.sonar.batch.source;
+import com.google.common.collect.ImmutableSet;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.component.Component;
+import org.sonar.api.resources.Qualifiers;
import org.sonar.api.source.Symbolizable;
-import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.sensor.DefaultSensorStorage;
import org.sonar.core.component.PerspectiveBuilder;
+import org.sonar.core.component.ResourceComponent;
+
+import javax.annotation.CheckForNull;
+
+import java.util.Set;
public class SymbolizableBuilder extends PerspectiveBuilder<Symbolizable> {
- private final ComponentDataCache cache;
+ private static final Set<String> SUPPORTED_QUALIFIERS = ImmutableSet.of(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE);
+ private final ResourceCache cache;
+ private final DefaultSensorStorage sensorStorage;
- public SymbolizableBuilder(ComponentDataCache cache) {
+ public SymbolizableBuilder(ResourceCache cache, DefaultSensorStorage sensorStorage) {
super(Symbolizable.class);
this.cache = cache;
+ this.sensorStorage = sensorStorage;
}
+ @CheckForNull
@Override
- protected Symbolizable loadPerspective(Class<Symbolizable> perspectiveClass, Component component) {
- return new DefaultSymbolizable(cache, component);
+ public Symbolizable loadPerspective(Class<Symbolizable> perspectiveClass, Component component) {
+ boolean supported = SUPPORTED_QUALIFIERS.contains(component.qualifier());
+ if (supported && component instanceof ResourceComponent) {
+ BatchResource batchComponent = cache.get(component.key());
+ if (batchComponent != null) {
+ InputFile path = (InputFile) batchComponent.inputPath();
+ if (path != null) {
+ return new DefaultSymbolizable((DefaultInputFile) path, sensorStorage);
+ }
+ }
+ }
+ return null;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java
deleted file mode 100644
index fb7b92dc038..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/symbol/DefaultSymbolTableBuilder.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.symbol;
-
-import org.sonar.api.source.Symbol;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.source.DefaultSymbol;
-import org.sonar.core.source.SnapshotDataTypes;
-
-import java.io.Serializable;
-import java.util.Comparator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-public class DefaultSymbolTableBuilder {
-
- private final String componentKey;
- private final ComponentDataCache cache;
- private final Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol = new LinkedHashMap<org.sonar.api.source.Symbol, Set<Integer>>();
-
- public DefaultSymbolTableBuilder(String componentKey, ComponentDataCache cache) {
- this.componentKey = componentKey;
- this.cache = cache;
- }
-
- public Symbol newSymbol(int fromOffset, int toOffset) {
- org.sonar.api.source.Symbol symbol = new DefaultSymbol(fromOffset, toOffset);
- referencesBySymbol.put(symbol, new TreeSet<Integer>());
- return symbol;
- }
-
- public void newReference(Symbol symbol, int fromOffset) {
- if (!referencesBySymbol.containsKey(symbol)) {
- throw new UnsupportedOperationException("Cannot add reference to a symbol in another file");
- }
- if (fromOffset >= symbol.getDeclarationStartOffset() && fromOffset < symbol.getDeclarationEndOffset()) {
- throw new UnsupportedOperationException("Cannot add reference (" + fromOffset + ") overlapping " + symbol);
- }
- referencesBySymbol.get(symbol).add(fromOffset);
- }
-
- public SymbolData build() {
- return new SymbolData(referencesBySymbol);
- }
-
- public void done() {
- cache.setData(componentKey, SnapshotDataTypes.SYMBOL_HIGHLIGHTING, build());
- }
-
- public static class SymbolComparator implements Comparator<Symbol>, Serializable {
- @Override
- public int compare(Symbol left, Symbol right) {
- return left.getDeclarationStartOffset() - right.getDeclarationStartOffset();
- }
- }
-
- public static class ReferenceComparator implements Comparator<Integer>, Serializable {
- @Override
- public int compare(Integer left, Integer right) {
- int result;
- if (left != null && right != null) {
- result = left - right;
- } else {
- result = left == null ? -1 : 1;
- }
- return result;
- }
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java b/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java
deleted file mode 100644
index 616429242ca..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/symbol/SymbolData.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.symbol;
-
-import org.sonar.api.source.Symbol;
-import org.sonar.batch.index.Data;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-public class SymbolData implements Data {
-
- public static final String FIELD_SEPARATOR = ",";
- public static final String SYMBOL_SEPARATOR = ";";
-
- private final Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol;
-
- public SymbolData(Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol) {
- this.referencesBySymbol = referencesBySymbol;
- }
-
- public Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol() {
- return referencesBySymbol;
- }
-
- @Override
- public String writeString() {
- StringBuilder sb = new StringBuilder();
-
- for (Symbol symbol : referencesBySymbol.keySet()) {
- if (sb.length() > 0) {
- sb.append(SYMBOL_SEPARATOR);
- }
-
- sb.append(symbol.getDeclarationStartOffset())
- .append(FIELD_SEPARATOR)
- .append(symbol.getDeclarationEndOffset())
- .append(FIELD_SEPARATOR)
- .append(symbol.getDeclarationStartOffset());
- Collection<Integer> symbolReferences = referencesBySymbol.get(symbol);
- for (Integer symbolReference : symbolReferences) {
- sb.append(FIELD_SEPARATOR).append(symbolReference);
- }
- }
-
- return sb.toString();
- }
-
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilderTest.java
deleted file mode 100644
index b4c4828b204..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilderTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.highlighting;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
-
-import java.util.Collection;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
-
-public class SyntaxHighlightingDataBuilderTest {
-
- private Collection<SyntaxHighlightingRule> highlightingRules;
-
- @Rule
- public ExpectedException throwable = ExpectedException.none();
-
- @Before
- public void setUpSampleRules() {
-
- SyntaxHighlightingDataBuilder highlightingDataBuilder = new SyntaxHighlightingDataBuilder();
- highlightingDataBuilder.registerHighlightingRule(0, 10, COMMENT);
- highlightingDataBuilder.registerHighlightingRule(10, 12, KEYWORD);
- highlightingDataBuilder.registerHighlightingRule(24, 38, KEYWORD);
- highlightingDataBuilder.registerHighlightingRule(42, 50, KEYWORD);
- highlightingDataBuilder.registerHighlightingRule(24, 65, CPP_DOC);
- highlightingDataBuilder.registerHighlightingRule(12, 20, COMMENT);
-
- highlightingRules = highlightingDataBuilder.getSyntaxHighlightingRuleSet();
- }
-
- @Test
- public void should_register_highlighting_rule() throws Exception {
- assertThat(highlightingRules).hasSize(6);
- }
-
- @Test
- public void should_order_by_start_then_end_offset() throws Exception {
- assertThat(highlightingRules).extracting("startPosition").containsOnly(0, 10, 12, 24, 24, 42);
- assertThat(highlightingRules).extracting("endPosition").containsOnly(10, 12, 20, 38, 65, 50);
- assertThat(highlightingRules).extracting("textType").containsOnly(COMMENT, KEYWORD, COMMENT, KEYWORD, CPP_DOC, KEYWORD);
- }
-
- @Test
- public void should_suport_overlapping() throws Exception {
- SyntaxHighlightingDataBuilder builder = new SyntaxHighlightingDataBuilder();
- builder.registerHighlightingRule(0, 15, KEYWORD);
- builder.registerHighlightingRule(8, 12, CPP_DOC);
- builder.build();
- }
-
- @Test
- public void should_prevent_boudaries_overlapping() throws Exception {
- throwable.expect(IllegalStateException.class);
- throwable.expectMessage("Cannot register highlighting rule for characters from 8 to 15 as it overlaps at least one existing rule");
-
- SyntaxHighlightingDataBuilder builder = new SyntaxHighlightingDataBuilder();
- builder.registerHighlightingRule(0, 10, KEYWORD);
- builder.registerHighlightingRule(8, 15, KEYWORD);
- builder.build();
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataTest.java b/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataTest.java
deleted file mode 100644
index dcebfe2893e..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/highlighting/SyntaxHighlightingDataTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.highlighting;
-
-import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
-
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.COMMENT;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.CPP_DOC;
-import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
-
-public class SyntaxHighlightingDataTest {
-
- @Test
- public void should_serialize_rules_to_string() throws Exception {
-
- List<SyntaxHighlightingRule> orderedHighlightingRules = Lists.newArrayList(
- SyntaxHighlightingRule.create(0, 10, COMMENT),
- SyntaxHighlightingRule.create(10, 12, KEYWORD),
- SyntaxHighlightingRule.create(12, 20, COMMENT),
- SyntaxHighlightingRule.create(24, 38, KEYWORD),
- SyntaxHighlightingRule.create(24, 65, CPP_DOC),
- SyntaxHighlightingRule.create(42, 50, KEYWORD)
- );
-
- String serializedRules = new SyntaxHighlightingData(orderedHighlightingRules).writeString();
- assertThat(serializedRules).isEqualTo("0,10,cd;10,12,k;12,20,cd;24,38,k;24,65,cppd;42,50,k");
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java
deleted file mode 100644
index 5fa9587f424..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.index;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ComponentDataCacheTest {
-
- @ClassRule
- public static TemporaryFolder temp = new TemporaryFolder();
-
- Caches caches;
-
- @Before
- public void start() throws Exception {
- caches = CachesTest.createCacheOnTemp(temp);
- caches.start();
- }
-
- @After
- public void stop() {
- caches.stop();
- }
-
- @Test
- public void should_get_and_set_string_data() {
- ComponentDataCache cache = new ComponentDataCache(caches);
- cache.setStringData("org/struts/Action.java", "SYNTAX", "1:foo;3:bar");
- assertThat(cache.getStringData("org/struts/Action.java", "SYNTAX")).isEqualTo("1:foo;3:bar");
- assertThat(cache.getStringData("org/struts/Action.java", "OTHER")).isNull();
- assertThat(cache.getStringData("Other.java", "SYNTAX")).isNull();
- assertThat(cache.getStringData("Other.java", "OTHER")).isNull();
- }
-
- @Test
- public void should_get_and_set_data() {
- ComponentDataCache cache = new ComponentDataCache(caches);
- cache.setData("org/struts/Action.java", "COUNT", new LongData(1234L));
- LongData count = cache.getData("org/struts/Action.java", "COUNT");
- assertThat(count.data()).isEqualTo(1234L);
- }
-
- static class LongData implements Data {
-
- private long data;
-
- LongData() {
- }
-
- LongData(long data) {
- this.data = data;
- }
-
- public long data() {
- return data;
- }
-
- @Override
- public String writeString() {
- return String.valueOf(data);
- }
-
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
index a37bef0da56..50a2554aa37 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
@@ -30,23 +30,18 @@ import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
-import org.sonar.api.source.Symbol;
import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
+import org.sonar.batch.protocol.Constants.HighlightingType;
+import org.sonar.batch.protocol.output.*;
+import org.sonar.batch.protocol.output.BatchReport.Range;
import org.sonar.batch.protocol.output.BatchReport.Scm;
import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
-import org.sonar.batch.protocol.output.BatchReportWriter;
-import org.sonar.batch.report.PublishReportJob;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
+import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting.HighlightingRule;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.batch.source.CodeColorizers;
-import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
-import org.sonar.core.source.SnapshotDataTypes;
import org.sonar.server.source.db.FileSourceDb;
import java.io.File;
@@ -64,24 +59,23 @@ public class SourceDataFactoryTest {
public TemporaryFolder temp = new TemporaryFolder();
private MeasureCache measureCache = mock(MeasureCache.class);
- private ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
private DuplicationCache duplicationCache = mock(DuplicationCache.class);
- private CodeColorizers colorizers = mock(CodeColorizers.class);
private DefaultInputFile inputFile;
- private InputFileMetadata metadata;
private SourceDataFactory sut;
private FileSourceDb.Data.Builder output;
private File reportDir;
+ private BatchReportWriter batchReportWriter;
@Before
public void setUp() throws Exception {
- PublishReportJob publishReportJob = mock(PublishReportJob.class);
+ ReportPublisher reportPublisher = mock(ReportPublisher.class);
reportDir = temp.newFolder();
- when(publishReportJob.getReportDir()).thenReturn(reportDir);
+ batchReportWriter = new BatchReportWriter(reportDir);
+ when(reportPublisher.getReportDir()).thenReturn(reportDir);
ResourceCache resourceCache = new ResourceCache();
resourceCache.add(org.sonar.api.resources.File.create("src/Foo.java").setEffectiveKey("module_key:src/Foo.java"), null);
when(measureCache.byMetric(anyString(), anyString())).thenReturn(Collections.<Measure>emptyList());
- sut = new SourceDataFactory(measureCache, componentDataCache, duplicationCache, colorizers, publishReportJob, resourceCache);
+ sut = new SourceDataFactory(measureCache, duplicationCache, reportPublisher, resourceCache);
// generate a file with 3 lines
File baseDir = temp.newFolder();
DefaultFileSystem fs = new DefaultFileSystem(baseDir.toPath());
@@ -89,7 +83,6 @@ public class SourceDataFactoryTest {
.setLines(3)
.setCharset(Charsets.UTF_8);
fs.add(inputFile);
- metadata = new InputFileMetadata();
FileUtils.write(inputFile.file(), "one\ntwo\nthree\n");
output = sut.createForSource(inputFile);
when(duplicationCache.byComponent(anyString())).thenReturn(Collections.<DefaultDuplication>emptyList());
@@ -106,7 +99,7 @@ public class SourceDataFactoryTest {
@Test
public void consolidateData() throws Exception {
- byte[] bytes = sut.consolidateData(inputFile, metadata);
+ byte[] bytes = sut.consolidateData(inputFile);
assertThat(bytes).isNotEmpty();
}
@@ -247,9 +240,7 @@ public class SourceDataFactoryTest {
@Test
public void applyHighlighting_missing() throws Exception {
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(null);
-
- sut.applyHighlighting(inputFile, metadata, output);
+ sut.applyHighlighting(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).hasHighlighting()).isFalse();
@@ -259,49 +250,28 @@ public class SourceDataFactoryTest {
@Test
public void applyHighlighting() throws Exception {
- SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
- .registerHighlightingRule(0, 4, TypeOfText.ANNOTATION)
- .registerHighlightingRule(4, 5, TypeOfText.COMMENT)
- .registerHighlightingRule(7, 16, TypeOfText.CONSTANT)
- .build();
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(highlighting);
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
-
- sut.applyHighlighting(inputFile, metadata, output);
+ batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
+ newRule(1, 0, 1, 4, HighlightingType.ANNOTATION),
+ newRule(2, 0, 2, 1, HighlightingType.COMMENT),
+ newRule(3, 1, 3, 9, HighlightingType.CONSTANT)));
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
+ sut.applyHighlighting(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,4,a");
assertThat(data.getLines(1).getHighlighting()).isEqualTo("0,1,cd");
- assertThat(data.getLines(2).getHighlighting()).isEqualTo("0,9,c");
- }
-
- @Test
- public void applyHighlighting_ignore_bad_line() throws Exception {
- SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
- .registerHighlightingRule(0, 4, TypeOfText.ANNOTATION)
- .registerHighlightingRule(4, 5, TypeOfText.COMMENT)
- .registerHighlightingRule(7, 25, TypeOfText.CONSTANT)
- .build();
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(highlighting);
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7, 15});
-
- sut.applyHighlighting(inputFile, metadata, output);
-
- FileSourceDb.Data data = output.build();
- assertThat(data.getLinesCount()).isEqualTo(3);
+ assertThat(data.getLines(2).getHighlighting()).isEqualTo("1,9,c");
}
@Test
public void applyHighlighting_multiple_lines() throws Exception {
- SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
- .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
- .registerHighlightingRule(4, 9, TypeOfText.COMMENT)
- .registerHighlightingRule(10, 16, TypeOfText.CONSTANT)
- .build();
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(highlighting);
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
+ batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
+ newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
+ newRule(2, 0, 3, 2, HighlightingType.COMMENT),
+ newRule(3, 3, 3, 9, HighlightingType.CONSTANT)));
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
- sut.applyHighlighting(inputFile, metadata, output);
+ sut.applyHighlighting(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
@@ -311,16 +281,15 @@ public class SourceDataFactoryTest {
@Test
public void applyHighlighting_nested_rules() throws Exception {
- SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
- .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
- .registerHighlightingRule(4, 6, TypeOfText.COMMENT)
- .registerHighlightingRule(7, 16, TypeOfText.CONSTANT)
- .registerHighlightingRule(8, 15, TypeOfText.KEYWORD)
- .build();
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(highlighting);
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
+ batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
+ newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
+ newRule(2, 0, 2, 2, HighlightingType.COMMENT),
+ newRule(3, 0, 3, 9, HighlightingType.CONSTANT),
+ newRule(3, 1, 3, 8, HighlightingType.KEYWORD)));
+
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
- sut.applyHighlighting(inputFile, metadata, output);
+ sut.applyHighlighting(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
@@ -330,16 +299,15 @@ public class SourceDataFactoryTest {
@Test
public void applyHighlighting_nested_rules_and_multiple_lines() throws Exception {
- SyntaxHighlightingData highlighting = new SyntaxHighlightingDataBuilder()
- .registerHighlightingRule(0, 3, TypeOfText.ANNOTATION)
- .registerHighlightingRule(4, 6, TypeOfText.COMMENT)
- .registerHighlightingRule(4, 16, TypeOfText.CONSTANT)
- .registerHighlightingRule(8, 15, TypeOfText.KEYWORD)
- .build();
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYNTAX_HIGHLIGHTING)).thenReturn(highlighting);
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
+ batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
+ newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
+ newRule(2, 0, 3, 9, HighlightingType.CONSTANT),
+ newRule(2, 0, 2, 2, HighlightingType.COMMENT),
+ newRule(3, 1, 3, 8, HighlightingType.KEYWORD)));
- sut.applyHighlighting(inputFile, metadata, output);
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
+
+ sut.applyHighlighting(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
@@ -347,11 +315,26 @@ public class SourceDataFactoryTest {
assertThat(data.getLines(2).getHighlighting()).isEqualTo("0,9,c;1,8,k");
}
+ private HighlightingRule newRule(int startLine, int startOffset, int endLine, int endOffset, HighlightingType type) {
+ return BatchReport.SyntaxHighlighting.HighlightingRule.newBuilder()
+ .setRange(Range.newBuilder().setStartLine(startLine).setStartOffset(startOffset).setEndLine(endLine).setEndOffset(endOffset).build())
+ .setType(type)
+ .build();
+ }
+
+ private BatchReport.Symbols.Symbol newSymbol(int startLine, int startOffset, int endLine, int endOffset,
+ int startLine1, int startOffset1, int endLine1, int endOffset1,
+ int startLine2, int startOffset2, int endLine2, int endOffset2) {
+ return BatchReport.Symbols.Symbol.newBuilder()
+ .setDeclaration(Range.newBuilder().setStartLine(startLine).setStartOffset(startOffset).setEndLine(endLine).setEndOffset(endOffset).build())
+ .addReference(Range.newBuilder().setStartLine(startLine1).setStartOffset(startOffset1).setEndLine(endLine1).setEndOffset(endOffset1).build())
+ .addReference(Range.newBuilder().setStartLine(startLine2).setStartOffset(startOffset2).setEndLine(endLine2).setEndOffset(endOffset2).build())
+ .build();
+ }
+
@Test
public void applySymbolReferences_missing() throws Exception {
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING)).thenReturn(null);
-
- sut.applySymbolReferences(inputFile, metadata, output);
+ sut.applySymbolReferences(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).hasSymbols()).isFalse();
@@ -361,17 +344,17 @@ public class SourceDataFactoryTest {
@Test
public void applySymbolReferences() throws Exception {
- DefaultSymbolTableBuilder symbolBuilder = new DefaultSymbolTableBuilder(inputFile.key(), null);
- Symbol s1 = symbolBuilder.newSymbol(1, 2);
- symbolBuilder.newReference(s1, 4);
- symbolBuilder.newReference(s1, 11);
- Symbol s2 = symbolBuilder.newSymbol(4, 6);
- symbolBuilder.newReference(s2, 0);
- symbolBuilder.newReference(s2, 7);
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING)).thenReturn(symbolBuilder.build());
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
-
- sut.applySymbolReferences(inputFile, metadata, output);
+ batchReportWriter.writeComponentSymbols(1, Arrays.asList(
+ newSymbol(1, 1, 1, 2,
+ 2, 0, 2, 1,
+ 3, 4, 3, 5),
+ newSymbol(2, 0, 2, 2,
+ 1, 0, 1, 2,
+ 3, 0, 3, 2)
+ ));
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
+
+ sut.applySymbolReferences(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getSymbols()).isEqualTo("1,2,1;0,2,2");
@@ -381,17 +364,18 @@ public class SourceDataFactoryTest {
@Test
public void applySymbolReferences_declaration_order_is_not_important() throws Exception {
- DefaultSymbolTableBuilder symbolBuilder = new DefaultSymbolTableBuilder(inputFile.key(), null);
- Symbol s2 = symbolBuilder.newSymbol(4, 6);
- symbolBuilder.newReference(s2, 7);
- symbolBuilder.newReference(s2, 0);
- Symbol s1 = symbolBuilder.newSymbol(1, 2);
- symbolBuilder.newReference(s1, 11);
- symbolBuilder.newReference(s1, 4);
- when(componentDataCache.getData(inputFile.key(), SnapshotDataTypes.SYMBOL_HIGHLIGHTING)).thenReturn(symbolBuilder.build());
- metadata.setOriginalLineOffsets(new int[] {0, 4, 7});
-
- sut.applySymbolReferences(inputFile, metadata, output);
+ batchReportWriter.writeComponentSymbols(1, Arrays.asList(
+ newSymbol(2, 0, 2, 2,
+ 1, 0, 1, 2,
+ 3, 0, 3, 2),
+ newSymbol(1, 1, 1, 2,
+ 2, 0, 2, 1,
+ 3, 4, 3, 5)
+
+ ));
+ inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
+
+ sut.applySymbolReferences(inputFile, output);
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getSymbols()).isEqualTo("1,2,1;0,2,2");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java
index e4dc6d3099f..a0021e72025 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java
@@ -44,7 +44,6 @@ import org.sonar.api.rules.RuleFinder;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.System2;
import org.sonar.batch.issue.IssueCache;
-import org.sonar.batch.scan.filesystem.InputFileMetadata;
import org.sonar.batch.scan.filesystem.InputPathCache;
import org.sonar.core.issue.IssueUpdater;
import org.sonar.core.issue.db.IssueChangeDto;
@@ -60,19 +59,8 @@ import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyCollection;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.RETURNS_MOCKS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.*;
public class IssueTrackingDecoratorTest {
@@ -132,7 +120,6 @@ public class IssueTrackingDecoratorTest {
List<ServerIssue> dbIssues = Collections.emptyList();
when(initialOpenIssues.selectAndRemoveIssues("struts:Action.java")).thenReturn(dbIssues);
when(inputPathCache.getFile("foo", "Action.java")).thenReturn(mock(DefaultInputFile.class));
- when(inputPathCache.getFileMetadata("foo", "Action.java")).thenReturn(new InputFileMetadata());
decorator.doDecorate(file);
// Apply filters, track, apply transitions, notify extensions then update cache
@@ -161,7 +148,6 @@ public class IssueTrackingDecoratorTest {
when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult);
when(inputPathCache.getFile("foo", "Action.java")).thenReturn(mock(DefaultInputFile.class));
- when(inputPathCache.getFileMetadata("foo", "Action.java")).thenReturn(new InputFileMetadata());
decorator.doDecorate(file);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
index 42f7bfc8330..8b42d6a5b67 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
@@ -71,7 +71,7 @@ public class HighlightingMediumTest {
File xooFile = new File(srcDir, "sample.xoo");
File xoohighlightingFile = new File(srcDir, "sample.xoo.highlighting");
- FileUtils.write(xooFile, "Sample xoo\ncontent");
+ FileUtils.write(xooFile, "Sample xoo\ncontent plop");
FileUtils.write(xoohighlightingFile, "0:10:s\n11:18:k");
TaskResult result = tester.newTask()
@@ -87,10 +87,10 @@ public class HighlightingMediumTest {
.start();
InputFile file = result.inputFile("src/sample.xoo");
- assertThat(result.highlightingTypeFor(file, 0)).containsExactly(TypeOfText.STRING);
- assertThat(result.highlightingTypeFor(file, 9)).containsExactly(TypeOfText.STRING);
- assertThat(result.highlightingTypeFor(file, 10)).isEmpty();
- assertThat(result.highlightingTypeFor(file, 11)).containsExactly(TypeOfText.KEYWORD);
+ assertThat(result.highlightingTypeFor(file, 1, 0)).containsExactly(TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 1, 9)).containsExactly(TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 2, 0)).containsExactly(TypeOfText.KEYWORD);
+ assertThat(result.highlightingTypeFor(file, 2, 8)).isEmpty();
}
@@ -126,7 +126,7 @@ public class HighlightingMediumTest {
System.out.println("Duration: " + (System.currentTimeMillis() - start));
InputFile file = result.inputFile("src/sample.xoo");
- assertThat(result.highlightingTypeFor(file, 0)).containsExactly(TypeOfText.STRING);
+ assertThat(result.highlightingTypeFor(file, 1, 0)).containsExactly(TypeOfText.STRING);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
index a231c93f69b..b8ca587d1b9 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
@@ -28,6 +28,7 @@ import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.TaskResult;
+import org.sonar.batch.protocol.output.BatchReport.Range;
import org.sonar.xoo.XooPlugin;
import java.io.File;
@@ -65,6 +66,7 @@ public class SymbolMediumTest {
File xooFile = new File(srcDir, "sample.xoo");
File xooSymbolFile = new File(srcDir, "sample.xoo.symbol");
FileUtils.write(xooFile, "Sample xoo\ncontent\nanother xoo");
+ // Highlight xoo symbol
FileUtils.write(xooSymbolFile, "7,10,27");
TaskResult result = tester.newTask()
@@ -80,7 +82,7 @@ public class SymbolMediumTest {
.start();
InputFile file = result.inputFile("src/sample.xoo");
- assertThat(result.symbolReferencesFor(file, 7, 10)).containsOnly(27);
+ assertThat(result.symbolReferencesFor(file, 1, 7)).containsOnly(Range.newBuilder().setStartLine(3).setStartOffset(8).setEndLine(3).setEndOffset(11).build());
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java
index a636a5386df..5b9221dc92c 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/ReportPublisherTest.java
@@ -37,7 +37,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class PublishReportJobTest extends AbstractDbUnitTestCase {
+public class ReportPublisherTest extends AbstractDbUnitTestCase {
private DefaultAnalysisMode mode;
@@ -56,7 +56,7 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
public void should_log_successful_analysis() throws Exception {
Settings settings = new Settings();
settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisher[0]);
+ ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
Logger logger = mock(Logger.class);
job.logSuccess(logger);
@@ -69,7 +69,7 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
public void should_log_successful_preview_analysis() throws Exception {
Settings settings = new Settings();
when(mode.isPreview()).thenReturn(true);
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisher[0]);
+ ReportPublisher job = new ReportPublisher(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisherStep[0]);
Logger logger = mock(Logger.class);
job.logSuccess(logger);
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 5960fab5c2d..c62ccb0ae8c 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
@@ -30,15 +30,14 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
-import org.sonar.api.resources.AbstractLanguage;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.*;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
import java.io.File;
import java.io.IOException;
+import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -97,7 +96,9 @@ public class ComponentIndexerTest {
}
private ComponentIndexer createIndexer(Languages languages) {
- return new ComponentIndexer(project, languages, sonarIndex);
+ ResourceCache resourceCache = mock(ResourceCache.class);
+ when(resourceCache.get(any(Resource.class))).thenReturn(new BatchResource(1, org.sonar.api.resources.File.create("foo.php"), null));
+ return new ComponentIndexer(project, languages, sonarIndex, resourceCache);
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
index 2b5b1f4bcca..0c83abfa01e 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderFactoryTest.java
@@ -22,6 +22,7 @@ package org.sonar.batch.scan.filesystem;
import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@@ -39,7 +40,7 @@ public class InputFileBuilderFactoryTest {
DefaultAnalysisMode analysisMode = mock(DefaultAnalysisMode.class);
InputFileBuilderFactory factory = new InputFileBuilderFactory(ProjectDefinition.create().setKey("struts"), pathResolver, langDetectionFactory,
- statusDetectionFactory, analysisMode, new Settings(), new FileMetadata(analysisMode));
+ statusDetectionFactory, analysisMode, new Settings(), new FileMetadata());
InputFileBuilder builder = factory.create(fs);
assertThat(builder.langDetection()).isNotNull();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
index df058f13c8f..2438c3de381 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileBuilderTest.java
@@ -26,6 +26,7 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.config.Settings;
import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.api.utils.PathUtils;
@@ -66,7 +67,7 @@ public class InputFileBuilderTest {
.thenReturn(InputFile.Status.ADDED);
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
- langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata(analysisMode));
+ langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata());
DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
builder.completeAndComputeMetadata(inputFile, InputFile.Type.MAIN);
@@ -89,7 +90,7 @@ public class InputFileBuilderTest {
when(fs.baseDir()).thenReturn(basedir);
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
- langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata(analysisMode));
+ langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata());
DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
assertThat(inputFile).isNull();
@@ -109,11 +110,11 @@ public class InputFileBuilderTest {
when(langDetection.language(any(InputFile.class))).thenReturn(null);
InputFileBuilder builder = new InputFileBuilder("struts", new PathResolver(),
- langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata(analysisMode));
+ langDetection, statusDetection, fs, analysisMode, new Settings(), new FileMetadata());
DeprecatedDefaultInputFile inputFile = builder.create(srcFile);
- InputFileMetadata metadata = builder.completeAndComputeMetadata(inputFile, InputFile.Type.MAIN);
+ inputFile = builder.completeAndComputeMetadata(inputFile, InputFile.Type.MAIN);
- assertThat(metadata).isNull();
+ assertThat(inputFile).isNull();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
index 7c943e06f66..f14e2a9b957 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
@@ -79,20 +79,4 @@ public class InputPathCacheTest {
assertThat(cache.allFiles()).hasSize(1);
}
- @Test
- public void should_add_input_file_metadata() throws Exception {
- InputPathCache cache = new InputPathCache();
- cache.put("struts-core", "src/main/java/Bar.java", new InputFileMetadata()
- .setHash("xyz")
- .setNonBlankLines(2)
- .setEmpty(true)
- .setOriginalLineOffsets(new int[] {0, 4}));
-
- InputFileMetadata loadedFileMetadata = cache.getFileMetadata("struts-core", "src/main/java/Bar.java");
- assertThat(loadedFileMetadata.originalLineOffsets()).containsOnly(0, 4);
- assertThat(loadedFileMetadata.hash()).isEqualTo("xyz");
- assertThat(loadedFileMetadata.nonBlankLines()).isEqualTo(2);
- assertThat(loadedFileMetadata.isEmpty()).isTrue();
-
- }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
index b65d7e8050c..60f04a9f626 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java
@@ -38,11 +38,8 @@ import org.sonar.api.batch.sensor.dependency.internal.DefaultDependency;
import org.sonar.api.batch.sensor.issue.Issue.Severity;
import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.config.Settings;
import org.sonar.api.design.Dependency;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.PersistenceMode;
@@ -52,9 +49,10 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rule.RuleKey;
import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.issue.ModuleIssues;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.sensor.coverage.CoverageExclusions;
import static org.assertj.core.api.Assertions.assertThat;
@@ -77,7 +75,7 @@ public class DefaultSensorStorageTest {
private DefaultFileSystem fs;
private DefaultSensorStorage sensorStorage;
private Settings settings;
- private ResourcePerspectives resourcePerspectives;
+ private ModuleIssues moduleIssues;
private Project project;
private DefaultIndex sonarIndex;
@@ -91,15 +89,14 @@ public class DefaultSensorStorageTest {
when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC);
when(metricFinder.findByKey(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
settings = new Settings();
- resourcePerspectives = mock(ResourcePerspectives.class);
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ moduleIssues = mock(ModuleIssues.class);
project = new Project("myProject");
sonarIndex = mock(DefaultIndex.class);
CoverageExclusions coverageExclusions = mock(CoverageExclusions.class);
when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true);
resourceCache = new ResourceCache();
sensorStorage = new DefaultSensorStorage(metricFinder, project,
- resourcePerspectives, settings, fs, activeRules, componentDataCache, mock(DuplicationCache.class), sonarIndex, coverageExclusions, resourceCache);
+ moduleIssues, settings, fs, activeRules, mock(DuplicationCache.class), sonarIndex, coverageExclusions, resourceCache, mock(ReportPublisher.class));
}
@Test
@@ -178,12 +175,7 @@ public class DefaultSensorStorageTest {
public void shouldAddIssueOnFile() {
InputFile file = new DefaultInputFile("foo", "src/Foo.php").setLines(4);
- ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, File.create("src/Foo.php"))).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+ ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class);
sensorStorage.store(new DefaultIssue()
.onFile(file)
@@ -192,7 +184,9 @@ public class DefaultSensorStorageTest {
.atLine(3)
.effortToFix(10.0));
- Issue issue = argumentCaptor.getValue();
+ verify(moduleIssues).initAndAddIssue(argumentCaptor.capture());
+
+ org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue();
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
assertThat(issue.message()).isEqualTo("Foo");
assertThat(issue.line()).isEqualTo(3);
@@ -204,12 +198,7 @@ public class DefaultSensorStorageTest {
public void shouldAddIssueOnDirectory() {
InputDir dir = new DefaultInputDir("foo", "src");
- ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, Directory.create("src"))).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+ ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class);
sensorStorage.store(new DefaultIssue()
.onDir(dir)
@@ -217,7 +206,9 @@ public class DefaultSensorStorageTest {
.message("Foo")
.effortToFix(10.0));
- Issue issue = argumentCaptor.getValue();
+ verify(moduleIssues).initAndAddIssue(argumentCaptor.capture());
+
+ org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue();
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
assertThat(issue.message()).isEqualTo("Foo");
assertThat(issue.line()).isNull();
@@ -227,12 +218,7 @@ public class DefaultSensorStorageTest {
@Test
public void shouldAddIssueOnProject() {
- ArgumentCaptor<Issue> argumentCaptor = ArgumentCaptor.forClass(Issue.class);
-
- Issuable issuable = mock(Issuable.class);
- when(resourcePerspectives.as(Issuable.class, (Resource) project)).thenReturn(issuable);
-
- when(issuable.addIssue(argumentCaptor.capture())).thenReturn(true);
+ ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class);
sensorStorage.store(new DefaultIssue()
.onProject()
@@ -241,7 +227,9 @@ public class DefaultSensorStorageTest {
.overrideSeverity(Severity.BLOCKER)
.effortToFix(10.0));
- Issue issue = argumentCaptor.getValue();
+ verify(moduleIssues).initAndAddIssue(argumentCaptor.capture());
+
+ org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue();
assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar"));
assertThat(issue.message()).isEqualTo("Foo");
assertThat(issue.line()).isNull();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/CodeColorizersTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/CodeColorizersTest.java
index a7486ad376b..a6568661633 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/CodeColorizersTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/CodeColorizersTest.java
@@ -25,38 +25,45 @@ import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.sensor.highlighting.NewHighlighting;
+import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.web.CodeColorizerFormat;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.colorizer.CDocTokenizer;
-import org.sonar.colorizer.CppDocTokenizer;
-import org.sonar.colorizer.JavadocTokenizer;
-import org.sonar.colorizer.KeywordsTokenizer;
-import org.sonar.colorizer.StringTokenizer;
-import org.sonar.colorizer.Tokenizer;
+import org.sonar.colorizer.*;
import java.io.File;
import java.util.Arrays;
import java.util.List;
-import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
public class CodeColorizersTest {
- private static final String HIGHLIGHTING_JS = "0,4,cppd;5,11,cppd;12,15,cppd;16,19,k;29,37,k;65,69,k;85,93,cd;98,102,k;112,114,s;120,124,k";
- private static final String HIGHLIGHTING_JAVA = "0,4,j;5,11,j;12,15,j;16,22,k;23,28,k;43,50,k;51,54,k;67,78,a;81,87,k;88,92,k;97,100,k;142,146,k;162,170,cd";
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
public void testConvertToHighlighting() throws Exception {
CodeColorizers codeColorizers = new CodeColorizers(Arrays.<CodeColorizerFormat>asList(new JavaScriptColorizerFormat()));
-
File jsFile = new File(this.getClass().getResource("CodeColorizersTest/Person.js").toURI());
+ NewHighlighting highlighting = mock(NewHighlighting.class);
- SyntaxHighlightingData syntaxHighlighting = codeColorizers.toSyntaxHighlighting(jsFile, Charsets.UTF_8, "js");
+ codeColorizers.toSyntaxHighlighting(jsFile, Charsets.UTF_8, "js", highlighting);
- assertThat(syntaxHighlighting.writeString()).isEqualTo(HIGHLIGHTING_JS);
+ verifyForJs(highlighting);
+ }
+ private void verifyForJs(NewHighlighting highlighting) {
+ verify(highlighting).highlight(0, 4, TypeOfText.CPP_DOC);
+ verify(highlighting).highlight(5, 11, TypeOfText.CPP_DOC);
+ verify(highlighting).highlight(12, 15, TypeOfText.CPP_DOC);
+ verify(highlighting).highlight(16, 19, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(29, 37, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(65, 69, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(85, 93, TypeOfText.COMMENT);
+ verify(highlighting).highlight(98, 102, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(112, 114, TypeOfText.STRING);
+ verify(highlighting).highlight(120, 124, TypeOfText.KEYWORD);
}
@Test
@@ -68,9 +75,10 @@ public class CodeColorizersTest {
File jsFile = new File(this.getClass().getResource("CodeColorizersTest/Person.js").toURI());
FileUtils.write(fileWithBom, FileUtils.readFileToString(jsFile), "UTF-8", true);
- SyntaxHighlightingData syntaxHighlighting = codeColorizers.toSyntaxHighlighting(fileWithBom, Charsets.UTF_8, "js");
+ NewHighlighting highlighting = mock(NewHighlighting.class);
+ codeColorizers.toSyntaxHighlighting(fileWithBom, Charsets.UTF_8, "js", highlighting);
- assertThat(syntaxHighlighting.writeString()).isEqualTo(HIGHLIGHTING_JS);
+ verifyForJs(highlighting);
}
@Test
@@ -79,9 +87,22 @@ public class CodeColorizersTest {
File javaFile = new File(this.getClass().getResource("CodeColorizersTest/Person.java").toURI());
- SyntaxHighlightingData syntaxHighlighting = codeColorizers.toSyntaxHighlighting(javaFile, Charsets.UTF_8, "java");
-
- assertThat(syntaxHighlighting.writeString()).isEqualTo(HIGHLIGHTING_JAVA);
+ NewHighlighting highlighting = mock(NewHighlighting.class);
+ codeColorizers.toSyntaxHighlighting(javaFile, Charsets.UTF_8, "java", highlighting);
+
+ verify(highlighting).highlight(0, 4, TypeOfText.STRUCTURED_COMMENT);
+ verify(highlighting).highlight(5, 11, TypeOfText.STRUCTURED_COMMENT);
+ verify(highlighting).highlight(12, 15, TypeOfText.STRUCTURED_COMMENT);
+ verify(highlighting).highlight(16, 22, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(23, 28, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(43, 50, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(51, 54, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(67, 78, TypeOfText.ANNOTATION);
+ verify(highlighting).highlight(81, 87, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(88, 92, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(97, 100, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(142, 146, TypeOfText.KEYWORD);
+ verify(highlighting).highlight(162, 170, TypeOfText.COMMENT);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultHighlightableTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultHighlightableTest.java
index a14e4fe91d1..7b3d3987bf3 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultHighlightableTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultHighlightableTest.java
@@ -23,16 +23,16 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
-import org.sonar.api.component.Component;
-import org.sonar.batch.highlighting.SyntaxHighlightingData;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.core.source.SnapshotDataTypes;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
+import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import java.io.StringReader;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
public class DefaultHighlightableTest {
@@ -41,27 +41,15 @@ public class DefaultHighlightableTest {
@Test
public void should_store_highlighting_rules() throws Exception {
- DefaultHighlightable highlightablePerspective = new DefaultHighlightable(mock(Component.class), null);
- highlightablePerspective.newHighlighting().highlight(0, 10, "k").highlight(20, 30, "cppd");
-
- assertThat(highlightablePerspective.getHighlightingRules().getSyntaxHighlightingRuleSet()).hasSize(2);
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.php")
+ .initMetadata(new FileMetadata().readMetadata(new StringReader("azerty\nbla bla")));
+ DefaultHighlightable highlightablePerspective = new DefaultHighlightable(inputFile, sensorStorage);
+ highlightablePerspective.newHighlighting().highlight(0, 6, "k").highlight(7, 10, "cppd").done();
+
+ ArgumentCaptor<DefaultHighlighting> argCaptor = ArgumentCaptor.forClass(DefaultHighlighting.class);
+ verify(sensorStorage).store(argCaptor.capture());
+ assertThat(argCaptor.getValue().getSyntaxHighlightingRuleSet()).hasSize(2);
}
- @Test
- public void should_apply_registered_highlighting() throws Exception {
- Component component = mock(Component.class);
- when(component.key()).thenReturn("myComponent");
-
- ComponentDataCache cache = mock(ComponentDataCache.class);
-
- DefaultHighlightable highlightable = new DefaultHighlightable(component, cache);
- highlightable.newHighlighting()
- .highlight(0, 10, "k")
- .highlight(20, 30, "cppd")
- .done();
-
- ArgumentCaptor<SyntaxHighlightingData> argCaptor = ArgumentCaptor.forClass(SyntaxHighlightingData.class);
- verify(cache).setData(eq("myComponent"), eq(SnapshotDataTypes.SYNTAX_HIGHLIGHTING), argCaptor.capture());
- assertThat(argCaptor.getValue().writeString()).isEqualTo("0,10,k;20,30,cppd");
- }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java
index c23fcd2831d..a0489a7c209 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolTableTest.java
@@ -20,22 +20,36 @@
package org.sonar.batch.source;
+import com.google.common.base.Strings;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.source.Symbol;
import org.sonar.api.source.Symbolizable;
+import java.io.StringReader;
+
import static org.assertj.core.api.Assertions.assertThat;
public class DefaultSymbolTableTest {
@Rule
public ExpectedException throwable = ExpectedException.none();
+ private DefaultInputFile inputFile;
+
+ @Before
+ public void prepare() {
+ inputFile = new DefaultInputFile("foo", "src/Foo.php")
+ .initMetadata(new FileMetadata().readMetadata(new StringReader(Strings.repeat("azerty\n", 20))));
+ }
@Test
public void should_order_symbol_and_references() throws Exception {
- Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder("foo");
+
+ Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder(inputFile);
Symbol firstSymbol = symbolTableBuilder.newSymbol(10, 20);
symbolTableBuilder.newReference(firstSymbol, 32);
Symbol secondSymbol = symbolTableBuilder.newSymbol(84, 92);
@@ -45,25 +59,22 @@ public class DefaultSymbolTableTest {
Symbolizable.SymbolTable symbolTable = symbolTableBuilder.build();
assertThat(symbolTable.symbols()).containsExactly(firstSymbol, secondSymbol, thirdSymbol);
- assertThat(symbolTable.references(firstSymbol)).containsExactly(32);
- assertThat(symbolTable.references(secondSymbol)).containsExactly(124);
- assertThat(symbolTable.references(thirdSymbol)).containsExactly(70);
}
@Test
public void should_reject_reference_conflicting_with_declaration() throws Exception {
throwable.expect(UnsupportedOperationException.class);
- Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder("foo");
+ Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder(inputFile);
Symbol symbol = symbolTableBuilder.newSymbol(10, 20);
symbolTableBuilder.newReference(symbol, 15);
}
@Test
public void test_toString() throws Exception {
- Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder("foo");
+ Symbolizable.SymbolTableBuilder symbolTableBuilder = new DefaultSymbolTable.Builder(inputFile);
Symbol symbol = symbolTableBuilder.newSymbol(10, 20);
- assertThat(symbol.toString()).isEqualTo("Symbol{offset=10-20}");
+ assertThat(symbol.toString()).isEqualTo("Symbol{range=Range[from [line=2, lineOffset=3] to [line=3, lineOffset=6]]}");
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolizableTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolizableTest.java
index 940c47ed46e..d3b1018ace5 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolizableTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/DefaultSymbolizableTest.java
@@ -20,31 +20,33 @@
package org.sonar.batch.source;
+import com.google.common.base.Strings;
import org.junit.Test;
-import org.sonar.api.component.Component;
+import org.mockito.ArgumentCaptor;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.source.Symbol;
import org.sonar.api.source.Symbolizable;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.batch.symbol.SymbolData;
-import org.sonar.core.source.SnapshotDataTypes;
+import org.sonar.batch.sensor.DefaultSensorStorage;
-import static org.mockito.Matchers.any;
+import java.io.StringReader;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
public class DefaultSymbolizableTest {
@Test
public void should_update_cache_when_done() throws Exception {
- Component component = mock(Component.class);
- when(component.key()).thenReturn("myComponent");
-
- ComponentDataCache cache = mock(ComponentDataCache.class);
+ DefaultSensorStorage sensorStorage = mock(DefaultSensorStorage.class);
+ DefaultInputFile inputFile = new DefaultInputFile("foo", "src/Foo.php")
+ .initMetadata(new FileMetadata().readMetadata(new StringReader(Strings.repeat("azerty\n", 20))));
- DefaultSymbolizable symbolPerspective = new DefaultSymbolizable(cache, component);
+ DefaultSymbolizable symbolPerspective = new DefaultSymbolizable(inputFile, sensorStorage);
Symbolizable.SymbolTableBuilder symbolTableBuilder = symbolPerspective.newSymbolTableBuilder();
Symbol firstSymbol = symbolTableBuilder.newSymbol(4, 8);
symbolTableBuilder.newReference(firstSymbol, 12);
@@ -57,6 +59,9 @@ public class DefaultSymbolizableTest {
symbolPerspective.setSymbolTable(symbolTable);
- verify(cache).setData(eq("myComponent"), eq(SnapshotDataTypes.SYMBOL_HIGHLIGHTING), any(SymbolData.class));
+ ArgumentCaptor<Map> argCaptor = ArgumentCaptor.forClass(Map.class);
+ verify(sensorStorage).store(eq(inputFile), argCaptor.capture());
+ // Map<Symbol, Set<TextRange>>
+ assertThat(argCaptor.getValue().keySet()).hasSize(2);
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/HighlightableBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/HighlightableBuilderTest.java
index e2adf2dd0db..893957a80a5 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/HighlightableBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/HighlightableBuilderTest.java
@@ -20,38 +20,42 @@
package org.sonar.batch.source;
import org.junit.Test;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.component.Component;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.source.Highlightable;
-import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
import org.sonar.core.component.ResourceComponent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class HighlightableBuilderTest {
- ComponentDataCache cache = mock(ComponentDataCache.class);
-
@Test
public void should_load_default_perspective() throws Exception {
Resource file = File.create("foo.c").setEffectiveKey("myproject:path/to/foo.c");
Component component = new ResourceComponent(file);
- HighlightableBuilder builder = new HighlightableBuilder(cache);
+ ResourceCache resourceCache = mock(ResourceCache.class);
+ when(resourceCache.get(file.getEffectiveKey())).thenReturn(new BatchResource(1, file, null).setInputPath(new DefaultInputFile("myproject", "path/to/foo.c")));
+ HighlightableBuilder builder = new HighlightableBuilder(resourceCache, mock(SensorStorage.class));
Highlightable perspective = builder.loadPerspective(Highlightable.class, component);
assertThat(perspective).isNotNull().isInstanceOf(DefaultHighlightable.class);
- assertThat(perspective.component()).isSameAs(component);
+ assertThat(perspective.component().key()).isEqualTo(component.key());
}
@Test
public void project_should_not_be_highlightable() {
Component component = new ResourceComponent(new Project("struts").setEffectiveKey("org.struts"));
- HighlightableBuilder builder = new HighlightableBuilder(cache);
+ HighlightableBuilder builder = new HighlightableBuilder(mock(ResourceCache.class), mock(SensorStorage.class));
Highlightable perspective = builder.loadPerspective(Highlightable.class, component);
assertThat(perspective).isNull();
diff --git a/sonar-batch/src/test/java/org/sonar/batch/source/SymbolizableBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/source/SymbolizableBuilderTest.java
index f2138c9a721..16c4fe669a7 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/source/SymbolizableBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/source/SymbolizableBuilderTest.java
@@ -21,26 +21,46 @@
package org.sonar.batch.source;
import org.junit.Test;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.component.Component;
import org.sonar.api.component.Perspective;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
import org.sonar.api.source.Symbolizable;
-import org.sonar.batch.index.ComponentDataCache;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.sensor.DefaultSensorStorage;
+import org.sonar.core.component.ResourceComponent;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class SymbolizableBuilderTest {
- ComponentDataCache dataCache = mock(ComponentDataCache.class);
-
@Test
public void should_load_perspective() throws Exception {
- Component component = mock(Component.class);
+ Resource file = File.create("foo.c").setEffectiveKey("myproject:path/to/foo.c");
+ Component component = new ResourceComponent(file);
+
+ ResourceCache resourceCache = mock(ResourceCache.class);
+ when(resourceCache.get(file.getEffectiveKey())).thenReturn(new BatchResource(1, file, null).setInputPath(new DefaultInputFile("myproject", "path/to/foo.c")));
- SymbolizableBuilder perspectiveBuilder = new SymbolizableBuilder(dataCache);
+ SymbolizableBuilder perspectiveBuilder = new SymbolizableBuilder(resourceCache, mock(DefaultSensorStorage.class));
Perspective perspective = perspectiveBuilder.loadPerspective(Symbolizable.class, component);
assertThat(perspective).isInstanceOf(Symbolizable.class);
- assertThat(perspective.component()).isEqualTo(component);
+ assertThat(perspective.component().key()).isEqualTo(component.key());
+ }
+
+ @Test
+ public void project_should_not_be_highlightable() {
+ Component component = new ResourceComponent(new Project("struts").setEffectiveKey("org.struts"));
+
+ SymbolizableBuilder builder = new SymbolizableBuilder(mock(ResourceCache.class), mock(DefaultSensorStorage.class));
+ Perspective perspective = builder.loadPerspective(Symbolizable.class, component);
+
+ assertThat(perspective).isNull();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java
deleted file mode 100644
index 05961573725..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/symbol/DefaultSymbolTableBuilderTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 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.symbol;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.mockito.ArgumentCaptor;
-import org.sonar.api.source.Symbol;
-import org.sonar.batch.index.ComponentDataCache;
-import org.sonar.core.source.SnapshotDataTypes;
-
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class DefaultSymbolTableBuilderTest {
-
- @Rule
- public ExpectedException throwable = ExpectedException.none();
-
- @Test
- public void should_write_symbol_and_references() throws Exception {
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- DefaultSymbolTableBuilder symbolTableBuilder = new DefaultSymbolTableBuilder("foo", componentDataCache);
- Symbol firstSymbol = symbolTableBuilder.newSymbol(10, 20);
- symbolTableBuilder.newReference(firstSymbol, 32);
- Symbol secondSymbol = symbolTableBuilder.newSymbol(84, 92);
- symbolTableBuilder.newReference(secondSymbol, 124);
- Symbol thirdSymbol = symbolTableBuilder.newSymbol(55, 62);
- symbolTableBuilder.newReference(thirdSymbol, 70);
- symbolTableBuilder.done();
-
- ArgumentCaptor<SymbolData> argCaptor = ArgumentCaptor.forClass(SymbolData.class);
- verify(componentDataCache).setData(eq("foo"), eq(SnapshotDataTypes.SYMBOL_HIGHLIGHTING), argCaptor.capture());
-
- Map<org.sonar.api.source.Symbol, Set<Integer>> referencesBySymbol = argCaptor.getValue().referencesBySymbol();
-
- assertThat(new ArrayList<Symbol>(referencesBySymbol.keySet())).containsExactly(firstSymbol, secondSymbol, thirdSymbol);
- assertThat(new ArrayList<Integer>(referencesBySymbol.get(firstSymbol))).containsExactly(32);
- assertThat(new ArrayList<Integer>(referencesBySymbol.get(secondSymbol))).containsExactly(124);
- assertThat(new ArrayList<Integer>(referencesBySymbol.get(thirdSymbol))).containsExactly(70);
-
- assertThat(argCaptor.getValue().writeString()).isEqualTo("10,20,10,32;84,92,84,124;55,62,55,70");
- }
-
- @Test
- public void should_serialize_unused_symbol() throws Exception {
-
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- DefaultSymbolTableBuilder symbolTableBuilder = new DefaultSymbolTableBuilder("foo", componentDataCache);
- symbolTableBuilder.newSymbol(10, 20);
- symbolTableBuilder.done();
-
- ArgumentCaptor<SymbolData> argCaptor = ArgumentCaptor.forClass(SymbolData.class);
- verify(componentDataCache).setData(eq("foo"), eq(SnapshotDataTypes.SYMBOL_HIGHLIGHTING), argCaptor.capture());
-
- assertThat(argCaptor.getValue().writeString()).isEqualTo("10,20,10");
- }
-
- @Test
- public void should_reject_reference_conflicting_with_declaration() throws Exception {
- throwable.expect(UnsupportedOperationException.class);
-
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- DefaultSymbolTableBuilder symbolTableBuilder = new DefaultSymbolTableBuilder("foo", componentDataCache);
- Symbol symbol = symbolTableBuilder.newSymbol(10, 20);
- symbolTableBuilder.newReference(symbol, 15);
- }
-
- @Test
- public void should_reject_reference_from_another_file() throws Exception {
- throwable.expect(UnsupportedOperationException.class);
-
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- DefaultSymbolTableBuilder symbolTableBuilder = new DefaultSymbolTableBuilder("foo", componentDataCache);
- Symbol symbol = symbolTableBuilder.newSymbol(10, 20);
-
- DefaultSymbolTableBuilder symbolTableBuilder2 = new DefaultSymbolTableBuilder("foo2", componentDataCache);
- Symbol symbol2 = symbolTableBuilder2.newSymbol(30, 40);
-
- symbolTableBuilder.newReference(symbol2, 15);
- }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/component/GraphPerspectiveBuilder.java b/sonar-core/src/main/java/org/sonar/core/component/GraphPerspectiveBuilder.java
index df2199c7103..5668a840d69 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/GraphPerspectiveBuilder.java
+++ b/sonar-core/src/main/java/org/sonar/core/component/GraphPerspectiveBuilder.java
@@ -30,7 +30,7 @@ public abstract class GraphPerspectiveBuilder<T extends Perspective> extends Per
protected final GraphPerspectiveLoader<T> perspectiveLoader;
protected GraphPerspectiveBuilder(ScanGraph graph, Class<T> perspectiveClass, EdgePath path,
- GraphPerspectiveLoader<T> perspectiveLoader) {
+ GraphPerspectiveLoader<T> perspectiveLoader) {
super(perspectiveClass);
this.graph = graph;
this.path = path;
@@ -39,7 +39,7 @@ public abstract class GraphPerspectiveBuilder<T extends Perspective> extends Per
public T create(ComponentVertex component) {
return (T) component.beanGraph().createAdjacentVertex(component, perspectiveLoader.getBeanClass(),
- perspectiveLoader.getPerspectiveKey());
+ perspectiveLoader.getPerspectiveKey());
}
public EdgePath path() {
@@ -51,7 +51,7 @@ public abstract class GraphPerspectiveBuilder<T extends Perspective> extends Per
}
@Override
- protected T loadPerspective(Class<T> perspectiveClass, Component component) {
+ public T loadPerspective(Class<T> perspectiveClass, Component component) {
ComponentVertex vertex;
if (component instanceof ComponentVertex) {
vertex = (ComponentVertex) component;
diff --git a/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java b/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java
index 5b69ebaf05d..31f9c323d61 100644
--- a/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java
+++ b/sonar-core/src/main/java/org/sonar/core/component/PerspectiveBuilder.java
@@ -34,10 +34,10 @@ public abstract class PerspectiveBuilder<T extends Perspective> implements Batch
this.perspectiveClass = perspectiveClass;
}
- protected Class<T> getPerspectiveClass() {
+ public Class<T> getPerspectiveClass() {
return perspectiveClass;
}
@CheckForNull
- protected abstract T loadPerspective(Class<T> perspectiveClass, Component component);
+ public abstract T loadPerspective(Class<T> perspectiveClass, Component component);
}
diff --git a/sonar-core/src/test/java/org/sonar/core/component/PerspectiveBuilderTest.java b/sonar-core/src/test/java/org/sonar/core/component/PerspectiveBuilderTest.java
index 4275f2c63d9..d3bb10520d5 100644
--- a/sonar-core/src/test/java/org/sonar/core/component/PerspectiveBuilderTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/component/PerspectiveBuilderTest.java
@@ -30,7 +30,7 @@ public class PerspectiveBuilderTest {
public void testGetPerspectiveClass() throws Exception {
PerspectiveBuilder<FakePerspective> builder = new PerspectiveBuilder<FakePerspective>(FakePerspective.class) {
@Override
- protected FakePerspective loadPerspective(Class<FakePerspective> perspectiveClass, Component component) {
+ public FakePerspective loadPerspective(Class<FakePerspective> perspectiveClass, Component component) {
return null;
}
};
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
index 768986d8c0c..4e0af79ccc7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/InputFile.java
@@ -19,6 +19,8 @@
*/
package org.sonar.api.batch.fs;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+
import javax.annotation.CheckForNull;
import java.io.File;
@@ -26,6 +28,14 @@ import java.nio.file.Path;
/**
* This layer over {@link java.io.File} adds information for code analyzers.
+ * For unit testing purpose you can create some {@link DefaultInputFile} and initialize
+ * all fields using
+ *
+ * <pre>
+ * new DefaultInputFile("moduleKey", "relative/path/from/module/baseDir.java")
+ * .setModuleBaseDir(path)
+ * .initMetadata(new FileMetadata().readMetadata(someReader));
+ * </pre>
*
* @since 4.2
*/
@@ -100,4 +110,20 @@ public interface InputFile extends InputPath {
*/
int lines();
+ /**
+ * Return a {@link TextPointer} in the given file.
+ * @param line Line of the pointer. Start at 1.
+ * @param lineOffset Offset in the line. Start at 0.
+ * @throw {@link IllegalArgumentException} if line or offset is not valid for the given file.
+ */
+ TextPointer newPointer(int line, int lineOffset);
+
+ /**
+ * Return a {@link TextRange} in the given file.
+ * @param start
+ * @param end
+ * @throw {@link IllegalArgumentException} if start or stop pointers are not valid for the given file.
+ */
+ TextRange newRange(TextPointer start, TextPointer end);
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/symbol/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextPointer.java
index 2ac5be1323d..63f49b7d407 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/symbol/package-info.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextPointer.java
@@ -17,5 +17,23 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-@javax.annotation.ParametersAreNonnullByDefault
-package org.sonar.batch.symbol;
+package org.sonar.api.batch.fs;
+
+/**
+ * Represents a position in a text file {@link InputFile}
+ *
+ * @since 5.2
+ */
+public interface TextPointer extends Comparable<TextPointer> {
+
+ /**
+ * The logical line where this pointer is located. First line is 1.
+ */
+ int line();
+
+ /**
+ * The offset of this pointer in the current line. First position in a line is 0.
+ */
+ int lineOffset();
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextRange.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextRange.java
new file mode 100644
index 00000000000..08239a1e0cd
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/TextRange.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.fs;
+
+/**
+ * Represents a text range in an {@link InputFile}
+ *
+ * @since 5.2
+ */
+public interface TextRange {
+
+ /**
+ * Start position of the range
+ */
+ TextPointer start();
+
+ /**
+ * End position of the range
+ */
+ TextPointer end();
+
+ /**
+ * Test if the current range has some common area with another range.
+ * Exemple: say the two ranges are on same line. Range with offsets [1,3] overlaps range with offsets [2,4] but not
+ * range with offset [3,5]
+ */
+ boolean overlap(TextRange another);
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
index a24060a5df1..83b4473fbea 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultInputFile.java
@@ -19,7 +19,11 @@
*/
package org.sonar.api.batch.fs.internal;
+import com.google.common.base.Preconditions;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.FileMetadata.Metadata;
import org.sonar.api.utils.PathUtils;
import javax.annotation.CheckForNull;
@@ -28,6 +32,7 @@ import javax.annotation.Nullable;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Path;
+import java.util.Arrays;
/**
* @since 4.2
@@ -40,9 +45,13 @@ public class DefaultInputFile implements InputFile {
private String language;
private Type type = Type.MAIN;
private Status status;
- private int lines;
+ private int lines = -1;
private Charset charset;
- private int lastValidOffset;
+ private int lastValidOffset = -1;
+ private String hash;
+ private int nonBlankLines;
+ private int[] originalLineOffsets;
+ private boolean empty;
public DefaultInputFile(String moduleKey, String relativePath) {
this.moduleKey = moduleKey;
@@ -145,6 +154,7 @@ public class DefaultInputFile implements InputFile {
}
public int lastValidOffset() {
+ Preconditions.checkState(lastValidOffset >= 0, "InputFile is not properly initialized. Please set 'lastValidOffset' property.");
return lastValidOffset;
}
@@ -153,6 +163,108 @@ public class DefaultInputFile implements InputFile {
return this;
}
+ /**
+ * Digest hash of the file.
+ */
+ public String hash() {
+ return hash;
+ }
+
+ public int nonBlankLines() {
+ return nonBlankLines;
+ }
+
+ public int[] originalLineOffsets() {
+ Preconditions.checkState(originalLineOffsets != null, "InputFile is not properly initialized. Please set 'originalLineOffsets' property.");
+ Preconditions.checkState(originalLineOffsets.length == lines, "InputFile is not properly initialized. 'originalLineOffsets' property length should be equal to 'lines'");
+ return originalLineOffsets;
+ }
+
+ public DefaultInputFile setHash(String hash) {
+ this.hash = hash;
+ return this;
+ }
+
+ public DefaultInputFile setNonBlankLines(int nonBlankLines) {
+ this.nonBlankLines = nonBlankLines;
+ return this;
+ }
+
+ public DefaultInputFile setOriginalLineOffsets(int[] originalLineOffsets) {
+ this.originalLineOffsets = originalLineOffsets;
+ return this;
+ }
+
+ public boolean isEmpty() {
+ return this.empty;
+ }
+
+ public DefaultInputFile setEmpty(boolean empty) {
+ this.empty = empty;
+ return this;
+ }
+
+ @Override
+ public TextPointer newPointer(int line, int lineOffset) {
+ DefaultTextPointer textPointer = new DefaultTextPointer(line, lineOffset);
+ checkValid(textPointer, "pointer");
+ return textPointer;
+ }
+
+ private void checkValid(TextPointer pointer, String owner) {
+ Preconditions.checkArgument(pointer.line() >= 1, "%s is not a valid line for a file", pointer.line());
+ Preconditions.checkArgument(pointer.line() <= this.lines, "%s is not a valid line for %s. File %s has %s line(s)", pointer.line(), owner, this, lines);
+ Preconditions.checkArgument(pointer.lineOffset() >= 0, "%s is not a valid line offset for a file", pointer.lineOffset());
+ int lineLength = lineLength(pointer.line());
+ Preconditions.checkArgument(pointer.lineOffset() <= lineLength,
+ "%s is not a valid line offset for %s. File %s has %s character(s) at line %s", pointer.lineOffset(), owner, this, lineLength, pointer.line());
+ }
+
+ private int lineLength(int line) {
+ return lastValidGlobalOffsetForLine(line) - originalLineOffsets()[line - 1];
+ }
+
+ private int lastValidGlobalOffsetForLine(int line) {
+ return line < this.lines ? (originalLineOffsets()[line] - 1) : lastValidOffset();
+ }
+
+ @Override
+ public TextRange newRange(TextPointer start, TextPointer end) {
+ checkValid(start, "start pointer");
+ checkValid(end, "end pointer");
+ Preconditions.checkArgument(start.compareTo(end) < 0, "Start pointer %s should be before end pointer %s", start, end);
+ return new DefaultTextRange(start, end);
+ }
+
+ /**
+ * Create Range from global offsets. Used for backward compatibility with older API.
+ */
+ public TextRange newRange(int startOffset, int endOffset) {
+ return newRange(newPointer(startOffset), newPointer(endOffset));
+ }
+
+ public TextPointer newPointer(int globalOffset) {
+ Preconditions.checkArgument(globalOffset >= 0, "%s is not a valid offset for a file", globalOffset);
+ Preconditions.checkArgument(globalOffset <= lastValidOffset(), "%s is not a valid offset for file %s. Max offset is %s", globalOffset, this, lastValidOffset());
+ int line = findLine(globalOffset);
+ int startLineOffset = originalLineOffsets()[line - 1];
+ return new DefaultTextPointer(line, globalOffset - startLineOffset);
+ }
+
+ private int findLine(int globalOffset) {
+ return Math.abs(Arrays.binarySearch(originalLineOffsets(), globalOffset) + 1);
+ }
+
+ public DefaultInputFile initMetadata(Metadata metadata) {
+ this.setLines(metadata.lines);
+ this.setLastValidOffset(metadata.lastValidOffset);
+ this.setNonBlankLines(metadata.nonBlankLines);
+ this.setHash(metadata.hash);
+ this.setOriginalLineOffsets(metadata.originalLineOffsets);
+ this.setEmpty(metadata.empty);
+ return this;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java
new file mode 100644
index 00000000000..572aa4cb838
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextPointer.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.fs.internal;
+
+import org.sonar.api.batch.fs.TextPointer;
+
+/**
+ * @since 5.2
+ */
+public class DefaultTextPointer implements TextPointer {
+
+ private final int line;
+ private final int lineOffset;
+
+ public DefaultTextPointer(int line, int lineOffset) {
+ this.line = line;
+ this.lineOffset = lineOffset;
+ }
+
+ @Override
+ public int line() {
+ return line;
+ }
+
+ @Override
+ public int lineOffset() {
+ return lineOffset;
+ }
+
+ @Override
+ public String toString() {
+ return "[line=" + line + ", lineOffset=" + lineOffset + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DefaultTextPointer)) {
+ return false;
+ }
+ DefaultTextPointer other = (DefaultTextPointer) obj;
+ return other.line == this.line && other.lineOffset == this.lineOffset;
+ }
+
+ @Override
+ public int hashCode() {
+ return 37 * this.line + lineOffset;
+ }
+
+ @Override
+ public int compareTo(TextPointer o) {
+ if (this.line == o.line()) {
+ return Integer.compare(this.lineOffset, o.lineOffset());
+ }
+ return Integer.compare(this.line, o.line());
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java
new file mode 100644
index 00000000000..b976d1656bc
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/DefaultTextRange.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.batch.fs.internal;
+
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+
+/**
+ * @since 5.2
+ */
+public class DefaultTextRange implements TextRange {
+
+ private final TextPointer start;
+ private final TextPointer end;
+
+ public DefaultTextRange(TextPointer start, TextPointer end) {
+ this.start = start;
+ this.end = end;
+ }
+
+ @Override
+ public TextPointer start() {
+ return start;
+ }
+
+ @Override
+ public TextPointer end() {
+ return end;
+ }
+
+ @Override
+ public boolean overlap(TextRange another) {
+ // [A,B] and [C,D]
+ // B > C && D > A
+ return this.end.compareTo(another.start()) > 0 && another.end().compareTo(this.start) > 0;
+ }
+
+ @Override
+ public String toString() {
+ return "Range[from " + start + " to " + end + "]";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof DefaultTextRange)) {
+ return false;
+ }
+ DefaultTextRange other = (DefaultTextRange) obj;
+ return start.equals(other.start) && end.equals(other.end);
+ }
+
+ @Override
+ public int hashCode() {
+ return start.hashCode() * 17 + end.hashCode();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
index 05161741c13..bb357542239 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/FileMetadata.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
@@ -17,7 +17,7 @@
* 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;
+package org.sonar.api.batch.fs.internal;
import com.google.common.base.Charsets;
import com.google.common.primitives.Ints;
@@ -27,8 +27,6 @@ import org.apache.commons.io.ByteOrderMark;
import org.apache.commons.io.input.BOMInputStream;
import org.sonar.api.BatchComponent;
import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
@@ -51,11 +49,6 @@ public class FileMetadata implements BatchComponent {
private static final char LINE_FEED = '\n';
private static final char CARRIAGE_RETURN = '\r';
- private final AnalysisMode analysisMode;
-
- public FileMetadata(AnalysisMode analysisMode) {
- this.analysisMode = analysisMode;
- }
private abstract static class CharHandler {
@@ -90,8 +83,8 @@ public class FileMetadata implements BatchComponent {
void handleAll(char c) {
this.empty = false;
if (!alreadyLoggedInvalidCharacter && c == '\ufffd') {
- LOG.warn("Invalid character encountered in file " + file + " at line " + lines
- + " for encoding " + encoding + ". Please fix file content or configure the encoding to be used using property '" + CoreProperties.ENCODING_PROPERTY + "'.");
+ LOG.warn("Invalid character encountered in file {} at line {} for encoding {}. Please fix file content or configure the encoding to be used using property '{}'.", file,
+ lines, encoding, CoreProperties.ENCODING_PROPERTY);
alreadyLoggedInvalidCharacter = true;
}
}
@@ -230,66 +223,82 @@ public class FileMetadata implements BatchComponent {
* Compute hash of a file ignoring line ends differences.
* Maximum performance is needed.
*/
- Metadata read(File file, Charset encoding) {
+ public Metadata readMetadata(File file, Charset encoding) {
LineCounter lineCounter = new LineCounter(file, encoding);
FileHashComputer fileHashComputer = new FileHashComputer();
LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
- if (!analysisMode.isPreview()) {
- scanFile(file, encoding, lineCounter, fileHashComputer, lineOffsetCounter);
- } else {
- // No need to compute line offsets in preview mode since there is no syntax highlighting
- scanFile(file, encoding, lineCounter, fileHashComputer);
+ readFile(file, encoding, lineCounter, fileHashComputer, lineOffsetCounter);
+ return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineOffsets(),
+ lineOffsetCounter.getLastValidOffset(),
+ lineCounter.isEmpty());
+ }
+
+ /**
+ * For testing purpose
+ */
+ public Metadata readMetadata(Reader reader) {
+ LineCounter lineCounter = new LineCounter(new File("fromString"), Charsets.UTF_16);
+ FileHashComputer fileHashComputer = new FileHashComputer();
+ LineOffsetCounter lineOffsetCounter = new LineOffsetCounter();
+ try {
+ read(reader, lineCounter, fileHashComputer, lineOffsetCounter);
+ } catch (IOException e) {
+ throw new IllegalStateException("Should never occurs", e);
}
return new Metadata(lineCounter.lines(), lineCounter.nonBlankLines(), fileHashComputer.getHash(), lineOffsetCounter.getOriginalLineOffsets(),
lineOffsetCounter.getLastValidOffset(),
lineCounter.isEmpty());
}
- private static void scanFile(File file, Charset encoding, CharHandler... handlers) {
- char c = (char) 0;
+ private static void readFile(File file, Charset encoding, CharHandler... handlers) {
try (BOMInputStream bomIn = new BOMInputStream(new FileInputStream(file),
ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
Reader reader = new BufferedReader(new InputStreamReader(bomIn, encoding))) {
- int i = reader.read();
- boolean afterCR = false;
- while (i != -1) {
- c = (char) i;
- if (afterCR) {
- for (CharHandler handler : handlers) {
- if (c != CARRIAGE_RETURN && c != LINE_FEED) {
- handler.handleIgnoreEoL(c);
- }
- handler.handleAll(c);
- handler.newLine();
- }
- afterCR = c == CARRIAGE_RETURN;
- } else if (c == LINE_FEED) {
- for (CharHandler handler : handlers) {
- handler.handleAll(c);
- handler.newLine();
- }
- } else if (c == CARRIAGE_RETURN) {
- afterCR = true;
- for (CharHandler handler : handlers) {
- handler.handleAll(c);
- }
- } else {
- for (CharHandler handler : handlers) {
+ read(reader, handlers);
+ } catch (IOException e) {
+ throw new IllegalStateException(String.format("Fail to read file '%s' with encoding '%s'", file.getAbsolutePath(), encoding), e);
+ }
+ }
+
+ private static void read(Reader reader, CharHandler... handlers) throws IOException {
+ char c = (char) 0;
+ int i = reader.read();
+ boolean afterCR = false;
+ while (i != -1) {
+ c = (char) i;
+ if (afterCR) {
+ for (CharHandler handler : handlers) {
+ if (c != CARRIAGE_RETURN && c != LINE_FEED) {
handler.handleIgnoreEoL(c);
- handler.handleAll(c);
}
+ handler.handleAll(c);
+ handler.newLine();
+ }
+ afterCR = c == CARRIAGE_RETURN;
+ } else if (c == LINE_FEED) {
+ for (CharHandler handler : handlers) {
+ handler.handleAll(c);
+ handler.newLine();
+ }
+ } else if (c == CARRIAGE_RETURN) {
+ afterCR = true;
+ for (CharHandler handler : handlers) {
+ handler.handleAll(c);
+ }
+ } else {
+ for (CharHandler handler : handlers) {
+ handler.handleIgnoreEoL(c);
+ handler.handleAll(c);
}
- i = reader.read();
- }
- for (CharHandler handler : handlers) {
- handler.eof();
}
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to read file '%s' with encoding '%s'", file.getAbsolutePath(), encoding), e);
+ i = reader.read();
+ }
+ for (CharHandler handler : handlers) {
+ handler.eof();
}
}
- static class Metadata {
+ public static class Metadata {
final int lines;
final int nonBlankLines;
final String hash;
@@ -317,6 +326,6 @@ public class FileMetadata implements BatchComponent {
* Compute a MD5 hash of each line of the file after removing of all blank chars
*/
public static void computeLineHashesForIssueTracking(DefaultInputFile f, LineHashConsumer consumer) {
- scanFile(f.file(), f.charset(), new LineHashComputer(consumer));
+ readFile(f.file(), f.charset(), new LineHashComputer(consumer));
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java
index 60e0db9a2d3..50bb7cbab30 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlighting.java
@@ -36,7 +36,7 @@ import java.util.Set;
public class DefaultHighlighting extends DefaultStorable implements NewHighlighting {
- private InputFile inputFile;
+ private DefaultInputFile inputFile;
private Set<SyntaxHighlightingRule> syntaxHighlightingRuleSet;
public DefaultHighlighting() {
@@ -48,9 +48,9 @@ public class DefaultHighlighting extends DefaultStorable implements NewHighlight
syntaxHighlightingRuleSet = Sets.newTreeSet(new Comparator<SyntaxHighlightingRule>() {
@Override
public int compare(SyntaxHighlightingRule left, SyntaxHighlightingRule right) {
- int result = left.getStartPosition() - right.getStartPosition();
+ int result = left.range().start().compareTo(right.range().start());
if (result == 0) {
- result = right.getEndPosition() - left.getEndPosition();
+ result = right.range().end().compareTo(left.range().end());
}
return result;
}
@@ -67,9 +67,9 @@ public class DefaultHighlighting extends DefaultStorable implements NewHighlight
SyntaxHighlightingRule previous = it.next();
while (it.hasNext()) {
SyntaxHighlightingRule current = it.next();
- if (previous.getEndPosition() > current.getStartPosition() && !(previous.getEndPosition() >= current.getEndPosition())) {
- String errorMsg = String.format("Cannot register highlighting rule for characters from %s to %s as it " +
- "overlaps at least one existing rule", current.getStartPosition(), current.getEndPosition());
+ if (previous.range().end().compareTo(current.range().start()) > 0 && !(previous.range().end().compareTo(current.range().end()) >= 0)) {
+ String errorMsg = String.format("Cannot register highlighting rule for characters at %s as it " +
+ "overlaps at least one existing rule", current.range());
throw new IllegalStateException(errorMsg);
}
previous = current;
@@ -80,7 +80,7 @@ public class DefaultHighlighting extends DefaultStorable implements NewHighlight
@Override
public DefaultHighlighting onFile(InputFile inputFile) {
Preconditions.checkNotNull(inputFile, "file can't be null");
- this.inputFile = inputFile;
+ this.inputFile = (DefaultInputFile) inputFile;
return this;
}
@@ -91,21 +91,11 @@ public class DefaultHighlighting extends DefaultStorable implements NewHighlight
@Override
public DefaultHighlighting highlight(int startOffset, int endOffset, TypeOfText typeOfText) {
Preconditions.checkState(inputFile != null, "Call onFile() first");
- int maxValidOffset = ((DefaultInputFile) inputFile).lastValidOffset();
- checkOffset(startOffset, maxValidOffset, "startOffset");
- checkOffset(endOffset, maxValidOffset, "endOffset");
- Preconditions.checkArgument(startOffset < endOffset, "startOffset (" + startOffset + ") should be < endOffset (" + endOffset + ") for file " + inputFile + ".");
- SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(startOffset, endOffset,
- typeOfText);
+ SyntaxHighlightingRule syntaxHighlightingRule = SyntaxHighlightingRule.create(inputFile.newRange(startOffset, endOffset), typeOfText);
this.syntaxHighlightingRuleSet.add(syntaxHighlightingRule);
return this;
}
- private void checkOffset(int offset, int maxValidOffset, String label) {
- Preconditions.checkArgument(offset >= 0 && offset <= maxValidOffset, "Invalid " + label + " " + offset + ". Should be >= 0 and <= " + maxValidOffset
- + " for file " + inputFile);
- }
-
@Override
protected void doSave() {
Preconditions.checkState(inputFile != null, "Call onFile() first");
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java
index 9989449ff00..c9b1f000c09 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/highlighting/internal/SyntaxHighlightingRule.java
@@ -19,32 +19,27 @@
*/
package org.sonar.api.batch.sensor.highlighting.internal;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.builder.ToStringStyle;
+import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
-import java.io.Serializable;
+public class SyntaxHighlightingRule {
-public class SyntaxHighlightingRule implements Serializable {
-
- private final int startPosition;
- private final int endPosition;
+ private final TextRange range;
private final TypeOfText textType;
- private SyntaxHighlightingRule(int startPosition, int endPosition, TypeOfText textType) {
- this.startPosition = startPosition;
- this.endPosition = endPosition;
+ private SyntaxHighlightingRule(TextRange range, TypeOfText textType) {
+ this.range = range;
this.textType = textType;
}
- public static SyntaxHighlightingRule create(int startPosition, int endPosition, TypeOfText textType) {
- return new SyntaxHighlightingRule(startPosition, endPosition, textType);
- }
-
- public int getStartPosition() {
- return startPosition;
+ public static SyntaxHighlightingRule create(TextRange range, TypeOfText textType) {
+ return new SyntaxHighlightingRule(range, textType);
}
- public int getEndPosition() {
- return endPosition;
+ public TextRange range() {
+ return range;
}
public TypeOfText getTextType() {
@@ -53,6 +48,6 @@ public class SyntaxHighlightingRule implements Serializable {
@Override
public String toString() {
- return "" + startPosition + "," + endPosition + "," + textType.cssClass();
+ return ReflectionToStringBuilder.toString(this, ToStringStyle.SIMPLE_STYLE);
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
index 2846e0676fb..278d9ad1741 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java
@@ -27,6 +27,7 @@ import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.sensor.Sensor;
@@ -55,12 +56,7 @@ import javax.annotation.Nullable;
import java.io.File;
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* Utility class to help testing {@link Sensor}.
@@ -179,14 +175,15 @@ public class SensorContextTester implements SensorContext {
return new DefaultHighlighting(sensorStorage);
}
- public List<TypeOfText> highlightingTypeFor(String componentKey, int charIndex) {
+ public List<TypeOfText> highlightingTypeAt(String componentKey, int line, int lineOffset) {
DefaultHighlighting syntaxHighlightingData = sensorStorage.highlightingByComponent.get(componentKey);
if (syntaxHighlightingData == null) {
return Collections.emptyList();
}
List<TypeOfText> result = new ArrayList<TypeOfText>();
+ DefaultTextPointer location = new DefaultTextPointer(line, lineOffset);
for (SyntaxHighlightingRule sortedRule : syntaxHighlightingData.getSyntaxHighlightingRuleSet()) {
- if (sortedRule.getStartPosition() <= charIndex && sortedRule.getEndPosition() > charIndex) {
+ if (sortedRule.range().start().compareTo(location) <= 0 && sortedRule.range().end().compareTo(location) > 0) {
result.add(sortedRule.getTextType());
}
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
index 850d3e6cdc7..121ba2a874c 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorStorage.java
@@ -19,6 +19,7 @@
*/
package org.sonar.api.batch.sensor.internal;
+import org.sonar.api.BatchComponent;
import org.sonar.api.batch.sensor.dependency.Dependency;
import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
@@ -29,7 +30,7 @@ import org.sonar.api.batch.sensor.measure.Measure;
* Interface for storing data computed by sensors.
* @since 5.1
*/
-public interface SensorStorage {
+public interface SensorStorage extends BatchComponent {
void store(Measure measure);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/component/Perspectives.java b/sonar-plugin-api/src/main/java/org/sonar/api/component/Perspectives.java
index a5f7773e745..8f16849892e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/component/Perspectives.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/component/Perspectives.java
@@ -22,6 +22,10 @@ package org.sonar.api.component;
import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
+/**
+ * @deprecated since 5.2 unused
+ */
+@Deprecated
public interface Perspectives extends BatchComponent, ServerComponent {
<P extends Perspective> P as(Class<P> perspectiveClass, Component component);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
index d92592678eb..e8555ed4e35 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/ComponentContainer.java
@@ -32,6 +32,7 @@ import org.sonar.api.ServerComponent;
import org.sonar.api.config.PropertyDefinitions;
import javax.annotation.Nullable;
+
import java.util.Collection;
import java.util.List;
@@ -172,7 +173,11 @@ public class ComponentContainer implements BatchComponent, ServerComponent {
if (component instanceof ComponentAdapter) {
pico.addAdapter((ComponentAdapter) component);
} else {
- pico.as(singleton ? Characteristics.CACHE : Characteristics.NO_CACHE).addComponent(key, component);
+ try {
+ pico.as(singleton ? Characteristics.CACHE : Characteristics.NO_CACHE).addComponent(key, component);
+ } catch (Throwable t) {
+ throw new IllegalStateException("Unable to register component " + getName(component), t);
+ }
declareExtension(null, component);
}
return this;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbol.java b/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbol.java
index dd4c7d40883..091b881fabe 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbol.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbol.java
@@ -22,12 +22,19 @@ package org.sonar.api.source;
public interface Symbol {
+ /**
+ * @deprecated in 5.2 not used.
+ */
+ @Deprecated
int getDeclarationStartOffset();
+ /**
+ * @deprecated in 5.2 not used.
+ */
+ @Deprecated
int getDeclarationEndOffset();
/**
- * @since unused
* @deprecated in 4.3 not used.
*/
@Deprecated
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java b/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java
index 1cc82162047..f205ec41c17 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/source/Symbolizable.java
@@ -44,6 +44,10 @@ public interface Symbolizable extends Perspective {
List<Symbol> symbols();
+ /**
+ * @deprecated since 5.2 not used
+ */
+ @Deprecated
List<Integer> references(Symbol symbol);
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
index edf072dca79..6b8b6af9fea 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/DefaultInputFileTest.java
@@ -27,6 +27,7 @@ import org.sonar.api.batch.fs.InputFile;
import java.io.File;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
public class DefaultInputFileTest {
@@ -73,4 +74,110 @@ public class DefaultInputFileTest {
DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php");
assertThat(file.toString()).isEqualTo("[moduleKey=ABCDE, relative=src/Foo.php, basedir=null]");
}
+
+ @Test
+ public void checkValidPointer() {
+ DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php");
+ file.setLines(2);
+ file.setOriginalLineOffsets(new int[] {0, 10});
+ file.setLastValidOffset(15);
+ assertThat(file.newPointer(1, 0).line()).isEqualTo(1);
+ assertThat(file.newPointer(1, 0).lineOffset()).isEqualTo(0);
+ // Don't fail
+ file.newPointer(1, 9);
+ file.newPointer(2, 0);
+ file.newPointer(2, 5);
+
+ try {
+ file.newPointer(0, 1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("0 is not a valid line for a file");
+ }
+ try {
+ file.newPointer(3, 1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("3 is not a valid line for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=null] has 2 line(s)");
+ }
+ try {
+ file.newPointer(1, -1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("-1 is not a valid line offset for a file");
+ }
+ try {
+ file.newPointer(1, 10);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("10 is not a valid line offset for pointer. File [moduleKey=ABCDE, relative=src/Foo.php, basedir=null] has 9 character(s) at line 1");
+ }
+ }
+
+ @Test
+ public void checkValidPointerUsingGlobalOffset() {
+ DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php");
+ file.setLines(2);
+ file.setOriginalLineOffsets(new int[] {0, 10});
+ file.setLastValidOffset(15);
+ assertThat(file.newPointer(0).line()).isEqualTo(1);
+ assertThat(file.newPointer(0).lineOffset()).isEqualTo(0);
+
+ assertThat(file.newPointer(9).line()).isEqualTo(1);
+ assertThat(file.newPointer(9).lineOffset()).isEqualTo(9);
+
+ assertThat(file.newPointer(10).line()).isEqualTo(2);
+ assertThat(file.newPointer(10).lineOffset()).isEqualTo(0);
+
+ assertThat(file.newPointer(15).line()).isEqualTo(2);
+ assertThat(file.newPointer(15).lineOffset()).isEqualTo(5);
+
+ try {
+ file.newPointer(-1);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("-1 is not a valid offset for a file");
+ }
+
+ try {
+ file.newPointer(16);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("16 is not a valid offset for file [moduleKey=ABCDE, relative=src/Foo.php, basedir=null]. Max offset is 15");
+ }
+ }
+
+ @Test
+ public void checkValidRange() {
+ DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php");
+ file.setLines(2);
+ file.setOriginalLineOffsets(new int[] {0, 10});
+ file.setLastValidOffset(15);
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 1)).start().line()).isEqualTo(1);
+ // Don't fail
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 1));
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 9));
+ file.newRange(file.newPointer(1, 0), file.newPointer(2, 0));
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(2, 5))).isEqualTo(file.newRange(0, 15));
+
+ try {
+ file.newRange(file.newPointer(1, 0), file.newPointer(1, 0));
+ fail();
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0]");
+ }
+ }
+
+ @Test
+ public void testRangeOverlap() {
+ DefaultInputFile file = new DefaultInputFile("ABCDE", "src/Foo.php");
+ file.setLines(2);
+ file.setOriginalLineOffsets(new int[] {0, 10});
+ file.setLastValidOffset(15);
+ // Don't fail
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)))).isTrue();
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isTrue();
+ assertThat(file.newRange(file.newPointer(1, 0), file.newPointer(1, 1)).overlap(file.newRange(file.newPointer(1, 1), file.newPointer(1, 2)))).isFalse();
+ assertThat(file.newRange(file.newPointer(1, 2), file.newPointer(1, 3)).overlap(file.newRange(file.newPointer(1, 0), file.newPointer(1, 2)))).isFalse();
+ }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileMetadataTest.java
index a470378a99e..7696c1afcbf 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/fs/internal/FileMetadataTest.java
@@ -17,7 +17,7 @@
* 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;
+package org.sonar.api.batch.fs.internal;
import com.google.common.base.Charsets;
import org.apache.commons.codec.binary.Hex;
@@ -26,11 +26,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
import org.sonar.api.utils.log.LogTester;
import org.sonar.api.utils.log.LoggerLevel;
-import org.sonar.batch.scan.filesystem.FileMetadata.LineHashConsumer;
import javax.annotation.Nullable;
@@ -39,7 +37,6 @@ import java.nio.charset.Charset;
import static org.apache.commons.codec.digest.DigestUtils.md5Hex;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
public class FileMetadataTest {
@@ -49,8 +46,6 @@ public class FileMetadataTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- private AnalysisMode mode = mock(AnalysisMode.class);
-
@Rule
public LogTester logTester = new LogTester();
@@ -59,7 +54,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.touch(tempFile);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(1);
assertThat(metadata.nonBlankLines).isEqualTo(0);
assertThat(metadata.hash).isNotEmpty();
@@ -73,7 +68,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\r\nbar\r\nbaz", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(3);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz"));
@@ -87,7 +82,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "marker´s\n", Charset.forName("cp1252"));
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(2);
assertThat(metadata.hash).isEqualTo(md5Hex("marker\ufffds\n"));
assertThat(metadata.originalLineOffsets).containsOnly(0, 9);
@@ -98,7 +93,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n"));
@@ -110,7 +105,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", Charsets.UTF_16, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_16);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_16);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n"));
@@ -122,7 +117,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\nbar\nbaz", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(3);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz"));
@@ -135,7 +130,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\nbar\nbaz\n", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
@@ -148,7 +143,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\nbar\r\nbaz\n", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz\n"));
@@ -160,7 +155,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\n\n\nbar", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(2);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\n\n\nbar"));
@@ -172,7 +167,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "foo\nbar\r\nbaz", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(3);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz"));
@@ -184,7 +179,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "\nfoo\nbar\r\nbaz", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(4);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("\nfoo\nbar\nbaz"));
@@ -196,7 +191,7 @@ public class FileMetadataTest {
File tempFile = temp.newFile();
FileUtils.write(tempFile, "\uFEFFfoo\nbar\r\nbaz", Charsets.UTF_8, true);
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(tempFile, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(tempFile, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(3);
assertThat(metadata.nonBlankLines).isEqualTo(3);
assertThat(metadata.hash).isEqualTo(md5Hex("foo\nbar\nbaz"));
@@ -238,7 +233,7 @@ public class FileMetadataTest {
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Fail to read file '" + file.getAbsolutePath() + "' with encoding 'UTF-8'");
- new FileMetadata(mode).read(file, Charsets.UTF_8);
+ new FileMetadata().readMetadata(file, Charsets.UTF_8);
}
@Test
@@ -253,9 +248,9 @@ public class FileMetadataTest {
File file2 = temp.newFile();
FileUtils.write(file2, "foo\nbar", Charsets.UTF_8, true);
- String hash1 = new FileMetadata(mode).read(file1, Charsets.UTF_8).hash;
- String hash1a = new FileMetadata(mode).read(file1a, Charsets.UTF_8).hash;
- String hash2 = new FileMetadata(mode).read(file2, Charsets.UTF_8).hash;
+ String hash1 = new FileMetadata().readMetadata(file1, Charsets.UTF_8).hash;
+ String hash1a = new FileMetadata().readMetadata(file1a, Charsets.UTF_8).hash;
+ String hash2 = new FileMetadata().readMetadata(file2, Charsets.UTF_8).hash;
assertThat(hash1).isEqualTo(hash1a);
assertThat(hash1).isNotEqualTo(hash2);
}
@@ -264,7 +259,7 @@ public class FileMetadataTest {
public void binary_file_with_unmappable_character() throws Exception {
File woff = new File(this.getClass().getResource("glyphicons-halflings-regular.woff").toURI());
- FileMetadata.Metadata metadata = new FileMetadata(mode).read(woff, Charsets.UTF_8);
+ FileMetadata.Metadata metadata = new FileMetadata().readMetadata(woff, Charsets.UTF_8);
assertThat(metadata.lines).isEqualTo(135);
assertThat(metadata.nonBlankLines).isEqualTo(134);
assertThat(metadata.hash).isNotEmpty();
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java
index 4cf1225e27b..79f7db9e06b 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/highlighting/internal/DefaultHighlightingTest.java
@@ -23,7 +23,10 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.DefaultTextPointer;
+import org.sonar.api.batch.fs.internal.DefaultTextRange;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import java.util.Collection;
@@ -36,6 +39,11 @@ import static org.sonar.api.batch.sensor.highlighting.TypeOfText.KEYWORD;
public class DefaultHighlightingTest {
+ private static final DefaultInputFile INPUT_FILE = new DefaultInputFile("foo", "src/Foo.java")
+ .setLines(2)
+ .setOriginalLineOffsets(new int[] {0, 50})
+ .setLastValidOffset(100);
+
private Collection<SyntaxHighlightingRule> highlightingRules;
@Rule
@@ -45,7 +53,7 @@ public class DefaultHighlightingTest {
public void setUpSampleRules() {
DefaultHighlighting highlightingDataBuilder = new DefaultHighlighting()
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(100))
+ .onFile(INPUT_FILE)
.highlight(0, 10, COMMENT)
.highlight(10, 12, KEYWORD)
.highlight(24, 38, KEYWORD)
@@ -61,17 +69,25 @@ public class DefaultHighlightingTest {
assertThat(highlightingRules).hasSize(6);
}
+ private static TextRange rangeOf(int startLine, int startOffset, int endLine, int endOffset) {
+ return new DefaultTextRange(new DefaultTextPointer(startLine, startOffset), new DefaultTextPointer(endLine, endOffset));
+ }
+
@Test
public void should_order_by_start_then_end_offset() throws Exception {
- assertThat(highlightingRules).extracting("startPosition").containsOnly(0, 10, 12, 24, 24, 42);
- assertThat(highlightingRules).extracting("endPosition").containsOnly(10, 12, 20, 38, 65, 50);
+ assertThat(highlightingRules).extracting("range", TextRange.class).containsExactly(rangeOf(1, 0, 1, 10),
+ rangeOf(1, 10, 1, 12),
+ rangeOf(1, 12, 1, 20),
+ rangeOf(1, 24, 2, 15),
+ rangeOf(1, 24, 1, 38),
+ rangeOf(1, 42, 2, 0));
assertThat(highlightingRules).extracting("textType").containsOnly(COMMENT, KEYWORD, COMMENT, KEYWORD, CPP_DOC, KEYWORD);
}
@Test
public void should_suport_overlapping() throws Exception {
new DefaultHighlighting(mock(SensorStorage.class))
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(100))
+ .onFile(INPUT_FILE)
.highlight(0, 15, KEYWORD)
.highlight(8, 12, CPP_DOC)
.save();
@@ -80,49 +96,14 @@ public class DefaultHighlightingTest {
@Test
public void should_prevent_boudaries_overlapping() throws Exception {
throwable.expect(IllegalStateException.class);
- throwable.expectMessage("Cannot register highlighting rule for characters from 8 to 15 as it overlaps at least one existing rule");
+ throwable
+ .expectMessage("Cannot register highlighting rule for characters at Range[from [line=1, lineOffset=8] to [line=1, lineOffset=15]] as it overlaps at least one existing rule");
new DefaultHighlighting(mock(SensorStorage.class))
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(100))
+ .onFile(INPUT_FILE)
.highlight(0, 10, KEYWORD)
.highlight(8, 15, KEYWORD)
.save();
}
- @Test
- public void should_prevent_invalid_offset() throws Exception {
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("Invalid endOffset 15. Should be >= 0 and <= 10 for file [moduleKey=foo, relative=src/Foo.java, basedir=null]");
-
- new DefaultHighlighting(mock(SensorStorage.class))
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(10))
- .highlight(0, 10, KEYWORD)
- .highlight(8, 15, KEYWORD)
- .save();
- }
-
- @Test
- public void positive_offset() throws Exception {
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("Invalid startOffset -8. Should be >= 0 and <= 10 for file [moduleKey=foo, relative=src/Foo.java, basedir=null]");
-
- new DefaultHighlighting(mock(SensorStorage.class))
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(10))
- .highlight(0, 10, KEYWORD)
- .highlight(-8, 15, KEYWORD)
- .save();
- }
-
- @Test
- public void should_prevent_invalid_offset_order() throws Exception {
- throwable.expect(IllegalArgumentException.class);
- throwable.expectMessage("startOffset (18) should be < endOffset (15) for file [moduleKey=foo, relative=src/Foo.java, basedir=null].");
-
- new DefaultHighlighting(mock(SensorStorage.class))
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(20))
- .highlight(0, 10, KEYWORD)
- .highlight(18, 15, KEYWORD)
- .save();
- }
-
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
index 0be267797b7..c1784a24dfc 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java
@@ -26,6 +26,7 @@ import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.fs.internal.FileMetadata;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
@@ -34,6 +35,7 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.rule.RuleKey;
import java.io.File;
+import java.io.StringReader;
import static org.assertj.core.api.Assertions.assertThat;
@@ -142,15 +144,15 @@ public class SensorContextTesterTest {
@Test
public void testHighlighting() {
- assertThat(tester.highlightingTypeFor("foo:src/Foo.java", 3)).isEmpty();
+ assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).isEmpty();
tester.newHighlighting()
- .onFile(new DefaultInputFile("foo", "src/Foo.java").setLastValidOffset(100))
+ .onFile(new DefaultInputFile("foo", "src/Foo.java").initMetadata(new FileMetadata().readMetadata(new StringReader("annot dsf fds foo bar"))))
.highlight(0, 4, TypeOfText.ANNOTATION)
.highlight(8, 10, TypeOfText.CONSTANT)
.highlight(9, 10, TypeOfText.COMMENT)
.save();
- assertThat(tester.highlightingTypeFor("foo:src/Foo.java", 3)).containsExactly(TypeOfText.ANNOTATION);
- assertThat(tester.highlightingTypeFor("foo:src/Foo.java", 9)).containsExactly(TypeOfText.CONSTANT, TypeOfText.COMMENT);
+ assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 3)).containsExactly(TypeOfText.ANNOTATION);
+ assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 9)).containsExactly(TypeOfText.CONSTANT, TypeOfText.COMMENT);
}
@Test
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/filesystem/glyphicons-halflings-regular.woff b/sonar-plugin-api/src/test/resources/org/sonar/api/batch/fs/internal/glyphicons-halflings-regular.woff
index 2cc3e4852a5..2cc3e4852a5 100644
--- a/sonar-batch/src/test/resources/org/sonar/batch/scan/filesystem/glyphicons-halflings-regular.woff
+++ b/sonar-plugin-api/src/test/resources/org/sonar/api/batch/fs/internal/glyphicons-halflings-regular.woff
Binary files differ