--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.duplication;
+
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Iterables.isEmpty;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS_KEY;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATED_FILES_KEY;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
+import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.server.computation.task.projectanalysis.formula.Counter;
+import org.sonar.server.computation.task.projectanalysis.formula.CounterInitializationContext;
+import org.sonar.server.computation.task.projectanalysis.formula.CreateMeasureContext;
+import org.sonar.server.computation.task.projectanalysis.formula.Formula;
+import org.sonar.server.computation.task.projectanalysis.formula.FormulaExecutorComponentVisitor;
+import org.sonar.server.computation.task.projectanalysis.measure.Measure;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
+import org.sonar.server.computation.task.projectanalysis.metric.Metric;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+
+public class DuplicationMeasures {
+ protected final ImmutableList<Formula> formulas;
+ protected final TreeRootHolder treeRootHolder;
+ protected final MetricRepository metricRepository;
+ protected final MeasureRepository measureRepository;
+ private final DuplicationRepository duplicationRepository;
+
+ public DuplicationMeasures(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
+ @Nullable DuplicationRepository duplicationRepository) {
+ this.treeRootHolder = treeRootHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ // will be null for views
+ this.duplicationRepository = duplicationRepository;
+ this.formulas = ImmutableList.<Formula>of(new DuplicationFormula(metricRepository, measureRepository));
+ }
+
+ /**
+ * Constructor used by Pico in Views where no DuplicationRepository is available.
+ */
+ public DuplicationMeasures(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this(treeRootHolder, metricRepository, measureRepository, null);
+ }
+
+ public void execute() {
+ new PathAwareCrawler<>(
+ FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository).buildFor(formulas))
+ .visit(treeRootHolder.getRoot());
+ }
+
+ protected DuplicationCounter createCounter() {
+ return new DuplicationCounter(duplicationRepository);
+ }
+
+ protected static class DuplicationCounter implements Counter<DuplicationCounter> {
+ @CheckForNull
+ private final DuplicationRepository duplicationRepository;
+ protected int fileCount = 0;
+ protected int blockCount = 0;
+ protected int lineCount = 0;
+
+ protected DuplicationCounter() {
+ this(null);
+ }
+
+ private DuplicationCounter(@Nullable DuplicationRepository duplicationRepository) {
+ this.duplicationRepository = duplicationRepository;
+ }
+
+ @Override
+ public void aggregate(DuplicationCounter counter) {
+ this.fileCount += counter.fileCount;
+ this.blockCount += counter.blockCount;
+ this.lineCount += counter.lineCount;
+ }
+
+ @Override
+ public void initialize(CounterInitializationContext context) {
+ Component leaf = context.getLeaf();
+ if (leaf.getType() == Component.Type.FILE) {
+ initializeForFile(leaf);
+ } else if (leaf.getType() == Component.Type.PROJECT_VIEW) {
+ initializeForProjectView(context);
+ }
+ }
+
+ protected void initializeForFile(Component file) {
+ Iterable<Duplication> duplications = requireNonNull(this.duplicationRepository, "DuplicationRepository missing")
+ .getDuplications(file);
+ if (isEmpty(duplications)) {
+ return;
+ }
+
+ // use a set to count lines only once
+ Set<Integer> duplicatedLineNumbers = new HashSet<>();
+ long blocks = 0;
+ for (Duplication duplication : duplications) {
+ blocks++;
+ addLines(duplication.getOriginal(), duplicatedLineNumbers);
+ for (InnerDuplicate innerDuplicate : from(duplication.getDuplicates()).filter(InnerDuplicate.class)) {
+ blocks++;
+ addLines(innerDuplicate.getTextBlock(), duplicatedLineNumbers);
+ }
+ }
+
+ this.fileCount += 1;
+ this.blockCount += blocks;
+ this.lineCount += duplicatedLineNumbers.size();
+ }
+
+ private static void addLines(TextBlock textBlock, Set<Integer> duplicatedLineNumbers) {
+ for (int i = textBlock.getStart(); i <= textBlock.getEnd(); i++) {
+ duplicatedLineNumbers.add(i);
+ }
+ }
+
+ private void initializeForProjectView(CounterInitializationContext context) {
+ fileCount += getMeasure(context, DUPLICATED_FILES_KEY);
+ blockCount += getMeasure(context, DUPLICATED_BLOCKS_KEY);
+ lineCount += getMeasure(context, DUPLICATED_LINES_KEY);
+ }
+
+ private static int getMeasure(CounterInitializationContext context, String metricKey) {
+ Optional<Measure> files = context.getMeasure(metricKey);
+ if (files.isPresent()) {
+ return files.get().getIntValue();
+ }
+ return 0;
+ }
+ }
+
+ private final class DuplicationFormula implements Formula<DuplicationCounter> {
+ private final MeasureRepository measureRepository;
+ private final Metric nclocMetric;
+ private final Metric linesMetric;
+ private final Metric commentLinesMetric;
+
+ private DuplicationFormula(MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.measureRepository = measureRepository;
+ this.nclocMetric = metricRepository.getByKey(NCLOC_KEY);
+ this.linesMetric = metricRepository.getByKey(LINES_KEY);
+ this.commentLinesMetric = metricRepository.getByKey(COMMENT_LINES_KEY);
+ }
+
+ @Override
+ public DuplicationCounter createNewCounter() {
+ return createCounter();
+ }
+
+ @Override
+ public Optional<Measure> createMeasure(DuplicationCounter counter, CreateMeasureContext context) {
+ switch (context.getMetric().getKey()) {
+ case DUPLICATED_FILES_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.fileCount));
+ case DUPLICATED_LINES_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.lineCount));
+ case DUPLICATED_LINES_DENSITY_KEY:
+ return createDuplicatedLinesDensityMeasure(counter, context);
+ case DUPLICATED_BLOCKS_KEY:
+ return Optional.of(Measure.newMeasureBuilder().create(counter.blockCount));
+ default:
+ throw new IllegalArgumentException("Unsupported metric " + context.getMetric());
+ }
+ }
+
+ private Optional<Measure> createDuplicatedLinesDensityMeasure(DuplicationCounter counter, CreateMeasureContext context) {
+ int duplicatedLines = counter.lineCount;
+ java.util.Optional<Integer> nbLines = getNbLinesFromLocOrNcloc(context);
+ if (nbLines.isPresent() && nbLines.get() > 0) {
+ double density = Math.min(100d, 100d * duplicatedLines / nbLines.get());
+ return Optional.of(Measure.newMeasureBuilder().create(density, context.getMetric().getDecimalScale()));
+ }
+ return Optional.absent();
+ }
+
+ private java.util.Optional<Integer> getNbLinesFromLocOrNcloc(CreateMeasureContext context) {
+ Optional<Measure> lines = measureRepository.getRawMeasure(context.getComponent(), linesMetric);
+ if (lines.isPresent()) {
+ return java.util.Optional.of(lines.get().getIntValue());
+ }
+ Optional<Measure> nclocs = measureRepository.getRawMeasure(context.getComponent(), nclocMetric);
+ if (nclocs.isPresent()) {
+ Optional<Measure> commentLines = measureRepository.getRawMeasure(context.getComponent(), commentLinesMetric);
+ int nbLines = nclocs.get().getIntValue();
+ return java.util.Optional.of(commentLines.isPresent() ? (nbLines + commentLines.get().getIntValue()) : nbLines);
+ }
+ return java.util.Optional.empty();
+ }
+
+ @Override
+ public String[] getOutputMetricKeys() {
+ return new String[] {DUPLICATED_FILES_KEY, DUPLICATED_LINES_KEY, DUPLICATED_LINES_DENSITY_KEY, DUPLICATED_BLOCKS_KEY};
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.duplication;
+
+public interface IncrementalDuplicationMeasures {
+ void execute();
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.measure;
+
+/**
+ * Provided by the incremental plugin
+ */
+public interface IncrementalMeasureTransition extends Runnable {
+
+}
*/
package org.sonar.server.computation.task.projectanalysis.step;
-import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableList;
-import java.util.HashSet;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.task.projectanalysis.component.Component;
-import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
-import org.sonar.server.computation.task.projectanalysis.duplication.Duplication;
-import org.sonar.server.computation.task.projectanalysis.duplication.DuplicationRepository;
-import org.sonar.server.computation.task.projectanalysis.duplication.InnerDuplicate;
-import org.sonar.server.computation.task.projectanalysis.duplication.TextBlock;
-import org.sonar.server.computation.task.projectanalysis.formula.Counter;
-import org.sonar.server.computation.task.projectanalysis.formula.CounterInitializationContext;
-import org.sonar.server.computation.task.projectanalysis.formula.CreateMeasureContext;
-import org.sonar.server.computation.task.projectanalysis.formula.Formula;
-import org.sonar.server.computation.task.projectanalysis.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.task.projectanalysis.measure.Measure;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepository;
-import org.sonar.server.computation.task.projectanalysis.metric.Metric;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepository;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.task.projectanalysis.duplication.DuplicationMeasures;
+import org.sonar.server.computation.task.projectanalysis.duplication.IncrementalDuplicationMeasures;
import org.sonar.server.computation.task.step.ComputationStep;
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Iterables.isEmpty;
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
-import static org.sonar.api.measures.CoreMetrics.DUPLICATED_BLOCKS_KEY;
-import static org.sonar.api.measures.CoreMetrics.DUPLICATED_FILES_KEY;
-import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
-import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_KEY;
-import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
-import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
-
/**
* Computes duplication measures on files and then aggregates them on higher components.
*
* This step must be executed after {@link CommentMeasuresStep} as it depends on {@link CoreMetrics#COMMENT_LINES}
*/
public class DuplicationMeasuresStep implements ComputationStep {
-
- private final ImmutableList<Formula> formulas;
-
- private final TreeRootHolder treeRootHolder;
- private final MetricRepository metricRepository;
- private final MeasureRepository measureRepository;
-
- public DuplicationMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
- @Nullable DuplicationRepository duplicationRepository) {
- this.treeRootHolder = treeRootHolder;
- this.metricRepository = metricRepository;
- this.measureRepository = measureRepository;
- this.formulas = ImmutableList.<Formula>of(new DuplicationFormula(metricRepository, measureRepository, duplicationRepository));
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final DuplicationMeasures defaultDuplicationMeasures;
+ private final IncrementalDuplicationMeasures incrementalDuplicationsMeasures;
+
+ public DuplicationMeasuresStep(AnalysisMetadataHolder analysisMetadataHolder, DuplicationMeasures defaultDuplicationMeasures,
+ IncrementalDuplicationMeasures incrementalDuplicationMeasures) {
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ this.defaultDuplicationMeasures = defaultDuplicationMeasures;
+ this.incrementalDuplicationsMeasures = incrementalDuplicationMeasures;
}
/**
- * Constructor used by Pico in Views where no DuplicationRepository is available.
+ * Constructor used by Pico in Views where no IncrementalDuplicationMeasures is available.
*/
- public DuplicationMeasuresStep(TreeRootHolder treeRootHolder, MetricRepository metricRepository, MeasureRepository measureRepository) {
- this(treeRootHolder, metricRepository, measureRepository, null);
+ public DuplicationMeasuresStep(AnalysisMetadataHolder analysisMetadataHolder, DuplicationMeasures defaultDuplicationMeasures) {
+ this(analysisMetadataHolder, defaultDuplicationMeasures, null);
}
@Override
@Override
public void execute() {
- new PathAwareCrawler<>(
- FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository).buildFor(formulas))
- .visit(treeRootHolder.getRoot());
- }
-
- private static class DuplicationCounter implements Counter<DuplicationCounter> {
- @CheckForNull
- private final DuplicationRepository duplicationRepository;
- private int fileCount = 0;
- private int blockCount = 0;
- private int lineCount = 0;
-
- private DuplicationCounter(@Nullable DuplicationRepository duplicationRepository) {
- this.duplicationRepository = duplicationRepository;
- }
-
- @Override
- public void aggregate(DuplicationCounter counter) {
- this.fileCount += counter.fileCount;
- this.blockCount += counter.blockCount;
- this.lineCount += counter.lineCount;
- }
-
- @Override
- public void initialize(CounterInitializationContext context) {
- Component leaf = context.getLeaf();
- if (leaf.getType() == Component.Type.FILE) {
- initializeForFile(leaf);
- } else if (leaf.getType() == Component.Type.PROJECT_VIEW) {
- initializeForProjectView(context);
- }
- }
-
- private void initializeForFile(Component file) {
- Iterable<Duplication> duplications = requireNonNull(this.duplicationRepository, "DuplicationRepository missing")
- .getDuplications(file);
- if (isEmpty(duplications)) {
- return;
- }
-
- // use a set to count lines only once
- Set<Integer> duplicatedLineNumbers = new HashSet<>();
- long blocks = 0;
- for (Duplication duplication : duplications) {
- blocks++;
- addLines(duplication.getOriginal(), duplicatedLineNumbers);
- for (InnerDuplicate innerDuplicate : from(duplication.getDuplicates()).filter(InnerDuplicate.class)) {
- blocks++;
- addLines(innerDuplicate.getTextBlock(), duplicatedLineNumbers);
- }
- }
-
- this.fileCount += 1;
- this.blockCount += blocks;
- this.lineCount += duplicatedLineNumbers.size();
- }
-
- private static void addLines(TextBlock textBlock, Set<Integer> duplicatedLineNumbers) {
- for (int i = textBlock.getStart(); i <= textBlock.getEnd(); i++) {
- duplicatedLineNumbers.add(i);
- }
- }
-
- private void initializeForProjectView(CounterInitializationContext context) {
- fileCount += getMeasure(context, DUPLICATED_FILES_KEY);
- blockCount += getMeasure(context, DUPLICATED_BLOCKS_KEY);
- lineCount += getMeasure(context, DUPLICATED_LINES_KEY);
- }
-
- private static int getMeasure(CounterInitializationContext context, String metricKey) {
- Optional<Measure> files = context.getMeasure(metricKey);
- if (files.isPresent()) {
- return files.get().getIntValue();
- }
- return 0;
- }
- }
-
- private static final class DuplicationFormula implements Formula<DuplicationCounter> {
- private final MeasureRepository measureRepository;
- @CheckForNull
- private final DuplicationRepository duplicationRepository;
- private final Metric nclocMetric;
- private final Metric linesMetric;
- private final Metric commentLinesMetric;
-
- private DuplicationFormula(MetricRepository metricRepository, MeasureRepository measureRepository, @Nullable DuplicationRepository duplicationRepository) {
- this.measureRepository = measureRepository;
- this.duplicationRepository = duplicationRepository;
- this.nclocMetric = metricRepository.getByKey(NCLOC_KEY);
- this.linesMetric = metricRepository.getByKey(LINES_KEY);
- this.commentLinesMetric = metricRepository.getByKey(COMMENT_LINES_KEY);
- }
-
- @Override
- public DuplicationCounter createNewCounter() {
- return new DuplicationCounter(duplicationRepository);
- }
-
- @Override
- public Optional<Measure> createMeasure(DuplicationCounter counter, CreateMeasureContext context) {
- switch (context.getMetric().getKey()) {
- case DUPLICATED_FILES_KEY:
- return Optional.of(Measure.newMeasureBuilder().create(counter.fileCount));
- case DUPLICATED_LINES_KEY:
- return Optional.of(Measure.newMeasureBuilder().create(counter.lineCount));
- case DUPLICATED_LINES_DENSITY_KEY:
- return createDuplicatedLinesDensityMeasure(counter, context);
- case DUPLICATED_BLOCKS_KEY:
- return Optional.of(Measure.newMeasureBuilder().create(counter.blockCount));
- default:
- throw new IllegalArgumentException("Unsupported metric " + context.getMetric());
- }
- }
-
- private Optional<Measure> createDuplicatedLinesDensityMeasure(DuplicationCounter counter, CreateMeasureContext context) {
- int duplicatedLines = counter.lineCount;
- java.util.Optional<Integer> nbLines = getNbLinesFromLocOrNcloc(context);
- if (nbLines.isPresent() && nbLines.get() > 0) {
- double density = Math.min(100d, 100d * duplicatedLines / nbLines.get());
- return Optional.of(Measure.newMeasureBuilder().create(density, context.getMetric().getDecimalScale()));
- }
- return Optional.absent();
- }
-
- private java.util.Optional<Integer> getNbLinesFromLocOrNcloc(CreateMeasureContext context) {
- Optional<Measure> lines = measureRepository.getRawMeasure(context.getComponent(), linesMetric);
- if (lines.isPresent()) {
- return java.util.Optional.of(lines.get().getIntValue());
- }
- Optional<Measure> nclocs = measureRepository.getRawMeasure(context.getComponent(), nclocMetric);
- if (nclocs.isPresent()) {
- Optional<Measure> commentLines = measureRepository.getRawMeasure(context.getComponent(), commentLinesMetric);
- int nbLines = nclocs.get().getIntValue();
- return java.util.Optional.of(commentLines.isPresent() ? (nbLines + commentLines.get().getIntValue()) : nbLines);
- }
- return java.util.Optional.empty();
- }
-
- @Override
- public String[] getOutputMetricKeys() {
- return new String[] {DUPLICATED_FILES_KEY, DUPLICATED_LINES_KEY, DUPLICATED_LINES_DENSITY_KEY, DUPLICATED_BLOCKS_KEY};
+ if (analysisMetadataHolder.isIncrementalAnalysis()) {
+ incrementalDuplicationsMeasures.execute();
+ } else {
+ defaultDuplicationMeasures.execute();
}
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.step;
+
+import org.sonar.server.computation.task.step.ComputationStep;
+
+public class IncrementalDuplicationsStep implements ComputationStep {
+
+ @Override
+ public void execute() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.step;
+
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.task.projectanalysis.measure.IncrementalMeasureTransition;
+import org.sonar.server.computation.task.step.ComputationStep;
+
+public class IncrementalMeasureTransitionStep implements ComputationStep {
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final IncrementalMeasureTransition runnable;
+
+ public IncrementalMeasureTransitionStep(AnalysisMetadataHolder analysisMetadataHolder) {
+ this(analysisMetadataHolder, null);
+ }
+
+ public IncrementalMeasureTransitionStep(AnalysisMetadataHolder analysisMetadataHolder, IncrementalMeasureTransition runnable) {
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ this.runnable = runnable;
+ }
+
+ @Override
+ public void execute() {
+ if (analysisMetadataHolder.isIncrementalAnalysis()) {
+ runnable.run();
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Incremental measure transition";
+ }
+}
import javax.annotation.Nonnull;
import org.sonar.core.util.CloseableIterator;
import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
private final TreeRootHolder treeRootHolder;
private final BatchReportReader batchReportReader;
private final DuplicationRepository duplicationRepository;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
- public LoadDuplicationsFromReportStep(TreeRootHolder treeRootHolder, BatchReportReader batchReportReader, DuplicationRepository duplicationRepository) {
+ public LoadDuplicationsFromReportStep(TreeRootHolder treeRootHolder, BatchReportReader batchReportReader,
+ DuplicationRepository duplicationRepository, AnalysisMetadataHolder analysisMetadataHolder) {
this.treeRootHolder = treeRootHolder;
this.batchReportReader = batchReportReader;
this.duplicationRepository = duplicationRepository;
+ this.analysisMetadataHolder = analysisMetadataHolder;
}
@Override
@Override
public void execute() {
- new DepthTraversalTypeAwareCrawler(
- new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, POST_ORDER) {
- @Override
- public void visitFile(Component file) {
- CloseableIterator<ScannerReport.Duplication> duplications = batchReportReader.readComponentDuplications(file.getReportAttributes().getRef());
- try {
- int idGenerator = 1;
- while (duplications.hasNext()) {
- loadDuplications(file, duplications.next(), idGenerator);
- idGenerator++;
+ if (!analysisMetadataHolder.isIncrementalAnalysis()) {
+ new DepthTraversalTypeAwareCrawler(
+ new TypeAwareVisitorAdapter(CrawlerDepthLimit.FILE, POST_ORDER) {
+ @Override
+ public void visitFile(Component file) {
+ CloseableIterator<ScannerReport.Duplication> duplications = batchReportReader.readComponentDuplications(file.getReportAttributes().getRef());
+ try {
+ int idGenerator = 1;
+ while (duplications.hasNext()) {
+ loadDuplications(file, duplications.next(), idGenerator);
+ idGenerator++;
+ }
+ } finally {
+ duplications.close();
}
- } finally {
- duplications.close();
}
- }
- }).visit(treeRootHolder.getRoot());
+ }).visit(treeRootHolder.getRoot());
+ }
}
private void loadDuplications(Component file, ScannerReport.Duplication duplication, int id) {
ValidateProjectStep.class,
LoadQualityProfilesStep.class,
+
+ // copy data in the incremental mode
+ IncrementalMeasureTransitionStep.class,
// load project related stuffs
LoadQualityGateStep.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.step;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.duplication.DuplicationMeasures;
+import org.sonar.server.computation.task.projectanalysis.duplication.IncrementalDuplicationMeasures;
+import org.sonar.server.computation.task.step.ComputationStep;
+
+public class DuplicationMeasuresStepTest extends BaseStepTest {
+ @Mock
+ private DuplicationMeasures defaultDuplicationMeasures;
+ @Mock
+ private IncrementalDuplicationMeasures incrementalDuplicationMeasures;
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+
+ private DuplicationMeasuresStep underTest;
+
+ @Before
+ public void before() {
+ MockitoAnnotations.initMocks(this);
+ underTest = new DuplicationMeasuresStep(analysisMetadataHolder, defaultDuplicationMeasures, incrementalDuplicationMeasures);
+ }
+
+ @Test
+ public void incremental_analysis_mode() {
+ analysisMetadataHolder.setIncrementalAnalysis(true);
+ underTest.execute();
+ verify(incrementalDuplicationMeasures).execute();
+ verifyZeroInteractions(defaultDuplicationMeasures);
+ }
+
+ @Test
+ public void full_analysis_mode() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
+ underTest.execute();
+ verify(defaultDuplicationMeasures).execute();
+ verifyZeroInteractions(incrementalDuplicationMeasures);
+ }
+
+ @Override
+ protected ComputationStep step() {
+ return underTest;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.step;
+
+public class IncrementalDuplicationsStepTest {
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.computation.task.projectanalysis.step;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.task.projectanalysis.measure.IncrementalMeasureTransition;
+import org.sonar.server.computation.task.step.ComputationStep;
+
+public class IncrementalMeasureTransitionStepTest extends BaseStepTest {
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+
+ IncrementalMeasureTransitionStep underTest = new IncrementalMeasureTransitionStep(analysisMetadataHolder);
+
+ @Override
+ protected ComputationStep step() {
+ return underTest;
+ }
+
+ @Test
+ public void skip_if_not_incremental() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
+ underTest.execute();
+ }
+
+ @Test
+ public void execute_if_incremental() {
+ IncrementalMeasureTransition runnable = mock(IncrementalMeasureTransition.class);
+ IncrementalMeasureTransitionStep underTest = new IncrementalMeasureTransitionStep(analysisMetadataHolder, runnable);
+ analysisMetadataHolder.setIncrementalAnalysis(true);
+
+ underTest.execute();
+ verify(runnable).run();
+ }
+
+}
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
@Rule
public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
- private LoadDuplicationsFromReportStep underTest = new LoadDuplicationsFromReportStep(treeRootHolder, reportReader, duplicationRepository);
+ private LoadDuplicationsFromReportStep underTest = new LoadDuplicationsFromReportStep(treeRootHolder, reportReader, duplicationRepository, analysisMetadataHolder);
@Test
public void verify_description() {
assertThat(underTest.getDescription()).isEqualTo("Load inner file and in project duplications");
}
+
+ @Test
+ public void skip_if_incremental_analysis() {
+ analysisMetadataHolder.setIncrementalAnalysis(true);
+ reportReader.putDuplications(FILE_2_REF, createDuplication(singleLineTextRange(LINE), createInnerDuplicate(LINE + 1)));
+
+ underTest.execute();
+
+ assertNoDuplication(FILE_2_REF);
+ }
@Test
public void loads_no_duplications_if_reader_has_no_duplication() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
underTest.execute();
assertNoDuplication(FILE_1_REF);
@Test
public void loads_duplication_without_otherFileRef_as_inner_duplication() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
reportReader.putDuplications(FILE_2_REF, createDuplication(singleLineTextRange(LINE), createInnerDuplicate(LINE + 1)));
underTest.execute();
@Test
public void loads_duplication_with_otherFileRef_as_inProject_duplication() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(LINE), createInProjectDuplicate(FILE_2_REF, LINE + 1)));
underTest.execute();
@Test
public void loads_multiple_duplications_with_multiple_duplicates() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
reportReader.putDuplications(
FILE_2_REF,
createDuplication(
@Test
public void loads_never_consider_originals_from_batch_on_same_lines_as_the_equals() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
reportReader.putDuplications(
FILE_2_REF,
createDuplication(
@Test
public void loads_duplication_with_otherFileRef_throws_IAE_if_component_does_not_exist() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
int line = 2;
reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(line), createInProjectDuplicate(666, line + 1)));
@Test
public void loads_duplication_with_otherFileRef_throws_IAE_if_references_itself() {
+ analysisMetadataHolder.setIncrementalAnalysis(false);
int line = 2;
reportReader.putDuplications(FILE_1_REF, createDuplication(singleLineTextRange(line), createInProjectDuplicate(FILE_1_REF, line + 1)));
* 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.server.computation.task.projectanalysis.step;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.duplication.DuplicationRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.duplication.TextBlock;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.server.computation.task.step.ComputationStep;
+package org.sonar.server.computation.task.projectanalysis.duplication;
import static com.google.common.base.Preconditions.checkArgument;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-public class ReportDuplicationMeasuresStepTest {
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
+public class ReportDuplicationMeasuresTest {
private static final int ROOT_REF = 1;
private static final int MODULE_REF = 12;
private static final int SUB_MODULE_1_REF = 123;
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
.setRoot(
- builder(PROJECT, ROOT_REF)
- .addChildren(
- builder(MODULE, MODULE_REF)
- .addChildren(
- builder(MODULE, SUB_MODULE_1_REF)
- .addChildren(
- builder(DIRECTORY, DIRECTORY_REF)
- .addChildren(
- builder(FILE, FILE_1_REF).build(),
- builder(FILE, FILE_2_REF).build())
- .build())
- .build(),
- builder(MODULE, SUB_MODULE_2_REF)
- .addChildren(
- builder(FILE, FILE_3_REF).build(),
- builder(FILE, FILE_4_REF).build()
- )
- .build())
- .build())
- .build());
+ builder(PROJECT, ROOT_REF)
+ .addChildren(
+ builder(MODULE, MODULE_REF)
+ .addChildren(
+ builder(MODULE, SUB_MODULE_1_REF)
+ .addChildren(
+ builder(DIRECTORY, DIRECTORY_REF)
+ .addChildren(
+ builder(FILE, FILE_1_REF).build(),
+ builder(FILE, FILE_2_REF).build())
+ .build())
+ .build(),
+ builder(MODULE, SUB_MODULE_2_REF)
+ .addChildren(
+ builder(FILE, FILE_3_REF).build(),
+ builder(FILE, FILE_4_REF).build())
+ .build())
+ .build())
+ .build());
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(LINES)
@Rule
public DuplicationRepositoryRule duplicationRepository = DuplicationRepositoryRule.create(treeRootHolder);
- ComputationStep underTest = new DuplicationMeasuresStep(treeRootHolder, metricRepository, measureRepository, duplicationRepository);
+ DuplicationMeasures underTest = new DuplicationMeasures(treeRootHolder, metricRepository, measureRepository, duplicationRepository);
@Test
public void compute_duplicated_blocks_one_for_original_one_for_each_InnerDuplicate() {
* 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.server.computation.task.projectanalysis.step;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
-import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.server.computation.task.step.ComputationStep;
+package org.sonar.server.computation.task.projectanalysis.duplication;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.assertThat;
import static org.sonar.server.computation.task.projectanalysis.component.ViewsComponent.builder;
import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
-public class ViewsDuplicationMeasuresStepTest {
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
+import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
+
+public class ViewsDuplicationMeasuresTest {
private static final int ROOT_REF = 1;
private static final int SUBVIEW_REF = 12;
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- ComputationStep underTest = new DuplicationMeasuresStep(treeRootHolder, metricRepository, measureRepository);
+ DuplicationMeasures underTest = new DuplicationMeasures(treeRootHolder, metricRepository, measureRepository);
@Test
public void aggregate_duplicated_blocks() {