]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6990 support repeated original-duplicate paars from the batch
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 16 Dec 2015 10:54:58 +0000 (11:54 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 17 Dec 2015 09:44:05 +0000 (10:44 +0100)
server/sonar-server/src/main/java/org/sonar/server/computation/duplication/DetailedTextBlock.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/duplication/TextBlock.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadDuplicationsFromReportStepTest.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 (file)
index 0000000..a096335
--- /dev/null
@@ -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:
+ * <ul>
+ *   <li>some language plugins are able to multiple duplication for the same textblock but with a
+ * different starting and/or ending offset</li>
+ *   <li>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</li>
+ * </ul>,
+ * 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);
+  }
+}
index e317e7c9225f7d3efb2e077fd6165acbb4f6bd14..43a24c871e416d8caa6aeb946f8f2419771cba75 100644 (file)
@@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkArgument;
  * same start line, by smallest size (ie. lowest end line).
  * </p>
  */
-public final class TextBlock implements Comparable<TextBlock> {
+public class TextBlock implements Comparable<TextBlock> {
   private final int start;
   private final int end;
 
index 3006266bfc2828cd6423fb8b35c39b7b98587282..6d0927f9f713a878820b7720d48c8383d591185e 100644 (file)
@@ -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<BatchReport.Duplication> 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());
+  }
 }
index 5515924be2e04ea80de2ec2b1795cc905c666c82..b1423876afd7666ad007694de301de34b1474745 100644 (file)
@@ -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);