From: Julien HENRY Date: Tue, 1 Dec 2015 10:26:45 +0000 (+0100) Subject: SONAR-6933 Drop newDuplication() beta API X-Git-Tag: 5.3-RC1~113 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a70899910e2448abda0ec8c76aff2000318dce49;p=sonarqube.git SONAR-6933 Drop newDuplication() beta API --- diff --git a/sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java b/sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java new file mode 100644 index 00000000000..8905bf5ac07 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/cpd/AbstractCpdEngine.java @@ -0,0 +1,109 @@ +/* + * 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; + +import com.google.common.base.Function; +import java.util.List; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +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.index.CloneGroup; +import org.sonar.duplications.index.ClonePart; + +import static com.google.common.collect.FluentIterable.from; + +public abstract class AbstractCpdEngine extends CpdEngine { + + private static final Logger LOG = Loggers.get(AbstractCpdEngine.class); + + static final int MAX_CLONE_GROUP_PER_FILE = 100; + static final int MAX_CLONE_PART_PER_GROUP = 100; + + private final ReportPublisher publisher; + private final BatchComponentCache batchComponentCache; + + public AbstractCpdEngine(ReportPublisher publisher, BatchComponentCache batchComponentCache) { + this.publisher = publisher; + this.batchComponentCache = batchComponentCache; + } + + protected final void saveDuplications(final InputFile inputFile, List 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."); + } + final BatchComponent component = batchComponentCache.get(inputFile); + Iterable reportDuplications = from(duplications) + .limit(MAX_CLONE_GROUP_PER_FILE) + .transform( + new Function() { + private final BatchReport.Duplication.Builder dupBuilder = BatchReport.Duplication.newBuilder(); + private final BatchReport.Duplicate.Builder blockBuilder = BatchReport.Duplicate.newBuilder(); + + @Override + public BatchReport.Duplication apply(CloneGroup input) { + return toReportDuplication(component, inputFile, dupBuilder, blockBuilder, input); + } + + }); + publisher.getWriter().writeComponentDuplications(component.batchId(), reportDuplications); + } + + private Duplication toReportDuplication(BatchComponent component, InputFile inputFile, Duplication.Builder dupBuilder, Duplicate.Builder blockBuilder, CloneGroup input) { + dupBuilder.clear(); + ClonePart originBlock = input.getOriginPart(); + blockBuilder.clear(); + dupBuilder.setOriginPosition(BatchReport.TextRange.newBuilder() + .setStartLine(originBlock.getStartLine()) + .setEndLine(originBlock.getEndLine()) + .build()); + int clonePartCount = 0; + for (ClonePart duplicate : input.getCloneParts()) { + 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 " + + MAX_CLONE_PART_PER_GROUP + " references."); + break; + } + blockBuilder.clear(); + String componentKey = duplicate.getResourceId(); + if (!component.key().equals(componentKey)) { + BatchComponent sameProjectComponent = batchComponentCache.get(componentKey); + blockBuilder.setOtherFileRef(sameProjectComponent.batchId()); + } + dupBuilder.addDuplicate(blockBuilder + .setRange(BatchReport.TextRange.newBuilder() + .setStartLine(duplicate.getStartLine()) + .setEndLine(duplicate.getEndLine()) + .build()) + .build()); + } + } + return dupBuilder.build(); + } + +} 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 a63b04f0006..2eb64fcc73d 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 @@ -21,9 +21,9 @@ package org.sonar.batch.cpd; 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.Collections; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -47,7 +47,9 @@ import org.sonar.duplications.block.Block; import org.sonar.duplications.index.CloneGroup; import org.sonar.duplications.internal.pmd.TokenizerBridge; -public class DefaultCpdEngine extends CpdEngine { +import static com.google.common.collect.FluentIterable.from; + +public class DefaultCpdEngine extends AbstractCpdEngine { private static final Logger LOG = LoggerFactory.getLogger(DefaultCpdEngine.class); @@ -63,6 +65,7 @@ public class DefaultCpdEngine extends CpdEngine { private final BatchComponentCache batchComponentCache; public DefaultCpdEngine(CpdMappings mappings, FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) { + super(publisher, batchComponentCache); this.mappings = mappings; this.fs = fs; this.settings = settings; @@ -112,18 +115,20 @@ public class DefaultCpdEngine extends CpdEngine { String resourceEffectiveKey = ((DefaultInputFile) inputFile).key(); Collection fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey); - Iterable filtered; + List filtered; try { List duplications = executorService.submit(new JavaCpdEngine.Task(index, fileBlocks)).get(TIMEOUT, TimeUnit.SECONDS); - filtered = Iterables.filter(duplications, minimumTokensPredicate); + filtered = from(duplications) + .filter(minimumTokensPredicate) + .toList(); } catch (TimeoutException e) { - filtered = null; + 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); } - JavaCpdEngine.save(context, inputFile, filtered); + saveDuplications(inputFile, filtered); } } finally { executorService.shutdown(); 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 21bec46e794..d83e049a45a 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 @@ -20,13 +20,13 @@ 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.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -34,7 +34,6 @@ 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; @@ -44,8 +43,6 @@ 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.batch.sensor.duplication.NewDuplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; import org.sonar.api.config.Settings; import org.sonar.batch.cpd.index.SonarDuplicationsIndex; import org.sonar.batch.index.BatchComponentCache; @@ -55,14 +52,13 @@ 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.index.ClonePart; 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 CpdEngine { +public class JavaCpdEngine extends AbstractCpdEngine { private static final Logger LOG = LoggerFactory.getLogger(JavaCpdEngine.class); @@ -73,15 +69,13 @@ public class JavaCpdEngine extends CpdEngine { */ private static final int TIMEOUT = 5 * 60; - private static final int MAX_CLONE_GROUP_PER_FILE = 100; - private static final int MAX_CLONE_PART_PER_GROUP = 100; - private final FileSystem fs; private final Settings settings; private final ReportPublisher publisher; private final BatchComponentCache batchComponentCache; public JavaCpdEngine(FileSystem fs, Settings settings, ReportPublisher publisher, BatchComponentCache batchComponentCache) { + super(publisher, batchComponentCache); this.fs = fs; this.settings = settings; this.publisher = publisher; @@ -152,13 +146,13 @@ public class JavaCpdEngine extends CpdEngine { try { clones = executorService.submit(new Task(index, fileBlocks)).get(TIMEOUT, TimeUnit.SECONDS); } catch (TimeoutException e) { - clones = null; + 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); } - save(context, inputFile, clones); + saveDuplications(inputFile, clones); } } finally { executorService.shutdown(); @@ -180,39 +174,4 @@ public class JavaCpdEngine extends CpdEngine { } } - static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable duplications) { - if (duplications == null || Iterables.isEmpty(duplications)) { - return; - } - - saveDuplications(context, inputFile, duplications); - } - - private static void saveDuplications(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, Iterable duplications) { - int cloneGroupCount = 0; - for (CloneGroup duplication : duplications) { - cloneGroupCount++; - if (cloneGroupCount > 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."); - break; - } - NewDuplication builder = context.newDuplication(); - ClonePart originPart = duplication.getOriginPart(); - builder.originBlock(inputFile, originPart.getStartLine(), originPart.getEndLine()); - int clonePartCount = 0; - for (ClonePart part : duplication.getCloneParts()) { - if (!part.equals(originPart)) { - clonePartCount++; - if (clonePartCount > MAX_CLONE_PART_PER_GROUP) { - LOG.warn("Too many duplication references on file " + inputFile.relativePath() + " for block at line " + originPart.getStartLine() + ". Keep only the first " - + MAX_CLONE_PART_PER_GROUP + " references."); - break; - } - ((DefaultDuplication) builder).isDuplicatedBy(part.getResourceId(), part.getStartLine(), part.getEndLine()); - } - } - builder.save(); - } - } - } diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationValueCoder.java deleted file mode 100644 index 1ab206e8edf..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationValueCoder.java +++ /dev/null @@ -1,53 +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.duplication; - -import com.persistit.Value; -import com.persistit.encoding.CoderContext; -import com.persistit.encoding.ValueCoder; -import org.sonar.api.batch.sensor.duplication.Duplication; -import org.sonar.api.batch.sensor.duplication.Duplication.Block; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; - -class DefaultDuplicationValueCoder implements ValueCoder { - - private DuplicationBlockValueCoder blockCoder = new DuplicationBlockValueCoder(); - - @Override - public void put(Value value, Object object, CoderContext context) { - DefaultDuplication c = (DefaultDuplication) object; - blockCoder.put(value, c.originBlock(), context); - value.put(c.duplicates().size()); - for (Duplication.Block block : c.duplicates()) { - blockCoder.put(value, block, context); - } - } - - @Override - public Object get(Value value, Class clazz, CoderContext context) { - DefaultDuplication g = new DefaultDuplication(); - g.setOriginBlock((Block) blockCoder.get(value, Duplication.Block.class, context)); - int count = value.getInt(); - for (int i = 0; i < count; i++) { - g.duplicates().add((Block) blockCoder.get(value, Duplication.Block.class, context)); - } - return g; - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java deleted file mode 100644 index 50dbd316bb7..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java +++ /dev/null @@ -1,44 +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.duplication; - -import com.persistit.Value; -import com.persistit.encoding.CoderContext; -import com.persistit.encoding.ValueCoder; -import org.sonar.api.batch.sensor.duplication.Duplication; - -class DuplicationBlockValueCoder implements ValueCoder { - - @Override - public void put(Value value, Object object, CoderContext context) { - Duplication.Block b = (Duplication.Block) object; - value.putUTF(b.resourceKey()); - value.put(b.startLine()); - value.put(b.length()); - } - - @Override - public Object get(Value value, Class clazz, CoderContext context) { - String resourceKey = value.getString(); - int startLine = value.getInt(); - int length = value.getInt(); - return new Duplication.Block(resourceKey, startLine, length); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java deleted file mode 100644 index cfc091d00cb..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java +++ /dev/null @@ -1,62 +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.duplication; - -import com.google.common.base.Function; -import com.google.common.collect.Iterables; -import org.sonar.api.batch.BatchSide; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import org.sonar.batch.index.Cache; -import org.sonar.batch.index.Caches; - -/** - * Cache of duplication blocks. This cache is shared amongst all project modules. - */ -@BatchSide -public class DuplicationCache { - - private final Cache cache; - private int sequence = 1; - - public DuplicationCache(Caches caches) { - caches.registerValueCoder(DefaultDuplication.class, new DefaultDuplicationValueCoder()); - cache = caches.createCache("duplications"); - } - - public Iterable componentKeys() { - return Iterables.transform(cache.keySet(), new Function() { - @Override - public String apply(Object input) { - return input.toString(); - } - }); - } - - public Iterable byComponent(String effectiveKey) { - return cache.values(effectiveKey); - } - - public DuplicationCache put(String effectiveKey, DefaultDuplication duplication) { - cache.put(effectiveKey, sequence, duplication); - sequence++; - return this; - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java deleted file mode 100644 index 103e90ab281..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java +++ /dev/null @@ -1,23 +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. - */ -@ParametersAreNonnullByDefault -package org.sonar.batch.duplication; - -import javax.annotation.ParametersAreNonnullByDefault; 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 deleted file mode 100644 index 068cb1c10e4..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/report/DuplicationsPublisher.java +++ /dev/null @@ -1,98 +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.google.common.base.Function; -import com.google.common.collect.Iterables; -import org.sonar.api.batch.sensor.duplication.Duplication.Block; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import org.sonar.batch.duplication.DuplicationCache; -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.protocol.output.BatchReportWriter; - -public class DuplicationsPublisher implements ReportPublisherStep { - - private final BatchComponentCache resourceCache; - private final DuplicationCache duplicationCache; - - public DuplicationsPublisher(BatchComponentCache resourceCache, DuplicationCache duplicationCache) { - this.resourceCache = resourceCache; - this.duplicationCache = duplicationCache; - } - - @Override - public void publish(BatchReportWriter writer) { - for (final BatchComponent resource : resourceCache.all()) { - if (!resource.isFile()) { - continue; - } - Iterable dups = duplicationCache.byComponent(resource.resource().getEffectiveKey()); - if (dups.iterator().hasNext()) { - Iterable reportDuplications = Iterables.transform(dups, - new Function() { - private final BatchReport.Duplication.Builder dupBuilder = BatchReport.Duplication.newBuilder(); - private final BatchReport.Duplicate.Builder blockBuilder = BatchReport.Duplicate.newBuilder(); - - @Override - public BatchReport.Duplication apply(DefaultDuplication input) { - return toReportDuplication(resource.key(), dupBuilder, blockBuilder, input); - } - - }); - writer.writeComponentDuplications(resource.batchId(), reportDuplications); - } - } - } - - private Duplication toReportDuplication(String currentComponentKey, Duplication.Builder dupBuilder, Duplicate.Builder blockBuilder, DefaultDuplication input) { - dupBuilder.clear(); - Block originBlock = input.originBlock(); - blockBuilder.clear(); - dupBuilder.setOriginPosition(BatchReport.TextRange.newBuilder() - .setStartLine(originBlock.startLine()) - .setEndLine(originBlock.startLine() + originBlock.length() - 1) - .build()); - for (Block duplicate : input.duplicates()) { - blockBuilder.clear(); - String componentKey = duplicate.resourceKey(); - if (!currentComponentKey.equals(componentKey)) { - BatchComponent sameProjectComponent = resourceCache.get(componentKey); - if (sameProjectComponent != null) { - blockBuilder.setOtherFileRef(sameProjectComponent.batchId()); - } else { - // Should never happens - throw new IllegalStateException("No cross project duplication supported on batch side: " + componentKey); - } - } - dupBuilder.addDuplicate(blockBuilder - .setRange(BatchReport.TextRange.newBuilder() - .setStartLine(duplicate.startLine()) - .setEndLine(duplicate.startLine() + duplicate.length() - 1) - .build()) - .build()); - } - return dupBuilder.build(); - } - -} 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 b694beb38cf..7c5e87050f9 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,7 +41,6 @@ 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.duplication.DuplicationCache; import org.sonar.batch.events.EventBus; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.index.Caches; @@ -61,7 +60,6 @@ import org.sonar.batch.report.ActiveRulesPublisher; import org.sonar.batch.report.AnalysisContextReportPublisher; import org.sonar.batch.report.ComponentsPublisher; import org.sonar.batch.report.CoveragePublisher; -import org.sonar.batch.report.DuplicationsPublisher; import org.sonar.batch.report.MeasuresPublisher; import org.sonar.batch.report.MetadataPublisher; import org.sonar.batch.report.ReportPublisher; @@ -179,9 +177,6 @@ public class ProjectScanContainer extends ComponentContainer { // Measures MeasureCache.class, - // Duplications - DuplicationCache.class, - ProjectSettings.class, // Report @@ -191,7 +186,6 @@ public class ProjectScanContainer extends ComponentContainer { ActiveRulesPublisher.class, ComponentsPublisher.class, MeasuresPublisher.class, - DuplicationsPublisher.class, CoveragePublisher.class, SourcePublisher.class, TestExecutionAndCoveragePublisher.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java index cb58332f96c..f6d30a2ae02 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorContext.java @@ -27,8 +27,6 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; -import org.sonar.api.batch.sensor.duplication.NewDuplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; @@ -114,11 +112,6 @@ public class DefaultSensorContext implements SensorContext { return new DefaultHighlighting(sensorStorage); } - @Override - public NewDuplication newDuplication() { - return new DefaultDuplication(sensorStorage); - } - @Override public NewCoverage newCoverage() { return new DefaultCoverage(sensorStorage); 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 bcb38b4958a..1c25a98091b 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 @@ -37,8 +37,6 @@ import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.coverage.CoverageType; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; -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; @@ -53,7 +51,6 @@ import org.sonar.api.resources.Resource; import org.sonar.api.source.Symbol; import org.sonar.api.utils.KeyValueFormat; import org.sonar.api.utils.SonarException; -import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.issue.ModuleIssues; @@ -94,18 +91,16 @@ public class DefaultSensorStorage implements SensorStorage { private final MetricFinder metricFinder; private final ModuleIssues moduleIssues; private final CoverageExclusions coverageExclusions; - private final DuplicationCache duplicationCache; 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, + Settings settings, FileSystem fs, ActiveRules activeRules, CoverageExclusions coverageExclusions, BatchComponentCache componentCache, ReportPublisher reportPublisher, MeasureCache measureCache) { this.metricFinder = metricFinder; this.moduleIssues = moduleIssues; this.coverageExclusions = coverageExclusions; - this.duplicationCache = duplicationCache; this.componentCache = componentCache; this.reportPublisher = reportPublisher; this.measureCache = measureCache; @@ -190,11 +185,6 @@ public class DefaultSensorStorage implements SensorStorage { return (File) r.resource(); } - @Override - public void store(Duplication duplication) { - duplicationCache.put(duplication.originBlock().resourceKey(), (DefaultDuplication) duplication); - } - @Override public void store(DefaultHighlighting highlighting) { BatchReportWriter writer = reportPublisher.getWriter(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/AbstractCpdEngineTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/AbstractCpdEngineTest.java new file mode 100644 index 00000000000..1f843d8e284 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/cpd/AbstractCpdEngineTest.java @@ -0,0 +1,227 @@ +/* + * 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; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Before; +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.DefaultInputModule; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.resources.Project; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; +import org.sonar.batch.index.BatchComponent; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport.Duplication; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.batch.report.ReportPublisher; +import org.sonar.core.util.CloseableIterator; +import org.sonar.duplications.index.CloneGroup; +import org.sonar.duplications.index.ClonePart; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AbstractCpdEngineTest { + + @Rule + public LogTester logTester = new LogTester(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private AbstractCpdEngine engine; + + private BatchReportReader reader; + private DefaultInputFile inputFile1; + private BatchComponent batchComponent1; + private BatchComponent batchComponent2; + private BatchComponent batchComponent3; + + @Before + public void before() throws IOException { + File outputDir = temp.newFolder(); + ReportPublisher reportPublisher = mock(ReportPublisher.class); + when(reportPublisher.getWriter()).thenReturn(new BatchReportWriter(outputDir)); + reader = new BatchReportReader(outputDir); + BatchComponentCache componentCache = new BatchComponentCache(); + Project p = new Project("foo"); + componentCache.add(p, null).setInputComponent(new DefaultInputModule("foo")); + org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); + inputFile1 = new DefaultInputFile("foo", "src/Foo.php").setLines(5); + batchComponent1 = componentCache.add(sampleFile, null).setInputComponent(inputFile1); + org.sonar.api.resources.Resource sampleFile2 = org.sonar.api.resources.File.create("src/Foo2.php").setEffectiveKey("foo:src/Foo2.php"); + batchComponent2 = componentCache.add(sampleFile2, null).setInputComponent(new DefaultInputFile("foo", "src/Foo2.php").setLines(5)); + org.sonar.api.resources.Resource sampleFile3 = org.sonar.api.resources.File.create("src/Foo3.php").setEffectiveKey("foo:src/Foo3.php"); + batchComponent3 = componentCache.add(sampleFile3, null).setInputComponent(new DefaultInputFile("foo", "src/Foo3.php").setLines(5)); + engine = new AbstractCpdEngine(reportPublisher, componentCache) { + + @Override + boolean isLanguageSupported(String language) { + return false; + } + + @Override + void analyse(String language, SensorContext context) { + } + }; + } + + @Test + public void testNothingToSave() { + engine.saveDuplications(inputFile1, Collections.EMPTY_LIST); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(0); + } + + @Test + public void testOneSimpleDuplicationBetweenTwoFiles() { + List groups = Arrays.asList(newCloneGroup(new ClonePart(batchComponent1.key(), 0, 2, 4), new ClonePart(batchComponent2.key(), 0, 15, 17))); + engine.saveDuplications(inputFile1, groups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(1); + CloseableIterator dups = reader.readComponentDuplications(batchComponent1.batchId()); + Duplication duplication = dups.next(); + dups.close(); + assertThat(duplication.getOriginPosition().getStartLine()).isEqualTo(2); + assertThat(duplication.getOriginPosition().getEndLine()).isEqualTo(4); + assertThat(duplication.getDuplicateList()).hasSize(1); + assertThat(duplication.getDuplicate(0).getOtherFileRef()).isEqualTo(batchComponent2.batchId()); + assertThat(duplication.getDuplicate(0).getRange().getStartLine()).isEqualTo(15); + assertThat(duplication.getDuplicate(0).getRange().getEndLine()).isEqualTo(17); + } + + @Test + public void testDuplicationOnSameFile() throws Exception { + List groups = Arrays.asList(newCloneGroup(new ClonePart(batchComponent1.key(), 0, 5, 204), new ClonePart(batchComponent1.key(), 0, 215, 414))); + engine.saveDuplications(inputFile1, groups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(1); + CloseableIterator dups = reader.readComponentDuplications(batchComponent1.batchId()); + Duplication duplication = dups.next(); + dups.close(); + assertThat(duplication.getOriginPosition().getStartLine()).isEqualTo(5); + assertThat(duplication.getOriginPosition().getEndLine()).isEqualTo(204); + assertThat(duplication.getDuplicateList()).hasSize(1); + assertThat(duplication.getDuplicate(0).hasOtherFileRef()).isFalse(); + assertThat(duplication.getDuplicate(0).getRange().getStartLine()).isEqualTo(215); + assertThat(duplication.getDuplicate(0).getRange().getEndLine()).isEqualTo(414); + } + + @Test + public void testTooManyDuplicates() throws Exception { + // 1 origin part + 101 duplicates = 102 + List parts = new ArrayList<>(AbstractCpdEngine.MAX_CLONE_PART_PER_GROUP + 2); + for (int i = 0; i < AbstractCpdEngine.MAX_CLONE_PART_PER_GROUP + 2; i++) { + parts.add(new ClonePart(batchComponent1.key(), i, i, i + 1)); + } + List groups = Arrays.asList(CloneGroup.builder().setLength(0).setOrigin(parts.get(0)).setParts(parts).build()); + engine.saveDuplications(inputFile1, groups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(1); + CloseableIterator dups = reader.readComponentDuplications(batchComponent1.batchId()); + Duplication duplication = dups.next(); + dups.close(); + assertThat(duplication.getDuplicateList()).hasSize(AbstractCpdEngine.MAX_CLONE_PART_PER_GROUP); + + assertThat(logTester.logs(LoggerLevel.WARN)).contains("Too many duplication references on file " + inputFile1.relativePath() + " for block at line 0. Keep only the first " + + AbstractCpdEngine.MAX_CLONE_PART_PER_GROUP + " references."); + } + + @Test + public void testTooManyDuplications() throws Exception { + // 1 origin part + 101 duplicates = 102 + List dups = new ArrayList<>(AbstractCpdEngine.MAX_CLONE_GROUP_PER_FILE + 1); + for (int i = 0; i < AbstractCpdEngine.MAX_CLONE_GROUP_PER_FILE + 1; i++) { + ClonePart clonePart = new ClonePart(batchComponent1.key(), i, i, i + 1); + ClonePart dupPart = new ClonePart(batchComponent1.key(), i + 1, i + 1, i + 2); + dups.add(newCloneGroup(clonePart, dupPart)); + } + engine.saveDuplications(inputFile1, dups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(AbstractCpdEngine.MAX_CLONE_GROUP_PER_FILE); + + assertThat(logTester.logs(LoggerLevel.WARN)) + .contains("Too many duplication groups on file " + inputFile1.relativePath() + ". Keep only the first " + AbstractCpdEngine.MAX_CLONE_GROUP_PER_FILE + " groups."); + } + + @Test + public void testOneDuplicatedGroupInvolvingMoreThanTwoFiles() throws Exception { + List groups = Arrays + .asList(newCloneGroup(new ClonePart(batchComponent1.key(), 0, 5, 204), new ClonePart(batchComponent2.key(), 0, 15, 214), new ClonePart(batchComponent3.key(), 0, 25, 224))); + engine.saveDuplications(inputFile1, groups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(1); + CloseableIterator dups = reader.readComponentDuplications(batchComponent1.batchId()); + Duplication duplication = dups.next(); + dups.close(); + assertThat(duplication.getOriginPosition().getStartLine()).isEqualTo(5); + assertThat(duplication.getOriginPosition().getEndLine()).isEqualTo(204); + assertThat(duplication.getDuplicateList()).hasSize(2); + assertThat(duplication.getDuplicate(0).getOtherFileRef()).isEqualTo(batchComponent2.batchId()); + assertThat(duplication.getDuplicate(0).getRange().getStartLine()).isEqualTo(15); + assertThat(duplication.getDuplicate(0).getRange().getEndLine()).isEqualTo(214); + assertThat(duplication.getDuplicate(1).getOtherFileRef()).isEqualTo(batchComponent3.batchId()); + assertThat(duplication.getDuplicate(1).getRange().getStartLine()).isEqualTo(25); + assertThat(duplication.getDuplicate(1).getRange().getEndLine()).isEqualTo(224); + } + + @Test + public void testTwoDuplicatedGroupsInvolvingThreeFiles() throws Exception { + List groups = Arrays.asList( + newCloneGroup(new ClonePart(batchComponent1.key(), 0, 5, 204), new ClonePart(batchComponent2.key(), 0, 15, 214)), + newCloneGroup(new ClonePart(batchComponent1.key(), 0, 15, 214), new ClonePart(batchComponent3.key(), 0, 15, 214))); + engine.saveDuplications(inputFile1, groups); + + assertThat(reader.readComponentDuplications(batchComponent1.batchId())).hasSize(2); + CloseableIterator dups = reader.readComponentDuplications(batchComponent1.batchId()); + Duplication duplication1 = dups.next(); + Duplication duplication2 = dups.next(); + dups.close(); + assertThat(duplication1.getOriginPosition().getStartLine()).isEqualTo(5); + assertThat(duplication1.getOriginPosition().getEndLine()).isEqualTo(204); + assertThat(duplication1.getDuplicateList()).hasSize(1); + assertThat(duplication1.getDuplicate(0).getOtherFileRef()).isEqualTo(batchComponent2.batchId()); + assertThat(duplication1.getDuplicate(0).getRange().getStartLine()).isEqualTo(15); + assertThat(duplication1.getDuplicate(0).getRange().getEndLine()).isEqualTo(214); + + assertThat(duplication2.getOriginPosition().getStartLine()).isEqualTo(15); + assertThat(duplication2.getOriginPosition().getEndLine()).isEqualTo(214); + assertThat(duplication2.getDuplicateList()).hasSize(1); + assertThat(duplication2.getDuplicate(0).getOtherFileRef()).isEqualTo(batchComponent3.batchId()); + assertThat(duplication2.getDuplicate(0).getRange().getStartLine()).isEqualTo(15); + assertThat(duplication2.getDuplicate(0).getRange().getEndLine()).isEqualTo(214); + } + + private CloneGroup newCloneGroup(ClonePart... parts) { + return CloneGroup.builder().setLength(0).setOrigin(parts[0]).setParts(Arrays.asList(parts)).build(); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java b/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java deleted file mode 100644 index ea02cec1064..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/cpd/JavaCpdEngineTest.java +++ /dev/null @@ -1,134 +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; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.batch.sensor.duplication.NewDuplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import org.sonar.api.batch.sensor.internal.SensorStorage; -import org.sonar.api.batch.sensor.measure.Measure; -import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; -import org.sonar.duplications.index.CloneGroup; -import org.sonar.duplications.index.ClonePart; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class JavaCpdEngineTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - SensorContext context = mock(SensorContext.class); - DefaultInputFile inputFile; - private SensorStorage storage = mock(SensorStorage.class); - - @Before - public void before() throws IOException { - when(context.newMeasure()).then(new Answer() { - @Override - public Measure answer(InvocationOnMock invocation) throws Throwable { - return new DefaultMeasure(storage); - } - }); - when(context.newDuplication()).then(new Answer() { - @Override - public NewDuplication answer(InvocationOnMock invocation) throws Throwable { - return new DefaultDuplication(storage); - } - }); - inputFile = (DefaultInputFile) new DefaultInputFile("foo", "src/main/java/Foo.java").setLines(300); - inputFile.setModuleBaseDir(temp.newFolder().toPath()); - } - - @SuppressWarnings("unchecked") - @Test - public void testNothingToSave() { - JavaCpdEngine.save(context, inputFile, null); - JavaCpdEngine.save(context, inputFile, Collections.EMPTY_LIST); - - verifyZeroInteractions(context); - } - - @Test - public void testOneSimpleDuplicationBetweenTwoFiles() { - inputFile.setLines(5); - List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 2, 4), new ClonePart("key2", 0, 15, 17))); - JavaCpdEngine.save(context, inputFile, groups); - - verify(storage).store(new DefaultDuplication() - .originBlock(inputFile, 2, 4) - .isDuplicatedBy("key2", 15, 17)); - } - - @Test - public void testDuplicationOnSameFile() throws Exception { - List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key1", 0, 215, 414))); - JavaCpdEngine.save(context, inputFile, groups); - - verify(storage).store(new DefaultDuplication() - .originBlock(inputFile, 5, 204) - .isDuplicatedBy("key1", 215, 414)); - } - - @Test - public void testOneDuplicatedGroupInvolvingMoreThanTwoFiles() throws Exception { - List groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214), new ClonePart("key3", 0, 25, 224))); - JavaCpdEngine.save(context, inputFile, groups); - - verify(storage).store(new DefaultDuplication() - .originBlock(inputFile, 5, 204) - .isDuplicatedBy("key2", 15, 214) - .isDuplicatedBy("key3", 25, 224)); - } - - @Test - public void testTwoDuplicatedGroupsInvolvingThreeFiles() throws Exception { - List groups = Arrays.asList( - newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214)), - newCloneGroup(new ClonePart("key1", 0, 15, 214), new ClonePart("key3", 0, 15, 214))); - JavaCpdEngine.save(context, inputFile, groups); - - verify(storage).store(new DefaultDuplication() - .originBlock(inputFile, 5, 204) - .isDuplicatedBy("key2", 15, 214)); - verify(storage).store(new DefaultDuplication() - .originBlock(inputFile, 15, 214) - .isDuplicatedBy("key3", 15, 214)); - } - - private CloneGroup newCloneGroup(ClonePart... parts) { - return CloneGroup.builder().setLength(0).setOrigin(parts[0]).setParts(Arrays.asList(parts)).build(); - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java deleted file mode 100644 index f5913814740..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java +++ /dev/null @@ -1,65 +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.duplication; - -import org.sonar.batch.index.AbstractCachesTest; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.batch.sensor.duplication.Duplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import static org.assertj.core.api.Assertions.assertThat; - -public class DuplicationCacheTest extends AbstractCachesTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void should_add_clone_groups() { - DuplicationCache cache = new DuplicationCache(caches); - - DefaultDuplication group1 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("foo", 1, 2)); - group1.duplicates().add(new Duplication.Block("foo", 1, 2)); - group1.duplicates().add(new Duplication.Block("foo2", 12, 22)); - group1.duplicates().add(new Duplication.Block("foo3", 13, 23)); - - DefaultDuplication group2 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("2foo", 1, 2)); - group2.duplicates().add(new Duplication.Block("2foo", 1, 2)); - group2.duplicates().add(new Duplication.Block("2foo2", 12, 22)); - group2.duplicates().add(new Duplication.Block("2foo3", 13, 23)); - - assertThat(cache.componentKeys()).hasSize(0); - - cache.put("foo", group1); - cache.put("foo", group2); - - assertThat(cache.componentKeys()).hasSize(1); - assertThat(cache.byComponent("foo")).hasSize(2); - - Iterable entry = cache.byComponent("foo"); - assertThat(entry.iterator().next().originBlock().resourceKey()).isEqualTo("foo"); - - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java deleted file mode 100644 index 6482786f7dd..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/report/DuplicationsPublisherTest.java +++ /dev/null @@ -1,155 +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 java.io.File; -import java.util.Arrays; -import java.util.Collections; -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.fs.internal.DefaultInputModule; -import org.sonar.api.batch.sensor.duplication.Duplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; -import org.sonar.api.resources.Project; -import org.sonar.batch.duplication.DuplicationCache; -import org.sonar.batch.index.BatchComponentCache; -import org.sonar.batch.protocol.output.BatchReport; -import org.sonar.batch.protocol.output.BatchReportReader; -import org.sonar.batch.protocol.output.BatchReportWriter; -import org.sonar.core.util.CloseableIterator; -import org.sonar.core.util.ContextException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class DuplicationsPublisherTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private DuplicationCache duplicationCache; - private DuplicationsPublisher publisher; - - @Before - public void prepare() { - BatchComponentCache resourceCache = new BatchComponentCache(); - Project p = new Project("foo"); - resourceCache.add(p, null).setInputComponent(new DefaultInputModule("foo")); - org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); - resourceCache.add(sampleFile, null).setInputComponent(new DefaultInputFile("foo", "src/Foo.php").setLines(5)); - org.sonar.api.resources.Resource sampleFile2 = org.sonar.api.resources.File.create("src/Foo2.php").setEffectiveKey("foo:src/Foo2.php"); - resourceCache.add(sampleFile2, null).setInputComponent(new DefaultInputFile("foo", "src/Foo2.php").setLines(5)); - duplicationCache = mock(DuplicationCache.class); - when(duplicationCache.byComponent(anyString())).thenReturn(Collections.emptyList()); - publisher = new DuplicationsPublisher(resourceCache, duplicationCache); - } - - @Test - public void publishDuplications_throws_IAE_if_resource_of_duplicate_does_not_exist() throws Exception { - - DefaultDuplication dup1 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10)) - .isDuplicatedBy("another", 20, 50); - when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1)); - - expectedException.expect(ContextException.class); - expectedException.expectCause(new CauseMatcher(IllegalStateException.class, "No cross project duplication supported on batch side: another")); - - File outputDir = temp.newFolder(); - BatchReportWriter writer = new BatchReportWriter(outputDir); - - publisher.publish(writer); - } - - private static class CauseMatcher extends TypeSafeMatcher { - - private final Class type; - private final String expectedMessage; - - public CauseMatcher(Class type, String expectedMessage) { - this.type = type; - this.expectedMessage = expectedMessage; - } - - @Override - protected boolean matchesSafely(Throwable item) { - return item.getClass().isAssignableFrom(type) - && item.getMessage().contains(expectedMessage); - } - - @Override - public void describeTo(Description description) { - description.appendText("expects type ") - .appendValue(type) - .appendText(" and a message ") - .appendValue(expectedMessage); - } - } - - @Test - public void publishDuplications() throws Exception { - - DefaultDuplication dup1 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 1, 10)) - .isDuplicatedBy("foo:src/Foo.php", 20, 50); - DefaultDuplication dup2 = new DefaultDuplication() - .setOriginBlock(new Duplication.Block("foo:src/Foo.php", 11, 10)) - .isDuplicatedBy("foo:src/Foo2.php", 20, 50); - when(duplicationCache.byComponent("foo:src/Foo.php")).thenReturn(Arrays.asList(dup1, dup2)); - - File outputDir = temp.newFolder(); - BatchReportWriter writer = new BatchReportWriter(outputDir); - - publisher.publish(writer); - - BatchReportReader reader = new BatchReportReader(outputDir); - - assertThat(reader.readComponentDuplications(1)).hasSize(0); - try (CloseableIterator componentDuplications = reader.readComponentDuplications(2)) { - org.sonar.batch.protocol.output.BatchReport.Duplication savedDup1 = componentDuplications.next(); - assertThat(savedDup1.getOriginPosition().getStartLine()).isEqualTo(1); - assertThat(savedDup1.getOriginPosition().getEndLine()).isEqualTo(10); - assertThat(savedDup1.getDuplicate(0).hasOtherFileRef()).isFalse(); - assertThat(savedDup1.getDuplicate(0).getRange().getStartLine()).isEqualTo(20); - assertThat(savedDup1.getDuplicate(0).getRange().getEndLine()).isEqualTo(50); - - org.sonar.batch.protocol.output.BatchReport.Duplication savedDup2 = componentDuplications.next(); - assertThat(savedDup2.getOriginPosition().getStartLine()).isEqualTo(11); - assertThat(savedDup2.getOriginPosition().getEndLine()).isEqualTo(20); - assertThat(savedDup2.getDuplicate(0).getOtherFileRef()).isEqualTo(3); - assertThat(savedDup2.getDuplicate(0).getRange().getStartLine()).isEqualTo(20); - assertThat(savedDup2.getDuplicate(0).getRange().getEndLine()).isEqualTo(50); - - assertThat(componentDuplications.hasNext()).isFalse(); - } - - } - -} 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 85ccba5628b..618e5ea3a45 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 @@ -39,7 +39,6 @@ import org.sonar.api.measures.Measure; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.issue.ModuleIssues; import org.sonar.batch.report.ReportPublisher; @@ -85,7 +84,7 @@ public class DefaultSensorStorageTest { when(coverageExclusions.accept(any(Resource.class), any(Measure.class))).thenReturn(true); resourceCache = new BatchComponentCache(); sensorStorage = new DefaultSensorStorage(metricFinder, - moduleIssues, settings, fs, activeRules, mock(DuplicationCache.class), coverageExclusions, resourceCache, mock(ReportPublisher.class), measureCache); + moduleIssues, settings, fs, activeRules, coverageExclusions, resourceCache, mock(ReportPublisher.class), measureCache); } @Test diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index 87a98418dff..0ae851463ce 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -20,12 +20,11 @@ package org.sonar.api.batch.sensor; import com.google.common.annotations.Beta; +import java.io.Serializable; import org.sonar.api.batch.AnalysisMode; -import org.sonar.api.batch.CpdMapping; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.coverage.NewCoverage; -import org.sonar.api.batch.sensor.duplication.NewDuplication; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.batch.sensor.issue.Issue; @@ -34,8 +33,6 @@ import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.NewMeasure; import org.sonar.api.config.Settings; -import java.io.Serializable; - /** * See {@link Sensor#execute(SensorContext)} * In order to write unit tests you can use {@link SensorContextTester} @@ -89,14 +86,6 @@ public interface SensorContext { // TODO - // ------------ DUPLICATIONS ------------ - - /** - * Builder to manually register duplication in a file. This can be used in addition to {@link CpdMapping} extension point. - * Don't forget to call {@link NewDuplication#save()}. - */ - NewDuplication newDuplication(); - // ------------ TESTS ------------ /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/Duplication.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/Duplication.java deleted file mode 100644 index e445d5ce498..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/Duplication.java +++ /dev/null @@ -1,106 +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.api.batch.sensor.duplication; - -import com.google.common.annotations.Beta; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; -import org.sonar.api.batch.sensor.SensorContext; - -import java.util.List; - -/** - *

