aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main/java
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-12-21 13:54:14 +0100
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-12-21 14:37:03 +0100
commitd1e303f8412f61f426a6c746cc2ac10b584940bd (patch)
treeb68693cc8caced2aeee5b06a3590b3e1392e8011 /sonar-batch/src/main/java
parent6fe8b0cd64c4b4e2386d994016b465b0386ed09c (diff)
downloadsonarqube-d1e303f8412f61f426a6c746cc2ac10b584940bd.tar.gz
sonarqube-d1e303f8412f61f426a6c746cc2ac10b584940bd.zip
SONAR-2867 Standard copy-paste detection should happen within a project, not only within a module
Diffstat (limited to 'sonar-batch/src/main/java')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/CpdExecutor.java (renamed from sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java)87
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/CpdIndexer.java (renamed from sonar-batch/src/main/java/org/sonar/batch/cpd/CpdEngine.java)5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/CpdSensor.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdIndexer.java (renamed from sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java)78
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdIndexer.java (renamed from sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java)85
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cpd/index/SonarDuplicationsIndex.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java15
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java6
9 files changed, 127 insertions, 177 deletions
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 ffac2cba012..b920ef1cefa 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
@@ -27,12 +27,12 @@ public final class CpdComponents {
private CpdComponents() {
}
- public static List all() {
+ public static List<Class<? extends Object>> all() {
return ImmutableList.of(
CpdSensor.class,
CpdMappings.class,
- JavaCpdEngine.class,
- DefaultCpdEngine.class);
+ JavaCpdIndexer.class,
+ DefaultCpdIndexer.class);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdExecutor.java
index 8905bf5ac07..302035c3973 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdExecutor.java
@@ -17,45 +17,104 @@
* 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;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
-import java.util.List;
+import com.google.common.base.Predicate;
import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+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;
import org.sonar.batch.protocol.output.BatchReport.Duplicate;
import org.sonar.batch.protocol.output.BatchReport.Duplication;
import org.sonar.batch.report.ReportPublisher;
+import org.sonar.duplications.block.Block;
+import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm;
import org.sonar.duplications.index.CloneGroup;
import org.sonar.duplications.index.ClonePart;
+import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
-import static com.google.common.collect.FluentIterable.from;
-
-public abstract class AbstractCpdEngine extends CpdEngine {
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
- private static final Logger LOG = Loggers.get(AbstractCpdEngine.class);
+import static com.google.common.collect.FluentIterable.from;
+/**
+ * Runs on the root module, at the end of the project analysis.
+ * It executes copy paste detection involving all files of all modules, which were indexed during sensors execution for each module
+ * by {@link CpdSensor). The sensor is responsible for handling exclusions and block sizes.
+ */
+public class CpdExecutor {
+ private static final Logger LOG = Loggers.get(CpdExecutor.class);
static final int MAX_CLONE_GROUP_PER_FILE = 100;
static final int MAX_CLONE_PART_PER_GROUP = 100;
+ private final SonarDuplicationsIndex index;
private final ReportPublisher publisher;
private final BatchComponentCache batchComponentCache;
+ private final Settings settings;
- public AbstractCpdEngine(ReportPublisher publisher, BatchComponentCache batchComponentCache) {
+ public CpdExecutor(Settings settings, SonarDuplicationsIndex index, ReportPublisher publisher, BatchComponentCache batchComponentCache) {
+ this.settings = settings;
+ this.index = index;
this.publisher = publisher;
this.batchComponentCache = batchComponentCache;
}
- protected final void saveDuplications(final InputFile inputFile, List<CloneGroup> duplications) {
+ public void execute() {
+ Iterator<ResourceBlocks> it = index.iterator();
+
+ while (it.hasNext()) {
+ ResourceBlocks resourceBlocks = it.next();
+ runCpdAnalysis(resourceBlocks.resourceId(), resourceBlocks.blocks());
+ }
+ }
+
+ private void runCpdAnalysis(String resource, Collection<Block> fileBlocks) {
+ LOG.debug("Detection of duplications for {}", resource);
+
+ BatchComponent component = batchComponentCache.get(resource);
+ if (component == null) {
+ LOG.error("Resource not found in component cache: {}. Skipping CPD computation for it", resource);
+ return;
+ }
+
+ List<CloneGroup> duplications;
+ try {
+ duplications = SuffixTreeCloneDetectionAlgorithm.detect(index, fileBlocks);
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail during detection of duplication for " + resource, e);
+ }
+
+ InputFile inputFile = (InputFile) component.inputComponent();
+ Predicate<CloneGroup> minimumTokensPredicate = DuplicationPredicates.numberOfUnitsNotLessThan(getMinimumTokens(inputFile.language()));
+ List<CloneGroup> filtered = from(duplications).filter(minimumTokensPredicate).toList();
+
+ saveDuplications(component, filtered);
+ }
+
+ @VisibleForTesting
+ int getMinimumTokens(String languageKey) {
+ int minimumTokens = settings.getInt("sonar.cpd." + languageKey + ".minimumTokens");
+ if (minimumTokens == 0) {
+ minimumTokens = 100;
+ }
+
+ return minimumTokens;
+ }
+
+ @VisibleForTesting
+ final void saveDuplications(final BatchComponent component, List<CloneGroup> duplications) {
if (duplications.size() > MAX_CLONE_GROUP_PER_FILE) {
- LOG.warn("Too many duplication groups on file " + inputFile.relativePath() + ". Keep only the first " + MAX_CLONE_GROUP_PER_FILE + " groups.");
+ LOG.warn("Too many duplication groups on file " + component.inputComponent() + ". Keep only the first " + MAX_CLONE_GROUP_PER_FILE +
+ " groups.");
}
- final BatchComponent component = batchComponentCache.get(inputFile);
Iterable<org.sonar.batch.protocol.output.BatchReport.Duplication> reportDuplications = from(duplications)
.limit(MAX_CLONE_GROUP_PER_FILE)
.transform(
@@ -65,14 +124,14 @@ public abstract class AbstractCpdEngine extends CpdEngine {
@Override
public BatchReport.Duplication apply(CloneGroup input) {
- return toReportDuplication(component, inputFile, dupBuilder, blockBuilder, input);
+ return toReportDuplication(component, dupBuilder, blockBuilder, input);
}
});
publisher.getWriter().writeComponentDuplications(component.batchId(), reportDuplications);
}
- private Duplication toReportDuplication(BatchComponent component, InputFile inputFile, Duplication.Builder dupBuilder, Duplicate.Builder blockBuilder, CloneGroup input) {
+ private Duplication toReportDuplication(BatchComponent component, Duplication.Builder dupBuilder, Duplicate.Builder blockBuilder, CloneGroup input) {
dupBuilder.clear();
ClonePart originBlock = input.getOriginPart();
blockBuilder.clear();
@@ -85,7 +144,8 @@ public abstract class AbstractCpdEngine extends CpdEngine {
if (!duplicate.equals(originBlock)) {
clonePartCount++;
if (clonePartCount > MAX_CLONE_PART_PER_GROUP) {
- LOG.warn("Too many duplication references on file " + inputFile.relativePath() + " for block at line " + originBlock.getStartLine() + ". Keep only the first "
+ LOG.warn("Too many duplication references on file " + component.inputComponent() + " for block at line " +
+ originBlock.getStartLine() + ". Keep only the first "
+ MAX_CLONE_PART_PER_GROUP + " references.");
break;
}
@@ -105,5 +165,4 @@ public abstract class AbstractCpdEngine extends CpdEngine {
}
return dupBuilder.build();
}
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdIndexer.java
index 3b5cfa3b738..6d53f2a4946 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdIndexer.java
@@ -21,14 +21,13 @@ package org.sonar.batch.cpd;
import org.slf4j.Logger;
import org.sonar.api.batch.BatchSide;
-import org.sonar.api.batch.sensor.SensorContext;
@BatchSide
-public abstract class CpdEngine {
+public abstract class CpdIndexer {
abstract boolean isLanguageSupported(String language);
- abstract void analyse(String language, SensorContext context);
+ abstract void index(String language);
protected void logExclusions(String[] exclusions, Logger logger) {
if (exclusions.length > 0) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdSensor.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdSensor.java
index ed41921c9eb..63ee56ac819 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/CpdSensor.java
@@ -35,12 +35,12 @@ public class CpdSensor implements Sensor {
private static final Logger LOG = LoggerFactory.getLogger(CpdSensor.class);
- private CpdEngine sonarEngine;
- private CpdEngine sonarBridgeEngine;
+ private CpdIndexer sonarEngine;
+ private CpdIndexer sonarBridgeEngine;
private Settings settings;
private FileSystem fs;
- public CpdSensor(JavaCpdEngine sonarEngine, DefaultCpdEngine sonarBridgeEngine, Settings settings, FileSystem fs) {
+ public CpdSensor(JavaCpdIndexer sonarEngine, DefaultCpdIndexer sonarBridgeEngine, Settings settings, FileSystem fs) {
this.sonarEngine = sonarEngine;
this.sonarBridgeEngine = sonarBridgeEngine;
this.settings = settings;
@@ -54,7 +54,7 @@ public class CpdSensor implements Sensor {
}
@VisibleForTesting
- CpdEngine getEngine(String language) {
+ CpdIndexer getEngine(String language) {
if (sonarEngine.isLanguageSupported(language)) {
return sonarEngine;
}
@@ -87,13 +87,13 @@ public class CpdSensor implements Sensor {
continue;
}
- CpdEngine engine = getEngine(language);
+ CpdIndexer engine = getEngine(language);
if (!engine.isLanguageSupported(language)) {
LOG.debug("Detection of duplicated code is not supported for {}", language);
continue;
}
LOG.info("{} is used for {}", engine, language);
- engine.analyse(language, context);
+ engine.index(language);
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdIndexer.java
index 2eb64fcc73d..bbc07472f95 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/DefaultCpdIndexer.java
@@ -20,16 +20,8 @@
package org.sonar.batch.cpd;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
-import java.util.Collection;
-import java.util.Collections;
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;
@@ -38,39 +30,25 @@ import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
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.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 static com.google.common.collect.FluentIterable.from;
+public class DefaultCpdIndexer extends CpdIndexer {
-public class DefaultCpdEngine extends AbstractCpdEngine {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultCpdEngine.class);
-
- /**
- * Limit of time to analyse one file (in seconds).
- */
- private static final int TIMEOUT = 5 * 60;
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultCpdIndexer.class);
private final CpdMappings mappings;
private final FileSystem fs;
private final Settings settings;
- private final ReportPublisher publisher;
- private final BatchComponentCache batchComponentCache;
+ private final SonarDuplicationsIndex index;
- public DefaultCpdEngine(CpdMappings mappings, FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) {
- super(publisher, batchComponentCache);
+ public DefaultCpdIndexer(CpdMappings mappings, FileSystem fs, Settings settings, SonarDuplicationsIndex index) {
this.mappings = mappings;
this.fs = fs;
this.settings = settings;
- this.publisher = publisher;
- this.batchComponentCache = batchComponentCache;
+ this.index = index;
}
@Override
@@ -79,7 +57,7 @@ public class DefaultCpdEngine extends AbstractCpdEngine {
}
@Override
- public void analyse(String languageKey, SensorContext context) {
+ public void index(String languageKey) {
CpdMapping mapping = mappings.getMapping(languageKey);
if (mapping == null) {
LOG.debug("No CpdMapping for language " + languageKey);
@@ -98,41 +76,7 @@ public class DefaultCpdEngine extends AbstractCpdEngine {
}
// Create index
- SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings);
populateIndex(languageKey, sourceFiles, mapping, index);
-
- // Detect
- runCpdAnalysis(languageKey, context, sourceFiles, index);
- }
-
- private void runCpdAnalysis(String languageKey, SensorContext context, List<InputFile> sourceFiles, SonarDuplicationsIndex index) {
- Predicate<CloneGroup> minimumTokensPredicate = DuplicationPredicates.numberOfUnitsNotLessThan(getMinimumTokens(languageKey));
-
- ExecutorService executorService = Executors.newSingleThreadExecutor();
- try {
- for (InputFile inputFile : sourceFiles) {
- LOG.debug("Detection of duplications for {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
- Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
-
- List<CloneGroup> filtered;
- try {
- List<CloneGroup> duplications = executorService.submit(new JavaCpdEngine.Task(index, fileBlocks)).get(TIMEOUT, TimeUnit.SECONDS);
- filtered = from(duplications)
- .filter(minimumTokensPredicate)
- .toList();
- } catch (TimeoutException e) {
- filtered = Collections.emptyList();
- LOG.warn("Timeout during detection of duplications for " + inputFile, e);
- } catch (InterruptedException | ExecutionException e) {
- throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e);
- }
-
- saveDuplications(inputFile, filtered);
- }
- } finally {
- executorService.shutdown();
- }
}
private void populateIndex(String languageKey, List<InputFile> sourceFiles, CpdMapping mapping, SonarDuplicationsIndex index) {
@@ -165,14 +109,4 @@ public class DefaultCpdEngine extends AbstractCpdEngine {
}
}
- @VisibleForTesting
- int getMinimumTokens(String languageKey) {
- int minimumTokens = settings.getInt("sonar.cpd." + languageKey + ".minimumTokens");
- if (minimumTokens == 0) {
- minimumTokens = 100;
- }
-
- return minimumTokens;
- }
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdIndexer.java
index d83e049a45a..42fdf42e000 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdEngine.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/JavaCpdIndexer.java
@@ -25,15 +25,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
-import java.util.Collection;
-import java.util.Collections;
import java.util.List;
-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 org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -42,44 +34,30 @@ import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
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.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;
-import org.sonar.duplications.index.CloneGroup;
-import org.sonar.duplications.index.CloneIndex;
import org.sonar.duplications.java.JavaStatementBuilder;
import org.sonar.duplications.java.JavaTokenProducer;
import org.sonar.duplications.statement.Statement;
import org.sonar.duplications.statement.StatementChunker;
import org.sonar.duplications.token.TokenChunker;
-public class JavaCpdEngine extends AbstractCpdEngine {
+public class JavaCpdIndexer extends CpdIndexer {
- private static final Logger LOG = LoggerFactory.getLogger(JavaCpdEngine.class);
+ private static final Logger LOG = LoggerFactory.getLogger(JavaCpdIndexer.class);
private static final int BLOCK_SIZE = 10;
- /**
- * Limit of time to analyse one file (in seconds).
- */
- private static final int TIMEOUT = 5 * 60;
-
private final FileSystem fs;
private final Settings settings;
- private final ReportPublisher publisher;
- private final BatchComponentCache batchComponentCache;
+ private final SonarDuplicationsIndex index;
- public JavaCpdEngine(FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) {
- super(publisher, batchComponentCache);
+ public JavaCpdIndexer(FileSystem fs, Settings settings, SonarDuplicationsIndex index) {
this.fs = fs;
this.settings = settings;
- this.publisher = publisher;
- this.batchComponentCache = batchComponentCache;
+ this.index = index;
}
@Override
@@ -88,7 +66,7 @@ public class JavaCpdEngine extends AbstractCpdEngine {
}
@Override
- public void analyse(String languageKey, SensorContext context) {
+ public void index(String languageKey) {
String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS);
logExclusions(cpdExclusions, LOG);
FilePredicates p = fs.predicates();
@@ -99,13 +77,10 @@ public class JavaCpdEngine extends AbstractCpdEngine {
if (sourceFiles.isEmpty()) {
return;
}
- SonarDuplicationsIndex index = createIndex(sourceFiles);
- detect(index, context, sourceFiles);
+ createIndex(sourceFiles);
}
- private SonarDuplicationsIndex createIndex(Iterable<InputFile> sourceFiles) {
- final SonarDuplicationsIndex index = new SonarDuplicationsIndex(publisher, batchComponentCache, settings);
-
+ private void createIndex(Iterable<InputFile> sourceFiles) {
TokenChunker tokenChunker = JavaTokenProducer.build();
StatementChunker statementChunker = JavaStatementBuilder.build();
BlockChunker blockChunker = new BlockChunker(BLOCK_SIZE);
@@ -129,49 +104,5 @@ public class JavaCpdEngine extends AbstractCpdEngine {
List<Block> blocks = blockChunker.chunk(resourceEffectiveKey, statements);
index.insert(inputFile, blocks);
}
-
- return index;
}
-
- private void detect(SonarDuplicationsIndex index, org.sonar.api.batch.sensor.SensorContext context, List<InputFile> sourceFiles) {
- ExecutorService executorService = Executors.newSingleThreadExecutor();
- try {
- for (InputFile inputFile : sourceFiles) {
- LOG.debug("Detection of duplications for {}", inputFile);
- String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
-
- Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
-
- List<CloneGroup> clones;
- try {
- clones = executorService.submit(new Task(index, fileBlocks)).get(TIMEOUT, TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- clones = Collections.emptyList();
- LOG.warn("Timeout during detection of duplications for " + inputFile, e);
- } catch (InterruptedException | ExecutionException e) {
- throw new IllegalStateException("Fail during detection of duplication for " + inputFile, e);
- }
-
- saveDuplications(inputFile, clones);
- }
- } finally {
- executorService.shutdown();
- }
- }
-
- static class Task implements Callable<List<CloneGroup>> {
- private final CloneIndex index;
- private final Collection<Block> fileBlocks;
-
- public Task(CloneIndex index, Collection<Block> fileBlocks) {
- this.index = index;
- this.fileBlocks = fileBlocks;
- }
-
- @Override
- public List<CloneGroup> call() {
- return SuffixTreeCloneDetectionAlgorithm.detect(index, fileBlocks);
- }
- }
-
}
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 f5872efdd50..1d55b45f008 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
@@ -22,6 +22,8 @@ package org.sonar.batch.cpd.index;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import java.util.Collection;
+import java.util.Iterator;
+
import org.apache.commons.lang.StringUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.fs.InputFile;
@@ -34,6 +36,7 @@ import org.sonar.duplications.block.ByteArray;
import org.sonar.duplications.index.AbstractCloneIndex;
import org.sonar.duplications.index.CloneIndex;
import org.sonar.duplications.index.PackedMemoryCloneIndex;
+import org.sonar.duplications.index.PackedMemoryCloneIndex.ResourceBlocks;
public class SonarDuplicationsIndex extends AbstractCloneIndex {
@@ -76,7 +79,7 @@ public class SonarDuplicationsIndex extends AbstractCloneIndex {
&& StringUtils.isBlank(settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY));
}
- public Collection<Block> getByInputFile(InputFile inputFile, String resourceKey) {
+ public Collection<Block> getByInputFile(String resourceKey) {
return mem.getByResourceId(resourceKey);
}
@@ -95,4 +98,9 @@ public class SonarDuplicationsIndex extends AbstractCloneIndex {
throw new UnsupportedOperationException();
}
+ @Override
+ public Iterator<ResourceBlocks> iterator() {
+ return mem.iterator();
+ }
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
index 3919f4d15af..8e2b7c36693 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java
@@ -22,6 +22,7 @@ package org.sonar.batch.phases;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.cpd.CpdExecutor;
import org.sonar.batch.events.BatchStepEvent;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.DefaultIndex;
@@ -52,12 +53,14 @@ public final class PhaseExecutor {
private final DefaultAnalysisMode analysisMode;
private final IssueTransition localIssueTracking;
private final IssueCallback issueCallback;
+ private final CpdExecutor cpdExecutor;
public PhaseExecutor(InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor,
SensorContext sensorContext, DefaultIndex index,
EventBus eventBus, ReportPublisher reportPublisher, ProjectInitializer pi,
FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier,
- IssueExclusionsLoader issueExclusionsLoader, DefaultAnalysisMode analysisMode, IssueTransition localIssueTracking, IssueCallback issueCallback) {
+ IssueExclusionsLoader issueExclusionsLoader, DefaultAnalysisMode analysisMode, IssueTransition localIssueTracking, IssueCallback issueCallback,
+ CpdExecutor cpdExecutor) {
this.postJobsExecutor = postJobsExecutor;
this.initializersExecutor = initializersExecutor;
this.sensorsExecutor = sensorsExecutor;
@@ -74,6 +77,7 @@ public final class PhaseExecutor {
this.analysisMode = analysisMode;
this.localIssueTracking = localIssueTracking;
this.issueCallback = issueCallback;
+ this.cpdExecutor = cpdExecutor;
}
/**
@@ -101,6 +105,8 @@ public final class PhaseExecutor {
if (analysisMode.isIssues()) {
localIssueTracking();
issuesCallback();
+ } else {
+ computeDuplications();
}
issuesReport();
publishReportJob();
@@ -110,6 +116,13 @@ public final class PhaseExecutor {
eventBus.fireEvent(new ProjectAnalysisEvent(module, false));
}
+ private void computeDuplications() {
+ String stepName = "Computing duplications";
+ eventBus.fireEvent(new BatchStepEvent(stepName, true));
+ cpdExecutor.execute();
+ eventBus.fireEvent(new BatchStepEvent(stepName, false));
+ }
+
private void publishReportJob() {
String stepName = "Publish report";
eventBus.fireEvent(new BatchStepEvent(stepName, true));
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 427f5c3fb7d..767f419920d 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
@@ -41,6 +41,8 @@ import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
import org.sonar.batch.bootstrap.MetricProvider;
import org.sonar.batch.cache.ProjectPersistentCacheProvider;
+import org.sonar.batch.cpd.CpdExecutor;
+import org.sonar.batch.cpd.index.SonarDuplicationsIndex;
import org.sonar.batch.events.EventBus;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.index.Caches;
@@ -203,6 +205,10 @@ public class ProjectScanContainer extends ComponentContainer {
CoveragePublisher.class,
SourcePublisher.class,
TestExecutionAndCoveragePublisher.class,
+
+ // Cpd
+ CpdExecutor.class,
+ SonarDuplicationsIndex.class,
ScanTaskObservers.class,
UserRepositoryLoader.class);