You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LoadDuplicationsFromReportStep.java 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.ce.task.projectanalysis.step;
  21. import java.util.function.Function;
  22. import java.util.stream.Collectors;
  23. import javax.annotation.Nonnull;
  24. import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
  25. import org.sonar.ce.task.projectanalysis.batch.BatchReportReader;
  26. import org.sonar.ce.task.projectanalysis.component.Component;
  27. import org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit;
  28. import org.sonar.ce.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
  29. import org.sonar.ce.task.projectanalysis.component.TreeRootHolder;
  30. import org.sonar.ce.task.projectanalysis.component.TypeAwareVisitorAdapter;
  31. import org.sonar.ce.task.projectanalysis.duplication.DetailedTextBlock;
  32. import org.sonar.ce.task.projectanalysis.duplication.Duplicate;
  33. import org.sonar.ce.task.projectanalysis.duplication.Duplication;
  34. import org.sonar.ce.task.projectanalysis.duplication.DuplicationRepository;
  35. import org.sonar.ce.task.projectanalysis.duplication.InExtendedProjectDuplicate;
  36. import org.sonar.ce.task.projectanalysis.duplication.InProjectDuplicate;
  37. import org.sonar.ce.task.projectanalysis.duplication.InnerDuplicate;
  38. import org.sonar.ce.task.projectanalysis.duplication.TextBlock;
  39. import org.sonar.ce.task.step.ComputationStep;
  40. import org.sonar.core.util.CloseableIterator;
  41. import org.sonar.scanner.protocol.output.ScannerReport;
  42. import static com.google.common.base.Preconditions.checkArgument;
  43. /**
  44. * Loads duplication information from the report and loads them into the {@link DuplicationRepository}.
  45. */
  46. public class LoadDuplicationsFromReportStep implements ComputationStep {
  47. private final TreeRootHolder treeRootHolder;
  48. private final AnalysisMetadataHolder analysisMetadataHolder;
  49. private final BatchReportReader batchReportReader;
  50. private final DuplicationRepository duplicationRepository;
  51. public LoadDuplicationsFromReportStep(TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder, BatchReportReader batchReportReader,
  52. DuplicationRepository duplicationRepository) {
  53. this.treeRootHolder = treeRootHolder;
  54. this.analysisMetadataHolder = analysisMetadataHolder;
  55. this.batchReportReader = batchReportReader;
  56. this.duplicationRepository = duplicationRepository;
  57. }
  58. @Override
  59. public String getDescription() {
  60. return "Load duplications";
  61. }
  62. @Override
  63. public void execute(ComputationStep.Context context) {
  64. DuplicationVisitor visitor = new DuplicationVisitor();
  65. new DepthTraversalTypeAwareCrawler(visitor).visit(treeRootHolder.getReportTreeRoot());
  66. context.getStatistics().add("duplications", visitor.count);
  67. }
  68. private class BatchDuplicateToCeDuplicate implements Function<ScannerReport.Duplicate, Duplicate> {
  69. private final Component file;
  70. private BatchDuplicateToCeDuplicate(Component file) {
  71. this.file = file;
  72. }
  73. @Override
  74. @Nonnull
  75. public Duplicate apply(@Nonnull ScannerReport.Duplicate input) {
  76. if (input.getOtherFileRef() != 0) {
  77. checkArgument(input.getOtherFileRef() != file.getReportAttributes().getRef(), "file and otherFile references can not be the same");
  78. Component otherComponent = treeRootHolder.getReportTreeComponentByRef(input.getOtherFileRef());
  79. if (analysisMetadataHolder.isPullRequest() && otherComponent.getStatus() == Component.Status.SAME) {
  80. return new InExtendedProjectDuplicate(otherComponent, convert(input.getRange()));
  81. } else {
  82. return new InProjectDuplicate(otherComponent, convert(input.getRange()));
  83. }
  84. }
  85. return new InnerDuplicate(convert(input.getRange()));
  86. }
  87. private TextBlock convert(ScannerReport.TextRange textRange) {
  88. return new TextBlock(textRange.getStartLine(), textRange.getEndLine());
  89. }
  90. }
  91. private class DuplicationVisitor extends TypeAwareVisitorAdapter {
  92. private int count = 0;
  93. private DuplicationVisitor() {
  94. super(CrawlerDepthLimit.FILE, Order.POST_ORDER);
  95. }
  96. @Override
  97. public void visitFile(Component file) {
  98. try (CloseableIterator<ScannerReport.Duplication> duplications = batchReportReader.readComponentDuplications(file.getReportAttributes().getRef())) {
  99. int idGenerator = 1;
  100. while (duplications.hasNext()) {
  101. loadDuplications(file, duplications.next(), idGenerator);
  102. idGenerator++;
  103. count++;
  104. }
  105. }
  106. }
  107. private void loadDuplications(Component file, ScannerReport.Duplication duplication, int id) {
  108. duplicationRepository.add(file,
  109. new Duplication(
  110. convert(duplication.getOriginPosition(), id),
  111. duplication.getDuplicateList().stream()
  112. .map(new BatchDuplicateToCeDuplicate(file)).collect(Collectors.toList())));
  113. }
  114. private DetailedTextBlock convert(ScannerReport.TextRange textRange, int id) {
  115. return new DetailedTextBlock(id, textRange.getStartLine(), textRange.getEndLine());
  116. }
  117. }
  118. }