- * A {@link Duplication} is a list of duplicated {@link Block}s. One block - * is considered as the original code and all others are duplicates. - * Use {@link SensorContext#newDuplication()} to manually create a duplication. Use {@link SensorContext#duplicationTokenBuilder(org.sonar.api.batch.fs.InputFile)} - * to feed tokens and let the core compute duplications. - * @since 5.1 - */ -@Beta -public interface Duplication { - - class Block { - private final String resourceKey; - private final int startLine; - private final int length; - - public Block(String resourceKey, int startLine, int length) { - this.resourceKey = resourceKey; - this.startLine = startLine; - this.length = length; - } - - public String resourceKey() { - return resourceKey; - } - - public int startLine() { - return startLine; - } - - public int length() { - return length; - } - - // Just for unit tests - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - Block rhs = (Block) obj; - return new EqualsBuilder() - .append(resourceKey, rhs.resourceKey) - .append(startLine, rhs.startLine) - .append(length, rhs.length).isEquals(); - } - - @Override - public int hashCode() { - return new HashCodeBuilder(13, 43) - .append(resourceKey) - .append(startLine) - .append(length).toHashCode(); - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE). - append("resourceKey", resourceKey). - append("startLine", startLine). - append("length", length). - toString(); - } - } - - Block originBlock(); - - List duplicates(); - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/NewDuplication.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/NewDuplication.java deleted file mode 100644 index d4d06ba600f..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/NewDuplication.java +++ /dev/null @@ -1,56 +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.api.batch.sensor.duplication; - -import com.google.common.annotations.Beta; -import org.sonar.api.batch.fs.InputFile; - -/** - *

- * This builder is used to declare duplications on files of the project. - * Usage: - *

- * context.newDuplication();
- *   .originBlock(inputFile, 2, 10)
- *   .isDuplicatedBy(inputFile, 14, 22)
- *   .isDuplicatedBy(anotherInputFile, 3, 11)
- *   .save();
- * 
- * @since 5.1 - */ -@Beta -public interface NewDuplication { - - /** - * Declare duplication origin block. Then call {@link #isDuplicatedBy(InputFile, int, int)} to reference all duplicates of this block. - */ - NewDuplication originBlock(InputFile originFile, int startLine, int endLine); - - /** - * Declare duplicate block of the previously declared {@link #originBlock(int, int)}. Can be called several times. - * @param sameOrOtherFile duplicate can be in the same file or in another file. - */ - NewDuplication isDuplicatedBy(InputFile sameOrOtherFile, int startLine, int endLine); - - /** - * Save the duplication. - */ - void save(); -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplication.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplication.java deleted file mode 100644 index 6c00e8ba33a..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplication.java +++ /dev/null @@ -1,145 +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.api.batch.sensor.duplication.internal; - -import org.sonar.api.batch.sensor.internal.SensorStorage; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; -import org.sonar.api.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.duplication.Duplication; -import org.sonar.api.batch.sensor.duplication.NewDuplication; -import org.sonar.api.batch.sensor.internal.DefaultStorable; - -import javax.annotation.Nullable; - -import java.util.LinkedList; -import java.util.List; - -public class DefaultDuplication extends DefaultStorable implements NewDuplication, Duplication { - - private Block originBlock; - private List duplicates = new LinkedList<>(); - - public DefaultDuplication() { - super(); - } - - public DefaultDuplication(@Nullable SensorStorage storage) { - super(storage); - } - - @Override - public DefaultDuplication originBlock(InputFile inputFile, int startLine, int endLine) { - Preconditions.checkArgument(inputFile != null, "InputFile can't be null"); - validateLineArgument(inputFile, startLine, "startLine"); - validateLineArgument(inputFile, endLine, "endLine"); - originBlock = new Duplication.Block(((DefaultInputFile) inputFile).key(), startLine, endLine - startLine + 1); - return this; - } - - @Override - public DefaultDuplication isDuplicatedBy(InputFile sameOrOtherFile, int startLine, int endLine) { - Preconditions.checkArgument(sameOrOtherFile != null, "InputFile can't be null"); - validateLineArgument(sameOrOtherFile, startLine, "startLine"); - validateLineArgument(sameOrOtherFile, endLine, "endLine"); - return isDuplicatedBy(((DefaultInputFile) sameOrOtherFile).key(), startLine, endLine); - } - - /** - * For internal use. Global duplications are referencing files outside of current project so - * no way to manipulate an InputFile. - */ - public DefaultDuplication isDuplicatedBy(String fileKey, int startLine, int endLine) { - Preconditions.checkNotNull(originBlock, "Call originBlock() first"); - duplicates.add(new Duplication.Block(fileKey, startLine, endLine - startLine + 1)); - return this; - } - - @Override - public void doSave() { - Preconditions.checkNotNull(originBlock, "Call originBlock() first"); - Preconditions.checkState(!duplicates.isEmpty(), "No duplicates. Call isDuplicatedBy()"); - storage.store(this); - } - - @Override - public Block originBlock() { - return originBlock; - } - - public DefaultDuplication setOriginBlock(Block originBlock) { - this.originBlock = originBlock; - return this; - } - - @Override - public List duplicates() { - return duplicates; - } - - // Just for unit tests - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj == this) { - return true; - } - if (obj.getClass() != getClass()) { - return false; - } - DefaultDuplication rhs = (DefaultDuplication) obj; - EqualsBuilder equalsBuilder = new EqualsBuilder() - .append(originBlock, rhs.originBlock) - .append(duplicates.size(), rhs.duplicates.size()); - if (duplicates.size() == rhs.duplicates.size()) { - for (int i = 0; i < duplicates.size(); i++) { - equalsBuilder.append(duplicates.get(i), rhs.duplicates.get(i)); - } - } - return equalsBuilder.isEquals(); - } - - @Override - public int hashCode() { - HashCodeBuilder hcBuilder = new HashCodeBuilder(17, 37) - .append(originBlock) - .append(duplicates.size()); - for (int i = 0; i < duplicates.size(); i++) { - hcBuilder.append(duplicates.get(i)); - } - return hcBuilder.toHashCode(); - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE). - append("origin", originBlock). - append("duplicates", duplicates, true). - toString(); - } - -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/package-info.java deleted file mode 100644 index 229366c3e9d..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/internal/package-info.java +++ /dev/null @@ -1,21 +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. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.api.batch.sensor.duplication.internal; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/package-info.java deleted file mode 100644 index 4973316830a..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/duplication/package-info.java +++ /dev/null @@ -1,21 +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. - */ -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.api.batch.sensor.duplication; 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 df0e22ab041..11030102a8b 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 @@ -42,9 +42,6 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.coverage.CoverageType; import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; -import org.sonar.api.batch.sensor.duplication.Duplication; -import org.sonar.api.batch.sensor.duplication.NewDuplication; -import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication; import org.sonar.api.batch.sensor.highlighting.NewHighlighting; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; @@ -206,15 +203,6 @@ public class SensorContextTester implements SensorContext { return result; } - @Override - public NewDuplication newDuplication() { - return new DefaultDuplication(sensorStorage); - } - - public Collection duplications() { - return sensorStorage.duplications; - } - public static class MockAnalysisMode implements AnalysisMode { private boolean isPreview = false; private boolean isIssues = false; @@ -252,8 +240,6 @@ public class SensorContextTester implements SensorContext { private Map highlightingByComponent = new HashMap<>(); private Map> coverageByComponent = new HashMap<>(); - private List duplications = new ArrayList<>(); - @Override public void store(Measure measure) { measuresByComponentAndMetric.row(measure.inputComponent().key()).put(measure.metric().key(), measure); @@ -264,11 +250,6 @@ public class SensorContextTester implements SensorContext { allIssues.add(issue); } - @Override - public void store(Duplication duplication) { - duplications.add(duplication); - } - @Override public void store(DefaultHighlighting highlighting) { highlightingByComponent.put(highlighting.inputFile().key(), highlighting); 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 60609262b7a..c9955399506 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 @@ -21,7 +21,6 @@ package org.sonar.api.batch.sensor.internal; import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; -import org.sonar.api.batch.sensor.duplication.Duplication; import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting; import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; @@ -37,8 +36,6 @@ public interface SensorStorage { void store(Issue issue); - void store(Duplication duplication); - void store(DefaultHighlighting highlighting); /** diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/DuplicationTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/DuplicationTest.java deleted file mode 100644 index 45b5346130c..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/DuplicationTest.java +++ /dev/null @@ -1,43 +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.api.batch.sensor.duplication; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DuplicationTest { - - @Test - public void testBlockEqualsAndCo() { - Duplication.Block b1 = new Duplication.Block("foo", 1, 10); - Duplication.Block b2 = new Duplication.Block("foo", 1, 10); - assertThat(b1).isEqualTo(b1); - assertThat(b1).isEqualTo(b2); - assertThat(b1).isNotEqualTo(""); - assertThat(b1).isNotEqualTo(new Duplication.Block("foo1", 1, 10)); - assertThat(b1).isNotEqualTo(new Duplication.Block("foo", 2, 10)); - assertThat(b1).isNotEqualTo(new Duplication.Block("foo", 1, 11)); - - assertThat(b1.hashCode()).isEqualTo(188843970); - assertThat(b1.toString()).isEqualTo("Duplication.Block[resourceKey=foo,startLine=1,length=10]"); - } - -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationTest.java deleted file mode 100644 index efee043ee98..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/duplication/internal/DefaultDuplicationTest.java +++ /dev/null @@ -1,72 +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.api.batch.sensor.duplication.internal; - -import org.junit.Test; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.batch.sensor.duplication.Duplication.Block; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DefaultDuplicationTest { - - @Test - public void testDuplicationEqualsAndCo() { - DefaultInputFile file1 = new DefaultInputFile("foo", "bar.txt").setLines(50); - DefaultInputFile file2 = new DefaultInputFile("foo", "bar2.txt").setLines(50); - DefaultDuplication d1 = new DefaultDuplication() - .originBlock(file1, 1, 10) - .isDuplicatedBy(file1, 20, 29) - .isDuplicatedBy(file2, 1, 10); - DefaultDuplication d2 = new DefaultDuplication() - .originBlock(file1, 1, 10) - .isDuplicatedBy(file1, 20, 29) - .isDuplicatedBy(file2, 1, 10); - DefaultDuplication d3 = new DefaultDuplication() - .originBlock(file1, 1, 10); - assertThat(d1).isEqualTo(d1); - assertThat(d1).isEqualTo(d2); - assertThat(d1).isNotEqualTo(""); - assertThat(d1).isNotEqualTo(d3); - - assertThat(d1.hashCode()).isNotNull(); - assertThat(d1.toString()).contains("origin=Duplication.Block[resourceKey=foo:bar.txt,startLine=1,length=10]"); - assertThat(d1.toString()).contains( - "duplicates=[Duplication.Block[resourceKey=foo:bar.txt,startLine=20,length=10], Duplication.Block[resourceKey=foo:bar2.txt,startLine=1,length=10]]"); - } - - @Test - public void test() { - - DefaultInputFile file1 = new DefaultInputFile("foo", "foo.php").setLines(50); - DefaultInputFile file2 = new DefaultInputFile("foo", "foo2.php").setLines(50); - - DefaultDuplication dup = new DefaultDuplication().originBlock(file1, 1, 11) - .isDuplicatedBy(file1, 40, 50) - .isDuplicatedBy(file2, 1, 10); - - Block originBlock = dup.originBlock(); - assertThat(originBlock.resourceKey()).isEqualTo("foo:foo.php"); - assertThat(originBlock.startLine()).isEqualTo(1); - assertThat(originBlock.length()).isEqualTo(11); - assertThat(dup.duplicates()).hasSize(2); - } - -} 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 7895ab3f3ee..5e146870ea7 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 @@ -19,16 +19,12 @@ */ package org.sonar.api.batch.sensor.internal; -import org.sonar.api.batch.sensor.coverage.NewCoverage; - -import org.junit.rules.ExpectedException; - import java.io.File; import java.io.StringReader; - import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; @@ -37,11 +33,13 @@ 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.coverage.CoverageType; +import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.issue.NewIssue; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.rule.RuleKey; + import static org.assertj.core.api.Assertions.assertThat; public class SensorContextTesterTest { @@ -147,29 +145,18 @@ public class SensorContextTesterTest { assertThat(tester.highlightingTypeAt("foo:src/Foo.java", 1, 9)).containsExactly(TypeOfText.CONSTANT, TypeOfText.COMMENT); } - @Test - public void testDuplication() { - assertThat(tester.duplications()).isEmpty(); - tester.newDuplication() - .originBlock(new DefaultInputFile("foo", "src/Foo.java").setLines(40), 1, 30) - .isDuplicatedBy(new DefaultInputFile("foo", "src/Foo2.java").setLines(40), 3, 33) - .isDuplicatedBy(new DefaultInputFile("foo", "src/Foo3.java").setLines(40), 4, 34) - .save(); - assertThat(tester.duplications()).hasSize(1); - } - @Test public void testCoverageAtLineZero() { assertThat(tester.lineHits("foo:src/Foo.java", CoverageType.UNIT, 1)).isNull(); assertThat(tester.lineHits("foo:src/Foo.java", CoverageType.UNIT, 4)).isNull(); - + exception.expect(IllegalStateException.class); NewCoverage coverage = tester.newCoverage() .onFile(new DefaultInputFile("foo", "src/Foo.java").initMetadata(new FileMetadata().readMetadata(new StringReader("annot dsf fds foo bar")))) .ofType(CoverageType.UNIT) .lineHits(0, 3); } - + @Test public void testCoverageAtLineOutOfRange() { assertThat(tester.lineHits("foo:src/Foo.java", CoverageType.UNIT, 1)).isNull();