From 212000d472e0c9a818de55cf54f5688d03febf03 Mon Sep 17 00:00:00 2001
From: =?utf8?q?S=C3=A9bastien=20Lesaint?=
Date: Wed, 16 Dec 2015 11:54:58 +0100
Subject: [PATCH] SONAR-6990 support repeated original-duplicate paars from the
batch
---
.../duplication/DetailedTextBlock.java | 65 +++++++++++++++++++
.../computation/duplication/TextBlock.java | 2 +-
.../step/LoadDuplicationsFromReportStep.java | 12 +++-
.../LoadDuplicationsFromReportStepTest.java | 44 +++++++++++--
4 files changed, 114 insertions(+), 9 deletions(-)
create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/duplication/DetailedTextBlock.java
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/DetailedTextBlock.java b/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/DetailedTextBlock.java
new file mode 100644
index 00000000000..a096335c870
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/DetailedTextBlock.java
@@ -0,0 +1,65 @@
+/*
+ * 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.server.computation.duplication;
+
+import java.util.Objects;
+import javax.annotation.Nullable;
+
+/**
+ * Given that:
+ *
+ * - some language plugins are able to multiple duplication for the same textblock but with a
+ * different starting and/or ending offset
+ * - there is no way to distinguish these block from each other as the offsets (or any other
+ * information) is not sent in the analysis report
+ *
,
+ * we are uniquely (and blindly) identifying each original block reported in the analysis report.
+ */
+public class DetailedTextBlock extends TextBlock {
+ private final int id;
+ /**
+ * @throws IllegalArgumentException if {@code start} is 0 or less
+ * @throws IllegalStateException if {@code end} is less than {@code start}
+ */
+ public DetailedTextBlock(int id, int start, int end) {
+ super(start, end);
+ this.id = id;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ DetailedTextBlock that = (DetailedTextBlock) o;
+ return id == that.id;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), id);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/TextBlock.java b/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/TextBlock.java
index e317e7c9225..43a24c871e4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/TextBlock.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/duplication/TextBlock.java
@@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* same start line, by smallest size (ie. lowest end line).
*
*/
-public final class TextBlock implements Comparable {
+public class TextBlock implements Comparable {
private final int start;
private final int end;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStep.java
index 3006266bfc2..6d0927f9f71 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStep.java
@@ -27,6 +27,7 @@ import org.sonar.server.computation.component.CrawlerDepthLimit;
import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.duplication.DetailedTextBlock;
import org.sonar.server.computation.duplication.DuplicationRepository;
import org.sonar.server.computation.duplication.TextBlock;
@@ -59,8 +60,9 @@ public class LoadDuplicationsFromReportStep implements ComputationStep {
public void visitFile(Component file) {
CloseableIterator duplications = batchReportReader.readComponentDuplications(file.getReportAttributes().getRef());
try {
+ int idGenerator = 1;
while (duplications.hasNext()) {
- loadDuplications(file, duplications.next());
+ loadDuplications(file, duplications.next(), idGenerator++);
}
} finally {
duplications.close();
@@ -69,8 +71,8 @@ public class LoadDuplicationsFromReportStep implements ComputationStep {
}).visit(treeRootHolder.getRoot());
}
- private void loadDuplications(Component file, BatchReport.Duplication duplication) {
- TextBlock original = convert(duplication.getOriginPosition());
+ private void loadDuplications(Component file, BatchReport.Duplication duplication, int id) {
+ DetailedTextBlock original = convert(duplication.getOriginPosition(), id);
for (BatchReport.Duplicate duplicate : duplication.getDuplicateList()) {
if (duplicate.hasOtherFileRef()) {
duplicationRepository.addDuplication(file, original, treeRootHolder.getComponentByRef(duplicate.getOtherFileRef()), convert(duplicate.getRange()));
@@ -83,4 +85,8 @@ public class LoadDuplicationsFromReportStep implements ComputationStep {
private static TextBlock convert(BatchReport.TextRange textRange) {
return new TextBlock(textRange.getStartLine(), textRange.getEndLine());
}
+
+ private static DetailedTextBlock convert(BatchReport.TextRange textRange, int id) {
+ return new DetailedTextBlock(id, textRange.getStartLine(), textRange.getEndLine());
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStepTest.java
index 5515924be2e..b1423876afd 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStepTest.java
@@ -28,6 +28,7 @@ import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.VisitException;
+import org.sonar.server.computation.duplication.DetailedTextBlock;
import org.sonar.server.computation.duplication.Duplicate;
import org.sonar.server.computation.duplication.Duplication;
import org.sonar.server.computation.duplication.DuplicationRepositoryRule;
@@ -85,7 +86,7 @@ public class LoadDuplicationsFromReportStepTest {
underTest.execute();
assertNoDuplication(FILE_1_REF);
- assertDuplications(FILE_2_REF, singleLineTextBlock(LINE), new InnerDuplicate(singleLineTextBlock(LINE + 1)));
+ assertDuplications(FILE_2_REF, singleLineDetailedTextBlock(1, LINE), new InnerDuplicate(singleLineTextBlock(LINE + 1)));
}
@Test
@@ -94,7 +95,7 @@ public class LoadDuplicationsFromReportStepTest {
underTest.execute();
- assertDuplications(FILE_1_REF, singleLineTextBlock(LINE), new InProjectDuplicate(treeRootHolder.getComponentByRef(FILE_2_REF), singleLineTextBlock(LINE + 1)));
+ assertDuplications(FILE_1_REF, singleLineDetailedTextBlock(1, LINE), new InProjectDuplicate(treeRootHolder.getComponentByRef(FILE_2_REF), singleLineTextBlock(LINE + 1)));
assertNoDuplication(FILE_2_REF);
}
@@ -118,20 +119,49 @@ public class LoadDuplicationsFromReportStepTest {
Component file1Component = treeRootHolder.getComponentByRef(FILE_1_REF);
assertThat(duplicationRepository.getDuplications(FILE_2_REF)).containsOnly(
duplication(
- singleLineTextBlock(LINE),
+ singleLineDetailedTextBlock(1, LINE),
new InnerDuplicate(singleLineTextBlock(LINE + 1)), new InnerDuplicate(singleLineTextBlock(LINE + 2)), new InProjectDuplicate(file1Component, singleLineTextBlock(LINE)),
new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 10))),
duplication(
- singleLineTextBlock(OTHER_LINE),
+ singleLineDetailedTextBlock(2, OTHER_LINE),
new InProjectDuplicate(file1Component, singleLineTextBlock(OTHER_LINE))
),
duplication(
- singleLineTextBlock(OTHER_LINE + 80),
+ singleLineDetailedTextBlock(3, OTHER_LINE + 80),
new InnerDuplicate(singleLineTextBlock(LINE)), new InnerDuplicate(singleLineTextBlock(LINE + 10))
)
);
}
+ @Test
+ public void loads_never_consider_originals_from_batch_on_same_lines_as_the_equals() {
+ reportReader.putDuplications(
+ FILE_2_REF,
+ createDuplication(
+ singleLineTextRange(LINE),
+ createInnerDuplicate(LINE + 1), createInnerDuplicate(LINE + 2), createInProjectDuplicate(FILE_1_REF, LINE + 2)),
+ createDuplication(
+ singleLineTextRange(LINE),
+ createInnerDuplicate(LINE + 2), createInnerDuplicate(LINE + 3), createInProjectDuplicate(FILE_1_REF, LINE + 2))
+ );
+
+ underTest.execute();
+
+ Component file1Component = treeRootHolder.getComponentByRef(FILE_1_REF);
+ assertThat(duplicationRepository.getDuplications(FILE_2_REF)).containsOnly(
+ duplication(
+ singleLineDetailedTextBlock(1, LINE),
+ new InnerDuplicate(singleLineTextBlock(LINE + 1)), new InnerDuplicate(singleLineTextBlock(LINE + 2)),
+ new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 2))
+ ),
+ duplication(
+ singleLineDetailedTextBlock(2, LINE),
+ new InnerDuplicate(singleLineTextBlock(LINE + 2)), new InnerDuplicate(singleLineTextBlock(LINE + 3)),
+ new InProjectDuplicate(file1Component, singleLineTextBlock(LINE + 2))
+ )
+ );
+ }
+
@Test
public void loads_duplication_with_otherFileRef_throws_IAE_if_component_does_not_exist() {
int line = 2;
@@ -166,6 +196,10 @@ public class LoadDuplicationsFromReportStepTest {
return new TextBlock(line, line);
}
+ private DetailedTextBlock singleLineDetailedTextBlock(int id, int line) {
+ return new DetailedTextBlock(id, line, line);
+ }
+
private static BatchReport.Duplication createDuplication(BatchReport.TextRange original, BatchReport.Duplicate... duplicates) {
BatchReport.Duplication.Builder builder = BatchReport.Duplication.newBuilder()
.setOriginPosition(original);
--
2.39.5