@Override @Nonnull public Duplicate apply(@Nonnull ClonePart input) { return new CrossProjectDuplicate( input.getResourceId(), new TextBlock(input.getStartLine(), input.getEndLine())); } }
/** * Two groups are equal, if they have same length, same origins and contain same parts in same order. */ @Override public boolean equals(Object object) { if (!(object instanceof CloneGroup)) { return false; } CloneGroup another = (CloneGroup) object; if (another.cloneLength != cloneLength || parts.size() != another.parts.size()) { return false; } if (!originPart.equals(another.originPart)) { return false; } boolean result = true; for (int i = 0; i < parts.size(); i++) { result &= another.parts.get(i).equals(parts.get(i)); } return result; }
private void reportClones(BlocksGroup beginGroup, BlocksGroup endGroup, int cloneLength) { List<Block[]> pairs = beginGroup.pairs(endGroup, cloneLength); ClonePart origin = null; List<ClonePart> parts = new ArrayList<>(); for (int i = 0; i < pairs.size(); i++) { Block[] pair = pairs.get(i); Block firstBlock = pair[0]; Block lastBlock = pair[1]; ClonePart part = new ClonePart(firstBlock.getResourceId(), firstBlock.getIndexInFile(), firstBlock.getStartLine(), lastBlock.getEndLine()); if (originResourceId.equals(part.getResourceId())) { if (origin == null || part.getUnitStart() < origin.getUnitStart()) { origin = part; } } parts.add(part); } filter.add(CloneGroup.builder().setLength(cloneLength).setOrigin(origin).setParts(parts).build()); }
private void addDuplication(Component file, CloneGroup duplication) { ClonePart originPart = duplication.getOriginPart(); Iterable<Duplicate> duplicates = convertClonePartsToDuplicates(file, duplication); if (!Iterables.isEmpty(duplicates)) { duplicationRepository.add( file, new Duplication(new TextBlock(originPart.getStartLine(), originPart.getEndLine()), duplicates)); } }
blockBuilder.clear(); dupBuilder.setOriginPosition(ScannerReport.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 " + component + " for block at line " + originBlock.getStartLine() + ". Keep only the first " + MAX_CLONE_PART_PER_GROUP + " references."); break; String componentKey = duplicate.getResourceId(); if (!component.key().equals(componentKey)) { DefaultInputComponent sameProjectComponent = (DefaultInputComponent) componentStore.getByKey(componentKey); .setStartLine(duplicate.getStartLine()) .setEndLine(duplicate.getEndLine()) .build()) .build());
@Override public int compare(ClonePart o1, ClonePart o2) { return FastStringComparator.INSTANCE.compare(o1.getResourceId(), o2.getResourceId()); } };
@Test public void testDuplicationBetweenTwoFiles() throws IOException { File file1 = new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile1.java"); File file2 = new File("test-resources/org/sonar/duplications/cpd/CPDTest/CPDFile2.java"); addToIndex(file1); addToIndex(file2); List<CloneGroup> duplications = detect(file1); assertThat(duplications.size()).isEqualTo(1); CloneGroup duplication = duplications.get(0); assertThat(duplication.getOriginPart().getResourceId()).isEqualTo(file1.getAbsolutePath()); ClonePart part1 = new ClonePart(file1.getAbsolutePath(), 1, 18, 41); ClonePart part2 = new ClonePart(file2.getAbsolutePath(), 1, 18, 41); assertThat(duplication.getCloneParts()).containsOnly(part1, part2); assertThat(duplication.getLengthInUnits()).as("length in tokens").isEqualTo(115); }
private static int computeBlockAndLineCount(Iterable<CloneGroup> duplications, Set<Integer> duplicatedLines) { int duplicatedBlocks = 0; for (CloneGroup clone : duplications) { ClonePart origin = clone.getOriginPart(); for (ClonePart part : clone.getCloneParts()) { if (part.getResourceId().equals(origin.getResourceId())) { duplicatedBlocks++; for (int duplicatedLine = part.getStartLine(); duplicatedLine < part.getStartLine() + part.getLines(); duplicatedLine++) { duplicatedLines.add(duplicatedLine); } } } } return duplicatedBlocks; }
/** * Creates new part with specified resourceId and unitStart, and 0 for lineStart and lineEnd. */ private ClonePart newClonePart(String resourceId, int unitStart) { return new ClonePart(resourceId, unitStart, 0, 0); }
@Override public boolean apply(@Nonnull ClonePart input) { if (counter == MAX_CLONE_PART_PER_GROUP) { LOGGER.warn("Too many duplication references on file {} for block at line {}. Keeping only the first {} references.", file.getDbKey(), originPart.getStartLine(), MAX_CLONE_PART_PER_GROUP); } boolean res = counter <= MAX_CLONE_GROUP_PER_FILE; counter++; return res; } }
@Override public int compare(ClonePart o1, ClonePart o2) { int c = RESOURCE_ID_COMPARATOR.compare(o1, o2); if (c == 0) { return o1.getUnitStart() - o2.getUnitStart(); } return c; } };
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(); } }
@Test public void type1() { String fragment0 = source( "if (a >= b) {", " c = d + b; // Comment1", " d = d + 1;}", "else", " c = d - a; // Comment2"); String fragment1 = source( "if (a>=b) {", " // Comment1", " c=d+b;", " d=d+1;", "} else // Comment2", " c=d-a;"); List<CloneGroup> duplications = detect2(fragment0, fragment1); assertThat(duplications.size(), is(1)); ClonePart part = duplications.get(0).getOriginPart(); assertThat(part.getStartLine(), is(1)); assertThat(part.getEndLine(), is(5)); }
@Override public boolean apply(@Nonnull ClonePart part) { return !part.getResourceId().equals(componentKey); } }
private static ClonePart newClonePart(String resourceId, int unitStart) { return new ClonePart(resourceId, unitStart, 0, 0); }
@Override public boolean apply(@Nonnull ClonePart input) { if (counter == MAX_CLONE_PART_PER_GROUP) { LOGGER.warn("Too many duplication references on file {} for block at line {}. Keeping only the first {} references.", file.getKey(), originPart.getStartLine(), MAX_CLONE_PART_PER_GROUP); } boolean res = counter <= MAX_CLONE_GROUP_PER_FILE; counter++; return res; } }
/** * Compares two parts on inclusion. * part1 includes part2 if {@code (part1.resourceId == part2.resourceId) && (part1.unitStart <= part2.unitStart) && (part2.unitEnd <= part1.unitEnd)}. * * @return 0 if part1 includes part2, * 1 if resourceId of part1 is greater than resourceId of part2 or if unitStart of part1 is greater than unitStart of part2, * -1 in all other cases */ @Override public int compare(ClonePart part1, ClonePart part2) { int c = RESOURCE_ID_COMPARATOR.compare(part1, part2); if (c == 0) { if (part1.getUnitStart() <= part2.getUnitStart()) { if (part2.getUnitStart() + l2 <= part1.getUnitStart() + l1) { // part1 contains part2 return 0; } else { // SortedListsUtils#contains should continue search return -1; } } else { // unitStart of part1 is less than unitStart of part2 - SortedListsUtils#contains should stop search return 1; } } else { return c; } }
blockBuilder.clear(); dupBuilder.setOriginPosition(ScannerReport.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 " + component + " for block at line " + originBlock.getStartLine() + ". Keep only the first " + MAX_CLONE_PART_PER_GROUP + " references."); break; String componentKey = duplicate.getResourceId(); if (!component.key().equals(componentKey)) { DefaultInputComponent sameProjectComponent = (DefaultInputComponent) componentStore.getByKey(componentKey); .setStartLine(duplicate.getStartLine()) .setEndLine(duplicate.getEndLine()) .build()) .build());