--- /dev/null
+/*
+ * 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<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.");
+ }
+ final BatchComponent component = batchComponentCache.get(inputFile);
+ Iterable<org.sonar.batch.protocol.output.BatchReport.Duplication> reportDuplications = from(duplications)
+ .limit(MAX_CLONE_GROUP_PER_FILE)
+ .transform(
+ new Function<CloneGroup, BatchReport.Duplication>() {
+ 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();
+ }
+
+}
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;
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);
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;
String resourceEffectiveKey = ((DefaultInputFile) inputFile).key();
Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
- Iterable<CloneGroup> filtered;
+ List<CloneGroup> filtered;
try {
List<CloneGroup> 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();
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;
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;
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;
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);
*/
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;
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();
}
}
- static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> 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<CloneGroup> 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();
- }
- }
-
}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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<DefaultDuplication> cache;
- private int sequence = 1;
-
- public DuplicationCache(Caches caches) {
- caches.registerValueCoder(DefaultDuplication.class, new DefaultDuplicationValueCoder());
- cache = caches.createCache("duplications");
- }
-
- public Iterable<String> componentKeys() {
- return Iterables.transform(cache.keySet(), new Function<Object, String>() {
- @Override
- public String apply(Object input) {
- return input.toString();
- }
- });
- }
-
- public Iterable<DefaultDuplication> byComponent(String effectiveKey) {
- return cache.values(effectiveKey);
- }
-
- public DuplicationCache put(String effectiveKey, DefaultDuplication duplication) {
- cache.put(effectiveKey, sequence, duplication);
- sequence++;
- return this;
- }
-
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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<DefaultDuplication> dups = duplicationCache.byComponent(resource.resource().getEffectiveKey());
- if (dups.iterator().hasNext()) {
- Iterable<org.sonar.batch.protocol.output.BatchReport.Duplication> reportDuplications = Iterables.transform(dups,
- new Function<DefaultDuplication, BatchReport.Duplication>() {
- 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();
- }
-
-}
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;
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;
// Measures
MeasureCache.class,
- // Duplications
- DuplicationCache.class,
-
ProjectSettings.class,
// Report
ActiveRulesPublisher.class,
ComponentsPublisher.class,
MeasuresPublisher.class,
- DuplicationsPublisher.class,
CoveragePublisher.class,
SourcePublisher.class,
TestExecutionAndCoveragePublisher.class,
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;
return new DefaultHighlighting(sensorStorage);
}
- @Override
- public NewDuplication newDuplication() {
- return new DefaultDuplication(sensorStorage);
- }
-
@Override
public NewCoverage newCoverage() {
return new DefaultCoverage(sensorStorage);
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;
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;
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;
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();
--- /dev/null
+/*
+ * 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<CloneGroup> 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<Duplication> 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<CloneGroup> 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<Duplication> 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<ClonePart> 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<CloneGroup> 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<Duplication> 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<CloneGroup> 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<CloneGroup> 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<Duplication> 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<CloneGroup> 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<Duplication> 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();
+ }
+
+}
+++ /dev/null
-/*
- * 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<Measure>() {
- @Override
- public Measure answer(InvocationOnMock invocation) throws Throwable {
- return new DefaultMeasure(storage);
- }
- });
- when(context.newDuplication()).then(new Answer<NewDuplication>() {
- @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<CloneGroup> 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<CloneGroup> 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<CloneGroup> 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<CloneGroup> 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();
- }
-
-}
+++ /dev/null
-/*
- * 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<DefaultDuplication> entry = cache.byComponent("foo");
- assertThat(entry.iterator().next().originBlock().resourceKey()).isEqualTo("foo");
-
- }
-
-}
+++ /dev/null
-/*
- * 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.<DefaultDuplication>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<Throwable> {
-
- private final Class<? extends Throwable> type;
- private final String expectedMessage;
-
- public CauseMatcher(Class<? extends Throwable> 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<BatchReport.Duplication> 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();
- }
-
- }
-
-}
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;
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
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;
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}
// 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 ------------
/**
+++ /dev/null
-/*
- * 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;
-
-/**
- * <p/>
- * 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<Block> duplicates();
-
-}
+++ /dev/null
-/*
- * 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;
-
-/**
- * <p/>
- * This builder is used to declare duplications on files of the project.
- * Usage:
- * <code><pre>
- * context.newDuplication();
- * .originBlock(inputFile, 2, 10)
- * .isDuplicatedBy(inputFile, 14, 22)
- * .isDuplicatedBy(anotherInputFile, 3, 11)
- * .save();
- * </pre></code>
- * @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();
-}
+++ /dev/null
-/*
- * 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<Block> 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<Block> 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();
- }
-
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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;
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;
return result;
}
- @Override
- public NewDuplication newDuplication() {
- return new DefaultDuplication(sensorStorage);
- }
-
- public Collection<Duplication> duplications() {
- return sensorStorage.duplications;
- }
-
public static class MockAnalysisMode implements AnalysisMode {
private boolean isPreview = false;
private boolean isIssues = false;
private Map<String, DefaultHighlighting> highlightingByComponent = new HashMap<>();
private Map<String, Map<CoverageType, DefaultCoverage>> coverageByComponent = new HashMap<>();
- private List<Duplication> duplications = new ArrayList<>();
-
@Override
public void store(Measure measure) {
measuresByComponentAndMetric.row(measure.inputComponent().key()).put(measure.metric().key(), measure);
allIssues.add(issue);
}
- @Override
- public void store(Duplication duplication) {
- duplications.add(duplication);
- }
-
@Override
public void store(DefaultHighlighting highlighting) {
highlightingByComponent.put(highlighting.inputFile().key(), highlighting);
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;
void store(Issue issue);
- void store(Duplication duplication);
-
void store(DefaultHighlighting highlighting);
/**
+++ /dev/null
-/*
- * 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]");
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-
-}
*/
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;
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 {
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();