aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java52
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java78
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java36
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java10
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java2
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java74
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java44
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java19
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/CpdMapping.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java13
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java3
13 files changed, 198 insertions, 151 deletions
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
index 28604e52bc2..aa4bf2b4da6 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarBridgeEngine.java
@@ -30,10 +30,11 @@ import org.sonar.api.batch.SensorContext;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
+import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.api.utils.SonarException;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.duplications.DuplicationPredicates;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.index.CloneGroup;
@@ -41,10 +42,13 @@ import org.sonar.duplications.internal.pmd.TokenizerBridge;
import org.sonar.plugins.cpd.index.IndexFactory;
import org.sonar.plugins.cpd.index.SonarDuplicationsIndex;
-import java.io.File;
import java.util.Collection;
import java.util.List;
-import java.util.concurrent.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class SonarBridgeEngine extends CpdEngine {
@@ -57,17 +61,17 @@ public class SonarBridgeEngine extends CpdEngine {
private final IndexFactory indexFactory;
private final CpdMapping[] mappings;
- private final ModuleFileSystem fileSystem;
+ private final DefaultModuleFileSystem fileSystem;
private final Settings settings;
- public SonarBridgeEngine(IndexFactory indexFactory, CpdMapping[] mappings, ModuleFileSystem moduleFileSystem, Settings settings) {
+ public SonarBridgeEngine(IndexFactory indexFactory, CpdMapping[] mappings, DefaultModuleFileSystem moduleFileSystem, Settings settings) {
this.indexFactory = indexFactory;
this.mappings = mappings;
this.fileSystem = moduleFileSystem;
this.settings = settings;
}
- public SonarBridgeEngine(IndexFactory indexFactory, ModuleFileSystem moduleFileSystem, Settings settings) {
+ public SonarBridgeEngine(IndexFactory indexFactory, DefaultModuleFileSystem moduleFileSystem, Settings settings) {
this(indexFactory, new CpdMapping[0], moduleFileSystem, settings);
}
@@ -80,8 +84,9 @@ public class SonarBridgeEngine extends CpdEngine {
public void analyse(Project project, SensorContext context) {
String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS);
logExclusions(cpdExclusions, LOG);
- List<File> sourceFiles = fileSystem.files(FileQuery.onSource().onLanguage(project.getLanguageKey()).withExclusions(cpdExclusions));
- if (sourceFiles.isEmpty()) {
+ Iterable<InputFile> sourceFiles = fileSystem.inputFiles(FileQuery.onSource().onLanguage(project.getLanguageKey())
+ .withExclusions(cpdExclusions));
+ if (!sourceFiles.iterator().hasNext()) {
return;
}
@@ -91,12 +96,11 @@ public class SonarBridgeEngine extends CpdEngine {
SonarDuplicationsIndex index = indexFactory.create(project);
TokenizerBridge bridge = new TokenizerBridge(mapping.getTokenizer(), fileSystem.sourceCharset().name(), getBlockSize(project));
- for (File file : sourceFiles) {
- LOG.debug("Populating index from {}", file);
- Resource resource = mapping.createResource(file, fileSystem.sourceDirs());
- String resourceId = SonarEngine.getFullKey(project, resource);
- List<Block> blocks = bridge.chunk(resourceId, file);
- index.insert(resource, blocks);
+ for (InputFile inputFile : sourceFiles) {
+ LOG.debug("Populating index from {}", inputFile);
+ String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY);
+ List<Block> blocks = bridge.chunk(resourceEffectiveKey, inputFile.file());
+ index.insert(inputFile, blocks);
}
// Detect
@@ -104,12 +108,10 @@ public class SonarBridgeEngine extends CpdEngine {
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
- for (File file : sourceFiles) {
- LOG.debug("Detection of duplications for {}", file);
- Resource resource = mapping.createResource(file, fileSystem.sourceDirs());
- String resourceKey = SonarEngine.getFullKey(project, resource);
-
- Collection<Block> fileBlocks = index.getByResource(resource, resourceKey);
+ for (InputFile inputFile : sourceFiles) {
+ LOG.debug("Detection of duplications for {}", inputFile);
+ String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY);
+ Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
Iterable<CloneGroup> filtered;
try {
@@ -117,14 +119,14 @@ public class SonarBridgeEngine extends CpdEngine {
filtered = Iterables.filter(duplications, minimumTokensPredicate);
} catch (TimeoutException e) {
filtered = null;
- LOG.warn("Timeout during detection of duplications for " + file, e);
+ LOG.warn("Timeout during detection of duplications for " + inputFile, e);
} catch (InterruptedException e) {
- throw new SonarException("Fail during detection of duplication for "+ file, e);
+ throw new SonarException("Fail during detection of duplication for " + inputFile, e);
} catch (ExecutionException e) {
- throw new SonarException("Fail during detection of duplication for "+ file, e);
+ throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- SonarEngine.save(context, resource, filtered);
+ SonarEngine.save(context, inputFile, filtered);
}
} finally {
executorService.shutdown();
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
index d92157f3e11..d4d545d34d0 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
@@ -28,19 +28,17 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.config.Settings;
-import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.resources.Java;
-import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
import org.sonar.api.scan.filesystem.FileQuery;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.scan.filesystem.internal.DefaultInputFile;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.api.utils.SonarException;
+import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.BlockChunker;
import org.sonar.duplications.detector.suffixtree.SuffixTreeCloneDetectionAlgorithm;
@@ -57,7 +55,6 @@ import org.sonar.plugins.cpd.index.SonarDuplicationsIndex;
import javax.annotation.Nullable;
-import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
@@ -85,14 +82,12 @@ public class SonarEngine extends CpdEngine {
private static final int TIMEOUT = 5 * 60;
private final IndexFactory indexFactory;
- private final ModuleFileSystem fileSystem;
- private final PathResolver pathResolver;
+ private final DefaultModuleFileSystem fileSystem;
private final Settings settings;
- public SonarEngine(IndexFactory indexFactory, ModuleFileSystem moduleFileSystem, PathResolver pathResolver, Settings settings) {
+ public SonarEngine(IndexFactory indexFactory, DefaultModuleFileSystem moduleFileSystem, Settings settings) {
this.indexFactory = indexFactory;
this.fileSystem = moduleFileSystem;
- this.pathResolver = pathResolver;
this.settings = settings;
}
@@ -101,80 +96,70 @@ public class SonarEngine extends CpdEngine {
return Java.KEY.equals(language.getKey());
}
- static String getFullKey(Project project, Resource resource) {
- return new StringBuilder(ResourceModel.KEY_SIZE)
- .append(project.getKey())
- .append(':')
- .append(resource.getKey())
- .toString();
- }
-
@Override
public void analyse(Project project, SensorContext context) {
String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS);
logExclusions(cpdExclusions, LOG);
- List<File> sourceFiles = fileSystem.files(FileQuery.onSource().onLanguage(project.getLanguageKey()).withExclusions(cpdExclusions));
- if (sourceFiles.isEmpty()) {
+ Iterable<InputFile> sourceFiles = fileSystem.inputFiles(FileQuery.onSource().onLanguage(project.getLanguageKey()).withExclusions(cpdExclusions));
+ if (!sourceFiles.iterator().hasNext()) {
return;
}
SonarDuplicationsIndex index = createIndex(project, sourceFiles);
detect(index, context, project, sourceFiles);
}
- private SonarDuplicationsIndex createIndex(Project project, List<File> sourceFiles) {
+ private SonarDuplicationsIndex createIndex(Project project, Iterable<InputFile> sourceFiles) {
final SonarDuplicationsIndex index = indexFactory.create(project);
TokenChunker tokenChunker = JavaTokenProducer.build();
StatementChunker statementChunker = JavaStatementBuilder.build();
BlockChunker blockChunker = new BlockChunker(BLOCK_SIZE);
- for (File file : sourceFiles) {
- LOG.debug("Populating index from {}", file);
- Resource resource = getResource(file);
- String resourceKey = getFullKey(project, resource);
+ for (InputFile inputFile : sourceFiles) {
+ LOG.debug("Populating index from {}", inputFile);
+ String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY);
List<Statement> statements;
Reader reader = null;
try {
- reader = new InputStreamReader(new FileInputStream(file), fileSystem.sourceCharset());
+ reader = new InputStreamReader(new FileInputStream(inputFile.file()), fileSystem.sourceCharset());
statements = statementChunker.chunk(tokenChunker.chunk(reader));
} catch (FileNotFoundException e) {
- throw new SonarException("Cannot find file " + file, e);
+ throw new SonarException("Cannot find file " + inputFile.file(), e);
} finally {
IOUtils.closeQuietly(reader);
}
- List<Block> blocks = blockChunker.chunk(resourceKey, statements);
- index.insert(resource, blocks);
+ List<Block> blocks = blockChunker.chunk(resourceEffectiveKey, statements);
+ index.insert(inputFile, blocks);
}
return index;
}
- private void detect(SonarDuplicationsIndex index, SensorContext context, Project project, List<File> sourceFiles) {
+ private void detect(SonarDuplicationsIndex index, SensorContext context, Project project, Iterable<InputFile> sourceFiles) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
try {
- for (File file : sourceFiles) {
- LOG.debug("Detection of duplications for {}", file);
- Resource resource = getResource(file);
- String resourceKey = getFullKey(project, resource);
+ for (InputFile inputFile : sourceFiles) {
+ LOG.debug("Detection of duplications for {}", inputFile);
+ String resourceEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY);
- Collection<Block> fileBlocks = index.getByResource(resource, resourceKey);
+ Collection<Block> fileBlocks = index.getByInputFile(inputFile, resourceEffectiveKey);
List<CloneGroup> clones;
try {
clones = executorService.submit(new Task(index, fileBlocks)).get(TIMEOUT, TimeUnit.SECONDS);
} catch (TimeoutException e) {
clones = null;
- LOG.warn("Timeout during detection of duplications for " + file, e);
+ LOG.warn("Timeout during detection of duplications for " + inputFile, e);
} catch (InterruptedException e) {
- throw new SonarException("Fail during detection of duplication for " + file, e);
+ throw new SonarException("Fail during detection of duplication for " + inputFile, e);
} catch (ExecutionException e) {
- throw new SonarException("Fail during detection of duplication for " + file, e);
+ throw new SonarException("Fail during detection of duplication for " + inputFile, e);
}
- save(context, resource, clones);
+ save(context, inputFile, clones);
}
} finally {
executorService.shutdown();
@@ -195,12 +180,7 @@ public class SonarEngine extends CpdEngine {
}
}
- protected Resource getResource(File file) {
- String relativePathFromBaseDir = pathResolver.relativePath(fileSystem.baseDir(), file);
- return JavaFile.create(relativePathFromBaseDir, "unused", false);
- }
-
- static void save(SensorContext context, Resource resource, @Nullable Iterable<CloneGroup> duplications) {
+ static void save(SensorContext context, InputFile inputFile, @Nullable Iterable<CloneGroup> duplications) {
if (duplications == null || Iterables.isEmpty(duplications)) {
return;
}
@@ -219,13 +199,13 @@ public class SonarEngine extends CpdEngine {
}
}
// 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(inputFile, CoreMetrics.DUPLICATED_FILES, 1.0);
+ context.saveMeasure(inputFile, CoreMetrics.DUPLICATED_LINES, (double) duplicatedLines.size());
+ context.saveMeasure(inputFile, CoreMetrics.DUPLICATED_BLOCKS, duplicatedBlocks);
Measure data = new Measure(CoreMetrics.DUPLICATIONS_DATA, toXml(duplications))
.setPersistenceMode(PersistenceMode.DATABASE);
- context.saveMeasure(resource, data);
+ context.saveMeasure(inputFile, data);
}
private static String toXml(Iterable<CloneGroup> duplications) {
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java
index 9ea3a65ba38..2ef72e7cae6 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbDuplicationsIndex.java
@@ -23,7 +23,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.batch.index.ResourcePersister;
import org.sonar.core.duplication.DuplicationDao;
import org.sonar.core.duplication.DuplicationUnitDto;
@@ -56,12 +56,12 @@ public class DbDuplicationsIndex {
this.languageKey = currentProject.getLanguageKey();
}
- int getSnapshotIdFor(Resource resource) {
- return resourcePersister.getSnapshotOrFail(resource).getId();
+ int getSnapshotIdFor(InputFile inputFile) {
+ return resourcePersister.getSnapshotOrFail(inputFile).getId();
}
- public void prepareCache(Resource resource) {
- int resourceSnapshotId = getSnapshotIdFor(resource);
+ public void prepareCache(InputFile inputFile) {
+ int resourceSnapshotId = getSnapshotIdFor(inputFile);
List<DuplicationUnitDto> units = dao.selectCandidates(resourceSnapshotId, lastSnapshotId, languageKey);
cache.clear();
// TODO Godin: maybe remove conversion of units to blocks?
@@ -74,11 +74,11 @@ public class DbDuplicationsIndex {
// TODO Godin: in fact we could work directly with id instead of key - this will allow to decrease memory consumption
Block block = Block.builder()
- .setResourceId(resourceKey)
- .setBlockHash(new ByteArray(hash))
- .setIndexInFile(indexInFile)
- .setLines(startLine, endLine)
- .build();
+ .setResourceId(resourceKey)
+ .setBlockHash(new ByteArray(hash))
+ .setIndexInFile(indexInFile)
+ .setLines(startLine, endLine)
+ .build();
// Group blocks by hash
Collection<Block> sameHash = cache.get(block.getBlockHash());
@@ -99,19 +99,19 @@ public class DbDuplicationsIndex {
}
}
- public void insert(Resource resource, Collection<Block> blocks) {
- int resourceSnapshotId = getSnapshotIdFor(resource);
+ public void insert(InputFile inputFile, Collection<Block> blocks) {
+ int resourceSnapshotId = getSnapshotIdFor(inputFile);
// TODO Godin: maybe remove conversion of blocks to units?
List<DuplicationUnitDto> units = Lists.newArrayList();
for (Block block : blocks) {
DuplicationUnitDto unit = new DuplicationUnitDto(
- currentProjectSnapshotId,
- resourceSnapshotId,
- block.getBlockHash().toString(),
- block.getIndexInFile(),
- block.getStartLine(),
- block.getEndLine());
+ currentProjectSnapshotId,
+ resourceSnapshotId,
+ block.getBlockHash().toString(),
+ block.getIndexInFile(),
+ block.getStartLine(),
+ block.getEndLine());
units.add(unit);
}
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java
index 9c74235bad6..cd554934c04 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarDuplicationsIndex.java
@@ -20,7 +20,7 @@
package org.sonar.plugins.cpd.index;
import com.google.common.collect.Lists;
-import org.sonar.api.resources.Resource;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
import org.sonar.duplications.index.AbstractCloneIndex;
@@ -43,18 +43,18 @@ public class SonarDuplicationsIndex extends AbstractCloneIndex {
this.db = db;
}
- public void insert(Resource resource, Collection<Block> blocks) {
+ public void insert(InputFile inputFile, Collection<Block> blocks) {
for (Block block : blocks) {
mem.insert(block);
}
if (db != null) {
- db.insert(resource, blocks);
+ db.insert(inputFile, blocks);
}
}
- public Collection<Block> getByResource(Resource resource, String resourceKey) {
+ public Collection<Block> getByInputFile(InputFile inputFile, String resourceKey) {
if (db != null) {
- db.prepareCache(resource);
+ db.prepareCache(inputFile);
}
return mem.getByResourceId(resourceKey);
}
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
index 26d5637373f..0cf3ade848b 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
@@ -42,7 +42,7 @@ public class CpdSensorTest {
@Before
public void setUp() {
IndexFactory indexFactory = mock(IndexFactory.class);
- sonarEngine = new SonarEngine(indexFactory, null, null, null);
+ sonarEngine = new SonarEngine(indexFactory, null, null);
sonarBridgeEngine = new SonarBridgeEngine(indexFactory, null, null);
settings = new Settings(new PropertyDefinitions(CpdPlugin.class));
sensor = new CpdSensor(sonarEngine, sonarBridgeEngine, settings);
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
index c2346fe86fb..f22eabb3a81 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/SonarEngineTest.java
@@ -19,15 +19,13 @@
*/
package org.sonar.plugins.cpd;
+import com.google.common.base.Charsets;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.JavaFile;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.scan.filesystem.ModuleFileSystem;
-import org.sonar.api.scan.filesystem.PathResolver;
+import org.sonar.api.scan.filesystem.internal.InputFile;
+import org.sonar.api.scan.filesystem.internal.InputFileBuilder;
import org.sonar.api.test.IsMeasure;
import org.sonar.duplications.index.CloneGroup;
import org.sonar.duplications.index.ClonePart;
@@ -36,44 +34,28 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
public class SonarEngineTest {
private SensorContext context;
- private Resource resource;
+ private InputFile inputFile;
@Before
public void setUp() {
context = mock(SensorContext.class);
- resource = new JavaFile("key1");
- }
-
- @Test
- public void testGetResource() {
- PathResolver pathResolver = mock(PathResolver.class);
- ModuleFileSystem fileSystem = mock(ModuleFileSystem.class);
- when(pathResolver.relativePath(any(java.io.File.class), any(java.io.File.class))).thenReturn("src/main/java/com/foo/Bar.java");
-
- SonarEngine engine = new SonarEngine(null, fileSystem, pathResolver, null);
- Resource resource = engine.getResource(new java.io.File(""));
-
- assertThat(resource.getKey()).isEqualTo("/src/main/java/com/foo/Bar.java");
- assertThat(resource).isInstanceOf(JavaFile.class);
+ inputFile = new InputFileBuilder(new java.io.File(""), Charsets.UTF_8, "src/main/java/Foo.java").build();
}
@SuppressWarnings("unchecked")
@Test
public void testNothingToSave() {
- SonarEngine.save(context, resource, null);
- SonarEngine.save(context, resource, Collections.EMPTY_LIST);
+ SonarEngine.save(context, inputFile, null);
+ SonarEngine.save(context, inputFile, Collections.EMPTY_LIST);
verifyZeroInteractions(context);
}
@@ -81,13 +63,13 @@ public class SonarEngineTest {
@Test
public void testOneSimpleDuplicationBetweenTwoFiles() {
List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key2", 0, 15, 214)));
- SonarEngine.save(context, resource, groups);
+ SonarEngine.save(context, inputFile, groups);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, 200d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_FILES, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_BLOCKS, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_LINES, 200d);
verify(context).saveMeasure(
- eq(resource),
+ eq(inputFile),
argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications><g>"
+ "<b s=\"5\" l=\"200\" r=\"key1\"/>"
+ "<b s=\"15\" l=\"200\" r=\"key2\"/>"
@@ -97,13 +79,13 @@ public class SonarEngineTest {
@Test
public void testDuplicationOnSameFile() throws Exception {
List<CloneGroup> groups = Arrays.asList(newCloneGroup(new ClonePart("key1", 0, 5, 204), new ClonePart("key1", 0, 215, 414)));
- SonarEngine.save(context, resource, groups);
+ SonarEngine.save(context, inputFile, groups);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, 400d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, 2d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_FILES, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_LINES, 400d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_BLOCKS, 2d);
verify(context).saveMeasure(
- eq(resource),
+ eq(inputFile),
argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications><g>"
+ "<b s=\"5\" l=\"200\" r=\"key1\"/>"
+ "<b s=\"215\" l=\"200\" r=\"key1\"/>"
@@ -113,13 +95,13 @@ public class SonarEngineTest {
@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)));
- SonarEngine.save(context, resource, groups);
+ SonarEngine.save(context, inputFile, groups);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, 200d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_FILES, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_BLOCKS, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_LINES, 200d);
verify(context).saveMeasure(
- eq(resource),
+ eq(inputFile),
argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications><g>"
+ "<b s=\"5\" l=\"200\" r=\"key1\"/>"
+ "<b s=\"15\" l=\"200\" r=\"key2\"/>"
@@ -132,13 +114,13 @@ public class SonarEngineTest {
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)));
- SonarEngine.save(context, resource, groups);
+ SonarEngine.save(context, inputFile, groups);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_FILES, 1d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_BLOCKS, 2d);
- verify(context).saveMeasure(resource, CoreMetrics.DUPLICATED_LINES, 210d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_FILES, 1d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_BLOCKS, 2d);
+ verify(context).saveMeasure(inputFile, CoreMetrics.DUPLICATED_LINES, 210d);
verify(context).saveMeasure(
- eq(resource),
+ eq(inputFile),
argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
+ "<g>"
+ "<b s=\"5\" l=\"200\" r=\"key1\"/>"
@@ -153,7 +135,7 @@ public class SonarEngineTest {
@Test
public void shouldEscapeXmlEntities() {
- File csharpFile = new File("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs");
+ InputFile csharpFile = new InputFileBuilder(new java.io.File(""), Charsets.UTF_8, "Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs").build();
List<CloneGroup> groups = Arrays.asList(newCloneGroup(
new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery.cs", 0, 5, 204),
new ClonePart("Loads/File Loads/Subs & Reds/SubsRedsDelivery2.cs", 0, 15, 214)));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
index d52e6e7d2c2..2d0a1283672 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
@@ -29,11 +29,16 @@ import org.sonar.api.design.Dependency;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.JavaFile;
+import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.Scopes;
import org.sonar.api.rules.Violation;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.api.utils.SonarException;
import org.sonar.core.measure.MeasurementFilters;
@@ -49,11 +54,13 @@ public class DefaultSensorContext implements SensorContext {
private SonarIndex index;
private Project project;
private MeasurementFilters filters;
+ private Languages languages;
- public DefaultSensorContext(SonarIndex index, Project project, MeasurementFilters filters) {
+ public DefaultSensorContext(SonarIndex index, Project project, MeasurementFilters filters, Languages languages) {
this.index = index;
this.project = project;
this.filters = filters;
+ this.languages = languages;
}
public Project getProject() {
@@ -74,6 +81,7 @@ public class DefaultSensorContext implements SensorContext {
StringUtils.equals(Scopes.FILE, resource.getScope());
}
+ @Override
public boolean index(Resource resource, Resource parentReference) {
// SONAR-5006
if (indexedByCore(resource)) {
@@ -88,42 +96,52 @@ public class DefaultSensorContext implements SensorContext {
"Plugin should not index physical resources"));
}
+ @Override
public boolean isExcluded(Resource reference) {
return index.isExcluded(reference);
}
+ @Override
public boolean isIndexed(Resource reference, boolean acceptExcluded) {
return index.isIndexed(reference, acceptExcluded);
}
+ @Override
public Resource getParent(Resource reference) {
return index.getParent(reference);
}
+ @Override
public Collection<Resource> getChildren(Resource reference) {
return index.getChildren(reference);
}
+ @Override
public Measure getMeasure(Metric metric) {
return index.getMeasure(project, metric);
}
+ @Override
public <M> M getMeasures(MeasuresFilter<M> filter) {
return index.getMeasures(project, filter);
}
+ @Override
public Measure saveMeasure(Measure measure) {
return index.addMeasure(project, measure);
}
+ @Override
public Measure saveMeasure(Metric metric, Double value) {
return index.addMeasure(project, new Measure(metric, value));
}
+ @Override
public Measure getMeasure(Resource resource, Metric metric) {
return index.getMeasure(resource, metric);
}
+ @Override
public String saveResource(Resource resource) {
Resource persistedResource = index.addResource(resource);
if (persistedResource != null) {
@@ -136,18 +154,22 @@ public class DefaultSensorContext implements SensorContext {
return index.index(resource, parentReference);
}
+ @Override
public Resource getResource(Resource resource) {
return index.getResource(resource);
}
+ @Override
public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
return index.getMeasures(resource, filter);
}
+ @Override
public Measure saveMeasure(Resource resource, Metric metric, Double value) {
return saveMeasure(resource, new Measure(metric, value));
}
+ @Override
public Measure saveMeasure(Resource resource, Measure measure) {
if (filters.accept(resource, measure)) {
return index.addMeasure(resourceOrProject(resource), measure);
@@ -217,4 +239,24 @@ public class DefaultSensorContext implements SensorContext {
private Resource resourceOrProject(Resource resource) {
return resource != null ? resource : project;
}
+
+ @Override
+ public Measure saveMeasure(InputFile inputFile, Metric metric, Double value) {
+ return saveMeasure(fromInputFile(inputFile), metric, value);
+ }
+
+ @Override
+ public Measure saveMeasure(InputFile inputFile, Measure measure) {
+ return saveMeasure(fromInputFile(inputFile), measure);
+ }
+
+ private Resource fromInputFile(InputFile inputFile) {
+ String languageKey = inputFile.attribute(InputFile.ATTRIBUTE_LANGUAGE);
+ boolean unitTest = InputFile.TYPE_TEST.equals(inputFile.attribute(InputFile.ATTRIBUTE_TYPE));
+ if (Java.KEY.equals(languageKey)) {
+ return JavaFile.create(inputFile.path(), inputFile.attribute(InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH), unitTest);
+ } else {
+ return File.create(inputFile.path(), inputFile.attribute(InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH), languages.get(languageKey), unitTest);
+ }
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index fa665e608b9..c76b2498ae1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -535,6 +535,11 @@ public class DefaultIndex extends SonarIndex {
return bucket;
}
+ if (StringUtils.isBlank(resource.getKey())) {
+ LOG.warn("Unable to index a resource without key " + resource);
+ return null;
+ }
+
checkLock(resource);
Resource parent = null;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java
index cbf24c5e6be..26799593177 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultResourcePersister.java
@@ -25,12 +25,16 @@ import org.apache.commons.lang.StringUtils;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Java;
+import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.resources.Scopes;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import org.sonar.api.security.ResourcePermissions;
import org.sonar.api.utils.SonarException;
@@ -131,6 +135,21 @@ public final class DefaultResourcePersister implements ResourcePersister {
return snapshot;
}
+ @Override
+ public Snapshot getSnapshotOrFail(InputFile inputFile) {
+ return getSnapshotOrFail(fromInputFile(inputFile));
+ };
+
+ private Resource fromInputFile(InputFile inputFile) {
+ String languageKey = inputFile.attribute(InputFile.ATTRIBUTE_LANGUAGE);
+ boolean unitTest = InputFile.TYPE_TEST.equals(inputFile.attribute(InputFile.ATTRIBUTE_TYPE));
+ if (Java.KEY.equals(languageKey)) {
+ return JavaFile.create(inputFile.path(), inputFile.attribute(InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH), unitTest);
+ } else {
+ return File.create(inputFile.path(), inputFile.attribute(InputFile.ATTRIBUTE_SOURCE_RELATIVE_PATH), null, unitTest);
+ }
+ }
+
/**
* just for unit tests
*/
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
index 4310f54c165..8e41528ba36 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
@@ -22,9 +22,10 @@ package org.sonar.batch.index;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
+import org.sonar.api.scan.filesystem.internal.InputFile;
public interface ResourcePersister {
-
+
Snapshot saveProject(Project project, Project parent);
/**
@@ -39,11 +40,9 @@ public interface ResourcePersister {
Snapshot getSnapshot(Resource resource);
- /**
- * @throws ResourceNotPersistedException if the resource is not persisted.
- */
Snapshot getSnapshotOrFail(Resource resource);
-
+
+ Snapshot getSnapshotOrFail(InputFile resource);
/**
* The current snapshot which is flagged as "last", different then the current analysis.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/CpdMapping.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/CpdMapping.java
index 3203740ee48..c000683c4e8 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/CpdMapping.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/CpdMapping.java
@@ -36,6 +36,10 @@ public interface CpdMapping extends BatchExtension {
Language getLanguage();
+ /**
+ * @deprecated since 4.2
+ */
+ @Deprecated
Resource createResource(File file, List<File> sourceDirs);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
index e4654dd08e3..23a02fd333a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/SensorContext.java
@@ -26,6 +26,7 @@ import org.sonar.api.measures.Metric;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
+import org.sonar.api.scan.filesystem.internal.InputFile;
import java.util.Collection;
import java.util.Date;
@@ -143,6 +144,12 @@ public interface SensorContext {
/**
* Add or update a measure.
+ * @since 4.2
+ */
+ Measure saveMeasure(InputFile inputFile, Metric metric, Double value);
+
+ /**
+ * Add or update a measure.
* <p>
* The resource is automatically saved, so there is no need to execute the method saveResource(). Does nothing if the resource is set as
* excluded.
@@ -150,6 +157,12 @@ public interface SensorContext {
*/
Measure saveMeasure(Resource resource, Measure measure);
+ /**
+ * Add or update a measure.
+ * @since 4.2
+ */
+ Measure saveMeasure(InputFile inputFile, Measure measure);
+
// ----------- RULE VIOLATIONS --------------
/**
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java
index 37b4e6a9582..ae901e0bdfe 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/resources/ResourceUtils.java
@@ -136,6 +136,7 @@ public final class ResourceUtils {
*/
public static boolean isPersistable(Resource resource) {
return StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()) ||
- StringUtils.equals(Scopes.FILE, resource.getScope());
+ StringUtils.equals(Scopes.FILE, resource.getScope());
}
+
}