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,
- FileLinesContextFactory contextFactory) {
+ public DefaultCpdEngine(@Nullable Project project, IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache) {
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, FileLinesContextFactory contextFactory) {
- this(null, indexFactory, mappings, fs, settings, duplicationCache, contextFactory);
+ public DefaultCpdEngine(IndexFactory indexFactory, CpdMappings mappings, FileSystem fs, Settings settings, BlockCache duplicationCache) {
+ this(null, indexFactory, mappings, fs, settings, duplicationCache);
}
@Override
throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- JavaCpdEngine.save(context, inputFile, filtered, contextFactory);
+ JavaCpdEngine.save(context, inputFile, filtered);
}
} finally {
executorService.shutdown();
import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplicationBuilder;
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.KeyValueFormat;
import org.sonar.api.utils.SonarException;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.BlockChunker;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
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, FileLinesContextFactory contextFactory) {
+ public JavaCpdEngine(@Nullable Project project, IndexFactory indexFactory, FileSystem fs, Settings settings) {
this.project = project;
this.indexFactory = indexFactory;
this.fs = fs;
this.settings = settings;
- this.contextFactory = contextFactory;
}
- public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings, FileLinesContextFactory contextFactory) {
- this(null, indexFactory, fs, settings, contextFactory);
+ public JavaCpdEngine(IndexFactory indexFactory, FileSystem fs, Settings settings) {
+ this(null, indexFactory, fs, settings);
}
@Override
throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- save(context, inputFile, clones, contextFactory);
+ save(context, inputFile, clones);
}
} finally {
executorService.shutdown();
}
}
- static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> duplications,
- FileLinesContextFactory contextFactory) {
+ static void save(org.sonar.api.batch.sensor.SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> duplications) {
if (duplications == null || Iterables.isEmpty(duplications)) {
return;
}
Set<Integer> duplicatedLines = new HashSet<Integer>();
int duplicatedBlocks = computeBlockAndLineCount(duplications, duplicatedLines);
- FileLinesContext linesContext = contextFactory.createFor(inputFile);
+ Map<Integer, Integer> duplicationByLine = new HashMap<Integer, Integer>();
for (int i = 1; i <= inputFile.lines(); i++) {
- linesContext.setIntValue(CoreMetrics.DUPLICATION_LINES_DATA_KEY, i, duplicatedLines.contains(i) ? 1 : 0);
+ duplicationByLine.put(i, duplicatedLines.contains(i) ? 1 : 0);
}
- linesContext.save();
+ ((DefaultMeasure<String>) context.<String>newMeasure()
+ .forMetric(CoreMetrics.DUPLICATION_LINES_DATA)
+ .onFile(inputFile)
+ .withValue(KeyValueFormat.format(duplicationByLine)))
+ .setFromCore()
+ .save();
// Save
context.<Integer>newMeasure()
.forMetric(CoreMetrics.DUPLICATED_FILES)
@Before
public void setUp() {
IndexFactory indexFactory = mock(IndexFactory.class);
- sonarEngine = new JavaCpdEngine(indexFactory, null, null, null);
- sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null, mock(BlockCache.class), null);
+ sonarEngine = new JavaCpdEngine(indexFactory, null, null);
+ sonarBridgeEngine = new DefaultCpdEngine(indexFactory, new CpdMappings(), null, null, mock(BlockCache.class));
settings = new Settings(new PropertyDefinitions(CpdPlugin.class));
DefaultFileSystem fs = new DefaultFileSystem();
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
-import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.batch.duplication.BlockCache;
@Before
public void init() {
settings = new Settings();
- engine = new DefaultCpdEngine(null, null, null, settings, mock(BlockCache.class), null);
+ engine = new DefaultCpdEngine(null, null, null, settings, mock(BlockCache.class));
}
@Test
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.FileLinesContext;
-import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.duplications.index.CloneGroup;
import org.sonar.duplications.index.ClonePart;
SensorContext context = mock(SensorContext.class);
DeprecatedDefaultInputFile inputFile;
private DefaultDuplicationBuilder duplicationBuilder;
- private FileLinesContextFactory contextFactory;
- private FileLinesContext linesContext;
private SensorStorage storage = mock(SensorStorage.class);
@Before
duplicationBuilder = spy(new DefaultDuplicationBuilder(inputFile));
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, contextFactory);
- JavaCpdEngine.save(context, inputFile, Collections.EMPTY_LIST, contextFactory);
+ JavaCpdEngine.save(context, inputFile, null);
+ JavaCpdEngine.save(context, inputFile, Collections.EMPTY_LIST);
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, contextFactory);
+ inputFile.setLines(5);
+ List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 2, 4), new ClonePart("key2", 0, 15, 17)));
+ JavaCpdEngine.save(context, inputFile, groups);
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1));
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1));
- verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(200));
+ verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_LINES).onFile(inputFile).withValue(3));
+ verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATION_LINES_DATA).onFile(inputFile).withValue("1=0;2=1;3=1;4=1;5=0"));
InOrder inOrder = Mockito.inOrder(duplicationBuilder);
- inOrder.verify(duplicationBuilder).originBlock(5, 204);
- inOrder.verify(duplicationBuilder).isDuplicatedBy("key2", 15, 214);
+ inOrder.verify(duplicationBuilder).originBlock(2, 4);
+ inOrder.verify(duplicationBuilder).isDuplicatedBy("key2", 15, 17);
inOrder.verify(duplicationBuilder).build();
-
- 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, contextFactory);
+ JavaCpdEngine.save(context, inputFile, groups);
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1));
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2));
@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, contextFactory);
+ JavaCpdEngine.save(context, inputFile, groups);
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1));
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(1));
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, contextFactory);
+ JavaCpdEngine.save(context, inputFile, groups);
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_FILES).onFile(inputFile).withValue(1));
verify(storage).store(new DefaultMeasure().forMetric(CoreMetrics.DUPLICATED_BLOCKS).onFile(inputFile).withValue(2));
import com.google.common.collect.Maps;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.SensorStorage;
import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.measures.FileLinesContext;
import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.utils.KeyValueFormat.Converter;
-import org.sonar.core.component.ComponentKeys;
import java.util.Map;
public class DefaultFileLinesContext implements FileLinesContext {
- private final MeasureCache measureCache;
+ private final SensorStorage sensorStorage;
private final InputFile inputFile;
/**
* metric key -> line -> value
*/
private final Map<String, Map<Integer, Object>> map = Maps.newHashMap();
- private String projectKey;
private MetricFinder metricFinder;
- public DefaultFileLinesContext(MetricFinder metricFinder, MeasureCache measureCache, String projectKey, InputFile inputFile) {
+ public DefaultFileLinesContext(MetricFinder metricFinder, SensorStorage sensorStorage, InputFile inputFile) {
this.metricFinder = metricFinder;
- this.projectKey = projectKey;
- Preconditions.checkNotNull(measureCache);
- this.measureCache = measureCache;
+ this.sensorStorage = sensorStorage;
this.inputFile = inputFile;
}
}
public Integer getIntValue(String metricKey, int line) {
- Preconditions.checkNotNull(metricKey);
- Preconditions.checkArgument(line > 0);
-
- Map lines = map.get(metricKey);
- if (lines == null) {
- // not in memory, so load
- lines = loadData(metricKey, KeyValueFormat.newIntegerConverter());
- map.put(metricKey, lines);
- }
- return (Integer) lines.get(line);
+ throw new UnsupportedOperationException();
}
public void setStringValue(String metricKey, int line, String value) {
}
public String getStringValue(String metricKey, int line) {
- Preconditions.checkNotNull(metricKey);
- Preconditions.checkArgument(line > 0);
-
- Map lines = map.get(metricKey);
- if (lines == null) {
- // not in memory, so load
- lines = loadData(metricKey, KeyValueFormat.newStringConverter());
- map.put(metricKey, lines);
- }
- return (String) lines.get(line);
+ throw new UnsupportedOperationException();
}
private Map<Integer, Object> getOrCreateLines(String metricKey) {
throw new IllegalStateException("Unable to find metric with key: " + metricKey);
}
Map<Integer, Object> lines = entry.getValue();
- if (shouldSave(lines)) {
- String data = KeyValueFormat.format(lines);
- measureCache.put(projectKey, ComponentKeys.createEffectiveKey(projectKey, inputFile), new DefaultMeasure<String>()
- .forMetric(metric)
- .onFile(inputFile)
- .withValue(data));
- entry.setValue(ImmutableMap.copyOf(lines));
- }
- }
- }
-
- private Map loadData(String metricKey, Converter converter) {
- Measure measure = measureCache.byMetric(projectKey, ComponentKeys.createEffectiveKey(projectKey, inputFile), metricKey);
- if (measure == null) {
- // no such measure
- return ImmutableMap.of();
+ String data = KeyValueFormat.format(lines);
+ new DefaultMeasure<String>(sensorStorage)
+ .forMetric(metric)
+ .onFile(inputFile)
+ .withValue(data)
+ .save();
+ entry.setValue(ImmutableMap.copyOf(lines));
}
- return ImmutableMap.copyOf(KeyValueFormat.parse((String) measure.value(), KeyValueFormat.newIntegerConverter(), converter));
- }
-
- /**
- * Checks that measure was not saved.
- *
- * @see #loadData(String, Converter)
- * @see #save()
- */
- private boolean shouldSave(Map<Integer, Object> lines) {
- return !(lines instanceof ImmutableMap);
}
@Override
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.SensorStorage;
import org.sonar.api.measures.FileLinesContext;
import org.sonar.api.measures.FileLinesContextFactory;
import org.sonar.api.resources.Resource;
public class DefaultFileLinesContextFactory implements FileLinesContextFactory {
- private final MeasureCache measureCache;
+ private final SensorStorage sensorStorage;
private final MetricFinder metricFinder;
private final ProjectDefinition def;
- private InputPathCache fileCache;
+ private final InputPathCache fileCache;
- public DefaultFileLinesContextFactory(InputPathCache fileCache, FileSystem fs, MetricFinder metricFinder, MeasureCache measureCache,
+ public DefaultFileLinesContextFactory(InputPathCache fileCache, FileSystem fs, MetricFinder metricFinder, SensorStorage sensorStorage,
ProjectDefinition def) {
this.fileCache = fileCache;
this.metricFinder = metricFinder;
- this.measureCache = measureCache;
+ this.sensorStorage = sensorStorage;
this.def = def;
}
if (fileCache.getFile(def.getKey(), inputFile.relativePath()) == null) {
throw new IllegalStateException("InputFile is not indexed: " + inputFile);
}
- return new DefaultFileLinesContext(metricFinder, measureCache, def.getKey(), inputFile);
+ return new DefaultFileLinesContext(metricFinder, sensorStorage, inputFile);
}
}
*/
package org.sonar.api.measures;
-
/**
- * Provides access to measures for the lines of file.
+ * Provides facility to store measures for the lines of file.
* Examples:
* <ul>
* <li>line 1 is a line of code</li>
/**
* @return value, or null if no such metric for given line
+ * @deprecated since 5.0 sensors should not read data
*/
+ @Deprecated
Integer getIntValue(String metricKey, int line);
/**
/**
* @return value, or null if no such metric for given line
+ * @deprecated since 5.0 sensors should not read data
*/
+ @Deprecated
String getStringValue(String metricKey, int line);
/**