import org.sonar.api.batch.CpdMapping;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.*;
+import org.sonar.duplications.DuplicationPredicates;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm;
import org.sonar.duplications.index.CloneGroup;
}
// Detect
- final int minimumTokens = PmdEngine.getMinimumTokens(project);
- Predicate<CloneGroup> minimumTokensPredicate = new Predicate<CloneGroup>() {
- public boolean apply(CloneGroup input) {
- return input.getLengthInUnits() >= minimumTokens;
- }
- };
+ Predicate<CloneGroup> minimumTokensPredicate = DuplicationPredicates.numberOfUnitsNotLessThan(PmdEngine.getMinimumTokens(project));
for (InputFile inputFile : inputFiles) {
Resource resource = mapping.createResource(inputFile.getFile(), fileSystem.getSourceDirs());
*/
package org.sonar.plugins.cpd;
+import com.google.common.collect.Iterables;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
if (inputFiles.isEmpty()) {
return;
}
+ SonarDuplicationsIndex index = createIndex(project, inputFiles);
+ detect(index, context, project, inputFiles);
+ }
- // Create index
+ private SonarDuplicationsIndex createIndex(Project project, List<InputFile> inputFiles) {
final SonarDuplicationsIndex index = indexFactory.create(project);
TokenChunker tokenChunker = JavaTokenProducer.build();
index.insert(resource, blocks);
}
- // Detect
+ return index;
+ }
+
+ private void detect(SonarDuplicationsIndex index, SensorContext context, Project project, List<InputFile> inputFiles) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
for (InputFile inputFile : inputFiles) {
return JavaFile.fromRelativePath(inputFile.getRelativePath(), false);
}
- static void save(SensorContext context, Resource resource, Iterable<CloneGroup> clones) {
- if (clones == null || !clones.iterator().hasNext()) {
+ static void save(SensorContext context, Resource resource, Iterable<CloneGroup> duplications) {
+ if (Iterables.isEmpty(duplications)) {
return;
}
// Calculate number of lines and blocks
Set<Integer> duplicatedLines = new HashSet<Integer>();
double duplicatedBlocks = 0;
- for (CloneGroup clone : clones) {
+ for (CloneGroup clone : duplications) {
ClonePart origin = clone.getOriginPart();
for (ClonePart part : clone.getCloneParts()) {
if (part.getResourceId().equals(origin.getResourceId())) {
}
}
}
- // Build XML
+ // Save
+ context.saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1.0);
+ context.saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, (double) duplicatedLines.size());
+ context.saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, duplicatedBlocks);
+ context.saveMeasure(resource, new Measure(CoreMetrics.DUPLICATIONS_DATA, toXml(duplications)));
+ }
+
+ private static String toXml(Iterable<CloneGroup> duplications) {
StringBuilder xml = new StringBuilder();
xml.append("<duplications>");
- for (CloneGroup clone : clones) {
+ for (CloneGroup duplication : duplications) {
xml.append("<g>");
- for (ClonePart part : clone.getCloneParts()) {
+ for (ClonePart part : duplication.getCloneParts()) {
xml.append("<b s=\"").append(part.getStartLine())
.append("\" l=\"").append(part.getLines())
.append("\" r=\"").append(part.getResourceId())
xml.append("</g>");
}
xml.append("</duplications>");
- // Save
- context.saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d);
- context.saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, (double) duplicatedLines.size());
- context.saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, duplicatedBlocks);
- context.saveMeasure(resource, new Measure(CoreMetrics.DUPLICATIONS_DATA, xml.toString()));
+ return xml.toString();
}
}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.duplications;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import org.sonar.duplications.index.CloneGroup;
+
+@Beta
+public final class DuplicationPredicates {
+
+ private DuplicationPredicates() {
+ }
+
+ public static Predicate<CloneGroup> numberOfUnitsNotLessThan(int min) {
+ return new NumberOfUnitsNotLessThan(min);
+ }
+
+ private static class NumberOfUnitsNotLessThan implements Predicate<CloneGroup> {
+ private final int min;
+
+ public NumberOfUnitsNotLessThan(int min) {
+ this.min = min;
+ }
+
+ public boolean apply(CloneGroup input) {
+ return input.getLengthInUnits() >= min;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar 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.
+ *
+ * Sonar 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 Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.duplications;
+
+import com.google.common.base.Predicate;
+import org.junit.Test;
+import org.sonar.duplications.index.CloneGroup;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class DuplicationPredicatesTest {
+
+ @Test
+ public void testNumberOfUnitsNotLessThan() {
+ Predicate<CloneGroup> predicate = DuplicationPredicates.numberOfUnitsNotLessThan(5);
+ assertThat(predicate.apply(CloneGroup.builder().setLengthInUnits(6).build()), is(true));
+ assertThat(predicate.apply(CloneGroup.builder().setLengthInUnits(5).build()), is(true));
+ assertThat(predicate.apply(CloneGroup.builder().setLengthInUnits(4).build()), is(false));
+ }
+
+}