summaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2015-11-04 17:43:02 +0100
committerJulien HENRY <julien.henry@sonarsource.com>2015-11-09 08:41:26 +0100
commitd24589f13f3e6712be21bacd14b670f5eacdfe8b (patch)
tree69b005107ffe32d8f9289ba90913b210b69ff2b1 /sonar-batch/src/main
parenteb5fd4fe77eb1b82b3aa5e1c3474d85ac39ee9ce (diff)
downloadsonarqube-d24589f13f3e6712be21bacd14b670f5eacdfe8b.tar.gz
sonarqube-d24589f13f3e6712be21bacd14b670f5eacdfe8b.zip
SONAR-6989 Feed the file duplication index in the batch report
Diffstat (limited to 'sonar-batch/src/main')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java52
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java80
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java71
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java42
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java45
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java14
10 files changed, 148 insertions, 182 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
index 31784aa1e80..34df18afaa8 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
@@ -19,16 +19,15 @@
*/
package org.sonar.batch.analysis;
-import org.sonar.batch.bootstrap.AbstractAnalysisMode;
-
-import org.sonar.batch.mediumtest.FakePluginInstaller;
-import org.sonar.batch.bootstrap.GlobalProperties;
+import java.util.Map;
+import javax.annotation.CheckForNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.AnalysisMode;
-
-import java.util.Map;
+import org.sonar.batch.bootstrap.AbstractAnalysisMode;
+import org.sonar.batch.bootstrap.GlobalProperties;
+import org.sonar.batch.mediumtest.FakePluginInstaller;
/**
* @since 4.0
@@ -99,6 +98,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
}
}
+ @CheckForNull
private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) {
if (props1.containsKey(key)) {
return props1.get(key);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java
index e2c5555d4e2..ffac2cba012 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java
@@ -20,11 +20,8 @@
package org.sonar.batch.cpd;
import com.google.common.collect.ImmutableList;
-
import java.util.List;
-import org.sonar.batch.cpd.index.IndexFactory;
-
public final class CpdComponents {
private CpdComponents() {
@@ -34,7 +31,6 @@ public final class CpdComponents {
return ImmutableList.of(
CpdSensor.class,
CpdMappings.class,
- IndexFactory.class,
JavaCpdEngine.class,
DefaultCpdEngine.class);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java
index 93fc1726b46..a63b04f0006 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java
@@ -23,6 +23,13 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
@@ -33,24 +40,13 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.cpd.index.IndexFactory;
import org.sonar.batch.cpd.index.SonarDuplicationsIndex;
+import org.sonar.batch.index.BatchComponentCache;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.index.CloneGroup;
import org.sonar.duplications.internal.pmd.TokenizerBridge;
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
public class DefaultCpdEngine extends CpdEngine {
private static final Logger LOG = LoggerFactory.getLogger(DefaultCpdEngine.class);
@@ -60,22 +56,18 @@ public class DefaultCpdEngine extends CpdEngine {
*/
private static final int TIMEOUT = 5 * 60;
- private final IndexFactory indexFactory;
private final CpdMappings mappings;
private final FileSystem fs;
private final Settings settings;
- private final Project project;
+ private final ReportPublisher publisher;
+ private final BatchComponentCache batchComponentCache;
- public DefaultCpdEngine(@Nullable Project project, IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings) {
- this.project = project;
- this.indexFactory = indexFactory;
+ public DefaultCpdEngine(CpdMappings mappings, FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) {
this.mappings = mappings;
this.fs = fs;
this.settings = settings;
- }
-
- public DefaultCpdEngine(IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings) {
- this(null, indexFactory, mappings, fs, settings);
+ this.publisher = publisher;
+ this.batchComponentCache = batchComponentCache;
}
@Override
@@ -97,14 +89,13 @@ public class DefaultCpdEngine extends CpdEngine {
List<InputFile> sourceFiles = Lists.newArrayList(fs.inputFiles(p.and(
p.hasType(InputFile.Type.MAIN),
p.hasLanguage(languageKey),
- p.doesNotMatchPathPatterns(cpdExclusions)
- )));
+ p.doesNotMatchPathPatterns(cpdExclusions))));
if (sourceFiles.isEmpty()) {
return;
}
// Create index
- SonarDuplicationsIndex index = indexFactory.create(project, languageKey);
+ SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings);
populateIndex(languageKey, sourceFiles, mapping, index);
// Detect
@@ -129,7 +120,7 @@ public class DefaultCpdEngine extends CpdEngine {
filtered = null;
LOG.warn("Timeout during detection of duplications for " + inputFile, e);
} catch (InterruptedException | ExecutionException e) {
- throw new SonarException("Fail during detection of duplication for " + inputFile, e);
+ throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e);
}
JavaCpdEngine.save(context, inputFile, filtered);
@@ -144,8 +135,8 @@ public class DefaultCpdEngine extends CpdEngine {
for (InputFile inputFile : sourceFiles) {
LOG.debug("Populating index from {}", inputFile);
String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
- List<Block> blocks2 = bridge.chunk(resourceEffectiveKey, inputFile.file());
- index.insert(inputFile, blocks2);
+ List<Block> blocks = bridge.chunk(resourceEffectiveKey, inputFile.file());
+ index.insert(inputFile, blocks);
}
}
@@ -162,7 +153,7 @@ public class DefaultCpdEngine extends CpdEngine {
static int getDefaultBlockSize(String languageKey) {
if ("cobol".equals(languageKey)) {
return 30;
- } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
+ } else if ("abap".equals(languageKey)) {
return 20;
} else {
return 10;
@@ -173,9 +164,6 @@ public class DefaultCpdEngine extends CpdEngine {
int getMinimumTokens(String languageKey) {
int minimumTokens = settings.getInt("sonar.cpd." + languageKey + ".minimumTokens");
if (minimumTokens == 0) {
- minimumTokens = settings.getInt(CoreProperties.CPD_MINIMUM_TOKENS_PROPERTY);
- }
- if (minimumTokens == 0) {
minimumTokens = 100;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java
index 97059241af5..1adca4f11ca 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java
@@ -22,6 +22,21 @@ package org.sonar.batch.cpd;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+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.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import javax.annotation.Nullable;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,10 +51,9 @@ import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.config.Settings;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.resources.Project;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.cpd.index.IndexFactory;
import org.sonar.batch.cpd.index.SonarDuplicationsIndex;
+import org.sonar.batch.index.BatchComponentCache;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.BlockChunker;
import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm;
@@ -52,23 +66,6 @@ import org.sonar.duplications.statement.Statement;
import org.sonar.duplications.statement.StatementChunker;
import org.sonar.duplications.token.TokenChunker;
-import javax.annotation.Nullable;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-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.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
public class JavaCpdEngine extends CpdEngine {
private static final Logger LOG = LoggerFactory.getLogger(JavaCpdEngine.class);
@@ -83,20 +80,16 @@ public class JavaCpdEngine extends CpdEngine {
private static final int MAX_CLONE_GROUP_PER_FILE = 100;
private static final int MAX_CLONE_PART_PER_GROUP = 100;
- private final IndexFactory indexFactory;
private final FileSystem fs;
private final Settings settings;
- private final Project project;
+ private final ReportPublisher publisher;
+ private final BatchComponentCache batchComponentCache;
- public JavaCpdEngine(@Nullable Project project, IndexFactory indexFactory, FileSystem fs, Settings settings) {
- this.project = project;
- this.indexFactory = indexFactory;
+ public JavaCpdEngine(FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) {
this.fs = fs;
this.settings = settings;
- }
-
- public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) {
- this(null, indexFactory, fs, settings);
+ this.publisher = publisher;
+ this.batchComponentCache = batchComponentCache;
}
@Override
@@ -112,17 +105,16 @@ public class JavaCpdEngine extends CpdEngine {
List<InputFile> sourceFiles = Lists.newArrayList(fs.inputFiles(p.and(
p.hasType(InputFile.Type.MAIN),
p.hasLanguage(languageKey),
- p.doesNotMatchPathPatterns(cpdExclusions)
- )));
+ p.doesNotMatchPathPatterns(cpdExclusions))));
if (sourceFiles.isEmpty()) {
return;
}
- SonarDuplicationsIndex index = createIndex(project, languageKey, sourceFiles);
+ SonarDuplicationsIndex index = createIndex(sourceFiles);
detect(index, context, sourceFiles);
}
- private SonarDuplicationsIndex createIndex(@Nullable Project project, String language, Iterable<InputFile> sourceFiles) {
- final SonarDuplicationsIndex index = indexFactory.create(project, language);
+ private SonarDuplicationsIndex createIndex(Iterable<InputFile> sourceFiles) {
+ final SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings);
TokenChunker tokenChunker = JavaTokenProducer.build();
StatementChunker statementChunker = JavaStatementBuilder.build();
@@ -139,7 +131,7 @@ public class JavaCpdEngine extends CpdEngine {
reader = new InputStreamReader(new FileInputStream(inputFile.file()), fs.encoding());
statements = statementChunker.chunk(tokenChunker.chunk(reader));
} catch (FileNotFoundException e) {
- throw new SonarException("Cannot find file " + inputFile.file(), e);
+ throw new IllegalStateException("Cannot find file " + inputFile.file(), e);
} finally {
IOUtils.closeQuietly(reader);
}
@@ -166,10 +158,8 @@ public class JavaCpdEngine extends CpdEngine {
} catch (TimeoutException e) {
clones = null;
LOG.warn("Timeout during detection of duplications for " + inputFile, e);
- } catch (InterruptedException e) {
- throw new SonarException("Fail during detection of duplication for " + inputFile, e);
- } catch (ExecutionException e) {
- throw new SonarException("Fail during detection of duplication for " + inputFile, e);
+ } catch (InterruptedException | ExecutionException e) {
+ throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e);
}
save(context, inputFile, clones);
@@ -209,20 +199,20 @@ public class JavaCpdEngine extends CpdEngine {
.forMetric(CoreMetrics.DUPLICATED_FILES)
.on(inputFile)
.withValue(1))
- .setFromCore()
- .save();
+ .setFromCore()
+ .save();
((DefaultMeasure<Integer>) context.<Integer>newMeasure()
.forMetric(CoreMetrics.DUPLICATED_LINES)
.on(inputFile)
.withValue(duplicatedLines))
- .setFromCore()
- .save();
+ .setFromCore()
+ .save();
((DefaultMeasure<Integer>) context.<Integer>newMeasure()
.forMetric(CoreMetrics.DUPLICATED_BLOCKS)
.on(inputFile)
.withValue(duplicatedBlocks))
- .setFromCore()
- .save();
+ .setFromCore()
+ .save();
}
private static void saveDuplications(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, Iterable<CloneGroup> duplications) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java
deleted file mode 100644
index 31a4b03ce55..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/IndexFactory.java
+++ /dev/null
@@ -1,71 +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.cpd.index;
-
-import org.sonar.batch.analysis.DefaultAnalysisMode;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.BatchSide;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-
-@BatchSide
-public class IndexFactory {
-
- private final Settings settings;
- private final DefaultAnalysisMode mode;
-
- public IndexFactory(DefaultAnalysisMode mode, Settings settings) {
- this.mode = mode;
- this.settings = settings;
- }
-
- public SonarDuplicationsIndex create(@Nullable Project project, String languageKey) {
- return new SonarDuplicationsIndex();
- }
-
- @VisibleForTesting
- boolean verifyCrossProject(@Nullable Project project, Logger logger) {
- boolean crossProject = false;
-
- if (settings.getBoolean(CoreProperties.CPD_CROSS_PROJECT)) {
- if (mode.isIssues()) {
- logger.info("Cross-project analysis disabled. Not supported in issues mode.");
- } else if (StringUtils.isNotBlank(settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY))) {
- logger.info("Cross-project analysis disabled. Not supported on project branches.");
- } else if (project == null) {
- // New sensor mode
- logger.info("Cross-project analysis disabled. Not supported in new sensor mode.");
- } else {
- logger.info("Cross-project analysis enabled");
- crossProject = true;
- }
- } else {
- logger.info("Cross-project analysis disabled");
- }
- return crossProject;
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java
index ab583d672dd..51a094a869e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java
@@ -19,8 +19,17 @@
*/
package org.sonar.batch.cpd.index;
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
import java.util.Collection;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.config.Settings;
+import org.sonar.batch.index.BatchComponentCache;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.DuplicationBlock;
+import org.sonar.batch.report.ReportPublisher;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
import org.sonar.duplications.index.AbstractCloneIndex;
@@ -30,13 +39,46 @@ import org.sonar.duplications.index.PackedMemoryCloneIndex;
public class SonarDuplicationsIndex extends AbstractCloneIndex {
private final CloneIndex mem = new PackedMemoryCloneIndex();
+ private final ReportPublisher publisher;
+ private final BatchComponentCache batchComponentCache;
+ private final Settings settings;
+
+ public SonarDuplicationsIndex(ReportPublisher publisher, BatchComponentCache batchComponentCache, Settings settings) {
+ this.publisher = publisher;
+ this.batchComponentCache = batchComponentCache;
+ this.settings = settings;
+ }
public void insert(InputFile inputFile, Collection<Block> blocks) {
+ if (isCrossProjectDuplicationEnabled(settings)) {
+ int id = batchComponentCache.get(inputFile).batchId();
+ final BatchReport.DuplicationBlock.Builder builder = BatchReport.DuplicationBlock.newBuilder();
+ publisher.getWriter().writeDuplicationBlocks(id, Iterables.transform(blocks, new Function<Block, BatchReport.DuplicationBlock>() {
+ @Override
+ public DuplicationBlock apply(Block input) {
+ builder.clear();
+ builder.setStartLine(input.getStartLine());
+ builder.setEndLine(input.getEndLine());
+ builder.setStartTokenIndex(input.getStartUnit());
+ builder.setEndTokenIndex(input.getEndUnit());
+ for (int i : input.getBlockHash().toIntArray()) {
+ builder.addHash(i);
+ }
+ return builder.build();
+ }
+ }));
+ }
for (Block block : blocks) {
mem.insert(block);
}
}
+ public static boolean isCrossProjectDuplicationEnabled(Settings settings) {
+ return settings.getBoolean(CoreProperties.CPD_CROSS_PROJECT)
+ // No cross project duplication for branches
+ && StringUtils.isBlank(settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY));
+ }
+
public Collection<Block> getByInputFile(InputFile inputFile, String resourceKey) {
return mem.getByResourceId(resourceKey);
}
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 04b5724b2c3..49c7f95736b 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
@@ -41,10 +41,8 @@ import org.sonar.api.batch.fs.TextPointer;
import org.sonar.api.batch.fs.TextRange;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.duplication.Duplication;
import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.issue.Issue;
-import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.issue.IssueCache;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReport.Component;
@@ -63,7 +61,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
private static final Logger LOG = LoggerFactory.getLogger(TaskResult.class);
private List<Issue> issues = 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<>();
@@ -86,7 +83,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
storeFs(container);
- storeDuplication(container);
}
private void storeReportComponents(int componentRef, String parentModuleKey, @Nullable String branch) {
@@ -106,13 +102,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
return reader;
}
- private void storeDuplication(ProjectScanContainer container) {
- DuplicationCache duplicationCache = container.getComponentByType(DuplicationCache.class);
- for (String effectiveKey : duplicationCache.componentKeys()) {
- duplications.put(effectiveKey, Lists.<Duplication>newArrayList(duplicationCache.byComponent(effectiveKey)));
- }
- }
-
private void storeFs(ProjectScanContainer container) {
InputPathCache inputFileCache = container.getComponentByType(InputPathCache.class);
for (InputFile inputPath : inputFileCache.allFiles()) {
@@ -127,6 +116,10 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
return issues;
}
+ public Component getReportComponent(String key) {
+ return reportComponents.get(key);
+ }
+
public List<BatchReport.Issue> issuesFor(InputPath inputPath) {
List<BatchReport.Issue> result = Lists.newArrayList();
int ref = reportComponents.get(key(inputPath)).getRef();
@@ -162,10 +155,6 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
return inputDirs.get(relativePath);
}
- public List<Duplication> duplicationsFor(InputFile inputFile) {
- return duplications.get(((DefaultInputFile) inputFile).key());
- }
-
public Map<String, List<BatchReport.Measure>> allMeasures() {
Map<String, List<BatchReport.Measure>> result = new HashMap<>();
for (Map.Entry<String, Component> component : reportComponents.entrySet()) {
@@ -226,6 +215,32 @@ public class TaskResult implements org.sonar.batch.mediumtest.ScanTaskObserver {
return Collections.emptyList();
}
+ public List<BatchReport.Duplication> duplicationsFor(InputFile file) {
+ List<BatchReport.Duplication> result = new ArrayList<>();
+ int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef();
+ try (CloseableIterator<BatchReport.Duplication> it = getReportReader().readComponentDuplications(ref)) {
+ while (it.hasNext()) {
+ result.add(it.next());
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ return result;
+ }
+
+ public List<BatchReport.DuplicationBlock> duplicationBlocksFor(InputFile file) {
+ List<BatchReport.DuplicationBlock> result = new ArrayList<>();
+ int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef();
+ try (CloseableIterator<BatchReport.DuplicationBlock> it = getReportReader().readComponentDuplicationBlocks(ref)) {
+ while (it.hasNext()) {
+ result.add(it.next());
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ return result;
+ }
+
@CheckForNull
public BatchReport.Coverage coverageFor(InputFile file, int line) {
int ref = reportComponents.get(((DefaultInputFile) file).key()).getRef();
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 6cf132a9f6e..068cb1c10e4 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
@@ -81,7 +81,8 @@ public class DuplicationsPublisher implements ReportPublisherStep {
if (sameProjectComponent != null) {
blockBuilder.setOtherFileRef(sameProjectComponent.batchId());
} else {
- blockBuilder.setOtherFileKey(componentKey);
+ // Should never happens
+ throw new IllegalStateException("No cross project duplication supported on batch side: " + componentKey);
}
}
dupBuilder.addDuplicate(blockBuilder
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java
index 52e98b53d81..9c1d2faca6d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java
@@ -21,7 +21,9 @@ package org.sonar.batch.report;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
+import org.sonar.batch.cpd.index.SonarDuplicationsIndex;
import org.sonar.batch.index.BatchComponent;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.protocol.output.BatchReport;
@@ -32,10 +34,12 @@ public class MetadataPublisher implements ReportPublisherStep {
private final BatchComponentCache componentCache;
private final ImmutableProjectReactor reactor;
+ private final Settings settings;
- public MetadataPublisher(BatchComponentCache componentCache, ImmutableProjectReactor reactor) {
+ public MetadataPublisher(BatchComponentCache componentCache, ImmutableProjectReactor reactor, Settings settings) {
this.componentCache = componentCache;
this.reactor = reactor;
+ this.settings = settings;
}
@Override
@@ -46,6 +50,7 @@ public class MetadataPublisher implements ReportPublisherStep {
.setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
// Here we want key without branch
.setProjectKey(root.getKey())
+ .setCrossProjectDuplicationActivated(SonarDuplicationsIndex.isCrossProjectDuplicationEnabled(settings))
.setRootComponentRef(rootProject.batchId());
String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY);
if (branch != null) {
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 0c6a9d67fa2..bcb38b4958a 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
@@ -95,18 +95,18 @@ public class DefaultSensorStorage implements SensorStorage {
private final ModuleIssues moduleIssues;
private final CoverageExclusions coverageExclusions;
private final DuplicationCache duplicationCache;
- private final BatchComponentCache resourceCache;
+ private final BatchComponentCache componentCache;
private final ReportPublisher reportPublisher;
private final MeasureCache measureCache;
public DefaultSensorStorage(MetricFinder metricFinder, ModuleIssues moduleIssues,
Settings settings, FileSystem fs, ActiveRules activeRules, DuplicationCache duplicationCache,
- CoverageExclusions coverageExclusions, BatchComponentCache resourceCache, ReportPublisher reportPublisher, MeasureCache measureCache) {
+ CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher, MeasureCache measureCache) {
this.metricFinder = metricFinder;
this.moduleIssues = moduleIssues;
this.coverageExclusions = coverageExclusions;
this.duplicationCache = duplicationCache;
- this.resourceCache = resourceCache;
+ this.componentCache = componentCache;
this.reportPublisher = reportPublisher;
this.measureCache = measureCache;
}
@@ -127,7 +127,7 @@ public class DefaultSensorStorage implements SensorStorage {
setValueAccordingToMetricType(newMeasure, m, measureToSave);
measureToSave.setFromCore(measure.isFromCore());
InputComponent inputComponent = newMeasure.inputComponent();
- Resource resource = resourceCache.get(inputComponent).resource();
+ Resource resource = componentCache.get(inputComponent).resource();
if (coverageExclusions.accept(resource, measureToSave)) {
saveMeasure(resource, measureToSave);
}
@@ -183,7 +183,7 @@ public class DefaultSensorStorage implements SensorStorage {
}
private File getFile(InputFile file) {
- BatchComponent r = resourceCache.get(file);
+ BatchComponent r = componentCache.get(file);
if (r == null) {
throw new IllegalStateException("Provided input file is not indexed");
}
@@ -199,13 +199,13 @@ public class DefaultSensorStorage implements SensorStorage {
public void store(DefaultHighlighting highlighting) {
BatchReportWriter writer = reportPublisher.getWriter();
DefaultInputFile inputFile = (DefaultInputFile) highlighting.inputFile();
- writer.writeComponentSyntaxHighlighting(resourceCache.get(inputFile).batchId(),
+ writer.writeComponentSyntaxHighlighting(componentCache.get(inputFile).batchId(),
Iterables.transform(highlighting.getSyntaxHighlightingRuleSet(), new BuildSyntaxHighlighting()));
}
public void store(DefaultInputFile inputFile, Map<Symbol, Set<TextRange>> referencesBySymbol) {
BatchReportWriter writer = reportPublisher.getWriter();
- writer.writeComponentSymbols(resourceCache.get(inputFile).batchId(),
+ writer.writeComponentSymbols(componentCache.get(inputFile).batchId(),
Iterables.transform(referencesBySymbol.entrySet(), new Function<Map.Entry<Symbol, Set<TextRange>>, BatchReport.Symbol>() {
private BatchReport.Symbol.Builder builder = BatchReport.Symbol.newBuilder();
private BatchReport.TextRange.Builder rangeBuilder = BatchReport.TextRange.newBuilder();