import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.config.Settings;
+import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.duplication.BlockCache;
private final Settings settings;
private final BlockCache duplicationCache;
private final Project project;
+ private final FileLinesContextFactory contextFactory;
- public DefaultCpdEngine(@Nullable Project project, IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache) {
+ public DefaultCpdEngine(@Nullable Project project, IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache,
+ FileLinesContextFactory contextFactory) {
this.project = project;
this.indexFactory = indexFactory;
this.mappings = mappings;
this.fs = fs;
this.settings = settings;
this.duplicationCache = duplicationCache;
+ this.contextFactory = contextFactory;
}
- public DefaultCpdEngine(IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache) {
- this(null, indexFactory, mappings, fs, settings, duplicationCache);
+ public DefaultCpdEngine(IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache, FileLinesContextFactory contextFactory) {
+ this(null, indexFactory, mappings, fs, settings, duplicationCache, contextFactory);
}
@Override
throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- JavaCpdEngine.save(context, inputFile, filtered);
+ JavaCpdEngine.save(context, inputFile, filtered, contextFactory);
}
} finally {
executorService.shutdown();
import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
import org.sonar.api.config.Settings;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.duplication.DefaultDuplicationBuilder;
private final FileSystem fs;
private final Settings settings;
private final Project project;
+ private final FileLinesContextFactory contextFactory;
- public JavaCpdEngine(@Nullable Project project, IndexFactory indexFactory, FileSystem fs, Settings settings) {
+ public JavaCpdEngine(@Nullable Project project, IndexFactory indexFactory, FileSystem fs, Settings settings, FileLinesContextFactory contextFactory) {
this.project = project;
this.indexFactory = indexFactory;
this.fs = fs;
this.settings = settings;
+ this.contextFactory = contextFactory;
}
- public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) {
- this(null, indexFactory, fs, settings);
+ public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings, FileLinesContextFactory contextFactory) {
+ this(null, indexFactory, fs, settings, contextFactory);
}
@Override
throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- save(context, inputFile, clones);
+ save(context, inputFile, clones, contextFactory);
}
} finally {
executorService.shutdown();
}
}
- static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> duplications) {
+ static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> duplications,
+ FileLinesContextFactory contextFactory) {
if (duplications == null || Iterables.isEmpty(duplications)) {
return;
}
}
}
}
+ FileLinesContext linesContext = contextFactory.createFor(inputFile);
+ for (int i = 1; i <= inputFile.lines(); i++) {
+ linesContext.setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, i, duplicatedLines.contains(i) ? 1 : 0);
+ }
+ linesContext.save();
// Save
context.addMeasure(context.<Integer>measureBuilder()
.forMetric(CoreMetrics.DUPLICATED_FILES)
@Before
public void setUp() {
IndexFactory indexFactory = mock(IndexFactory.class);
- sonarEngine = new JavaCpdEngine(indexFactory, null, null);
- sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null, mock(BlockCache.class));
+ sonarEngine = new JavaCpdEngine(indexFactory, null, null, null);
+ sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null, mock(BlockCache.class), null);
settings = new Settings(new PropertyDefinitions(CpdPlugin.class));
DefaultFileSystem fs = new DefaultFileSystem();
@Before
public void init() {
settings = new Settings();
- engine = new DefaultCpdEngine(null, null, null, settings, mock(BlockCache.class));
+ engine = new DefaultCpdEngine(null, null, null, settings, mock(BlockCache.class), null);
}
@Test
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder;
import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.FileLinesContext;
+import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.batch.duplication.DefaultDuplicationBuilder;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.duplications.index.CloneGroup;
SensorContext context = mock(SensorContext.class);
DeprecatedDefaultInputFile inputFile;
private DefaultDuplicationBuilder duplicationBuilder;
+ private FileLinesContextFactory contextFactory;
+ private FileLinesContext linesContext;
@Before
public void before() throws IOException {
duplicationBuilder = spy(new DefaultDuplicationBuilder(inputFile, duplicationCache));
when(context.duplicationBuilder(any(InputFile.class))).thenReturn(duplicationBuilder);
inputFile.setFile(temp.newFile("Foo.java"));
+ contextFactory = mock(FileLinesContextFactory.class);
+ linesContext = mock(FileLinesContext.class);
+ when(contextFactory.createFor(inputFile)).thenReturn(linesContext);
}
@SuppressWarnings("unchecked")
@Test
public void testNothingToSave() {
- JavaCpdEngine.save(context, inputFile, null);
- JavaCpdEngine.save(context, inputFile, Collections.EMPTY_LIST);
+ JavaCpdEngine.save(context, inputFile, null, contextFactory);
+ JavaCpdEngine.save(context, inputFile, Collections.EMPTY_LIST, contextFactory);
verifyZeroInteractions(context);
}
@Test
public void testOneSimpleDuplicationBetweenTwoFiles() {
+ inputFile.setLines(300);
List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214)));
- JavaCpdEngine.save(context, inputFile, groups);
+ JavaCpdEngine.save(context, inputFile, groups, contextFactory);
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1).build());
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1).build());
inOrder.verify(duplicationBuilder).originBlock(5, 204);
inOrder.verify(duplicationBuilder).isDuplicatedBy("key2", 15, 214);
inOrder.verify(duplicationBuilder).done();
+
+ verify(linesContext).setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, 1, 0);
+ verify(linesContext).setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, 4, 0);
+ verify(linesContext).setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, 5, 1);
+ verify(linesContext).setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, 204, 1);
+ verify(linesContext).setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, 205, 0);
}
@Test
public void testDuplicationOnSameFile() throws Exception {
List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key1", 0, 215, 414)));
- JavaCpdEngine.save(context, inputFile, groups);
+ JavaCpdEngine.save(context, inputFile, groups, contextFactory);
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1).build());
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2).build());
@Test
public void testOneDuplicatedGroupInvolvingMoreThanTwoFiles() throws Exception {
List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214), new ClonePart("key3", 0, 25, 224)));
- JavaCpdEngine.save(context, inputFile, groups);
+ JavaCpdEngine.save(context, inputFile, groups, contextFactory);
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1).build());
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1).build());
List<CloneGroup> groups = Arrays.asList(
newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214)),
newCloneGroup(new ClonePart("key1", 0, 15, 214), new ClonePart("key3", 0, 15, 214)));
- JavaCpdEngine.save(context, inputFile, groups);
+ JavaCpdEngine.save(context, inputFile, groups, contextFactory);
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1).build());
verify(context).addMeasure(new DefaultMeasureBuilder().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2).build());
assertThat(result.inputFiles()).hasSize(2);
// 4 measures per file
- assertThat(result.measures()).hasSize(6);
+ assertThat(result.measures()).hasSize(8);
InputFile inputFile = result.inputFiles().get(0);
// One clone group
.setOptimizedBestValue(true)
.create();
+ /**
+ * @deprecated since 4.5. Internal storage of duplication is not an API. No more available on batch side.
+ */
+ @Deprecated
public static final String DUPLICATIONS_DATA_KEY = "duplications_data";
/**
* </duplications>
* </pre>
* </p>
+ * @deprecated since 4.5. Internal storage of duplication is not an API. No more available on batch side.
*/
+ @Deprecated
public static final Metric<String> DUPLICATIONS_DATA = new Metric.Builder(DUPLICATIONS_DATA_KEY, "Duplications details", Metric.ValueType.DATA)
.setDescription("Duplications details")
.setDirection(Metric.DIRECTION_NONE)
.setDeleteHistoricalData(true)
.create();
+ /**
+ * @since 4.5 used by dev cockpit.
+ */
+ @Beta
+ public static final String DUPLICATION_LINES_DATA_KEY = "comment_lines_data";
+
+ /**
+ * Information about duplication in file.
+ * Key-value pairs, where key - is a number of line, and value - is an indicator of whether line is duplicated somewhere (1) or not (0).
+ *
+ * @see org.sonar.api.measures.FileLinesContext
+ * @since 4.5 used by dev cockpit
+ */
+ @Beta
+ public static final Metric<String> DUPLICATION_LINES_DATA = new Metric.Builder(DUPLICATION_LINES_DATA_KEY, "duplication_lines_data", Metric.ValueType.DATA)
+ .setHidden(true)
+ .setDomain(DOMAIN_DUPLICATION)
+ .create();
+
// --------------------------------------------------------------------------------------------------------------------
//
// CODING RULES
@Test
public void read_metrics_from_class_reflection() {
List<Metric> metrics = CoreMetrics.getMetrics();
- assertThat(metrics).hasSize(153);
+ assertThat(metrics).hasSize(154);
assertThat(metrics).contains(CoreMetrics.NCLOC, CoreMetrics.DIRECTORIES);
}