aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2014-07-25 16:31:45 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2014-07-30 18:03:36 +0200
commit6074164392edd3db2dfdfd21d05cd56c19e2b0e6 (patch)
treeb9314796d68c4c396dcf45a1ab689b06490fd4a2 /sonar-batch
parent12f243728f42a5eb1e714ff15f0240109193f1d8 (diff)
downloadsonarqube-6074164392edd3db2dfdfd21d05cd56c19e2b0e6.tar.gz
sonarqube-6074164392edd3db2dfdfd21d05cd56c19e2b0e6.zip
SONAR-5389 New duplication API
Diffstat (limited to 'sonar-batch')
-rw-r--r--sonar-batch/pom.xml5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/BlockCache.java56
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationBuilder.java74
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java77
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java (renamed from sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/Xoo.java)31
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java58
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroup.java76
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java54
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/FileBlocksValueCoder.java69
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java (renamed from sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/XooConstants.java)19
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/Cache.java13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/Caches.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java49
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java12
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java59
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java10
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java76
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java24
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java64
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java44
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan2/SensorsExecutor.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java82
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java9
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/XooPlugin.java53
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/MeasureSensor.java119
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/ScmActivitySensor.java113
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SymbolReferencesSensor.java98
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SyntaxHighlightingSensor.java95
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java60
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssueOnDirPerFileSensor.java61
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssuePerLineSensor.java75
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java5
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java16
47 files changed, 969 insertions, 755 deletions
diff --git a/sonar-batch/pom.xml b/sonar-batch/pom.xml
index 1ba3a32d61f..89f7c9252a4 100644
--- a/sonar-batch/pom.xml
+++ b/sonar-batch/pom.xml
@@ -149,5 +149,10 @@
<artifactId>jsonassert</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.codehaus.sonar.plugins</groupId>
+ <artifactId>sonar-xoo-plugin</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
index 7317c9afd08..32bebf6182e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchExtensionDictionnary.java
@@ -22,6 +22,7 @@ package org.sonar.batch.bootstrap;
import com.google.common.collect.Lists;
import org.apache.commons.lang.ClassUtils;
import org.sonar.api.batch.CheckProject;
+import org.sonar.api.batch.Phase;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.platform.ComponentContainer;
@@ -56,6 +57,15 @@ public class BatchExtensionDictionnary extends org.sonar.api.batch.BatchExtensio
return result;
}
+ @Override
+ protected Phase.Name evaluatePhase(Object extension) {
+ if (extension instanceof SensorWrapper) {
+ return super.evaluatePhase(((SensorWrapper) extension).wrappedSensor());
+ } else {
+ return super.evaluatePhase(extension);
+ }
+ }
+
private <T> List<T> getFilteredExtensions(Class<T> type, @Nullable Project project, @Nullable ExtensionMatcher matcher) {
List<T> result = Lists.newArrayList();
for (Object extension : getExtensions(type)) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/BlockCache.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/BlockCache.java
new file mode 100644
index 00000000000..f6a4e3d18bf
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/BlockCache.java
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.index.Cache;
+import org.sonar.batch.index.Cache.Entry;
+import org.sonar.batch.index.Caches;
+import org.sonar.duplications.block.FileBlocks;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * Cache of duplication blocks. This cache is shared amongst all project modules.
+ */
+public class BlockCache implements BatchComponent {
+
+ private final Cache<FileBlocks> cache;
+
+ public BlockCache(Caches caches) {
+ caches.registerValueCoder(FileBlocks.class, new FileBlocksValueCoder());
+ cache = caches.createCache("blocks");
+ }
+
+ public Iterable<Entry<FileBlocks>> entries() {
+ return cache.entries();
+ }
+
+ @CheckForNull
+ public FileBlocks byComponent(String effectiveKey) {
+ return cache.get(effectiveKey);
+ }
+
+ public BlockCache put(String effectiveKey, FileBlocks blocks) {
+ cache.put(effectiveKey, blocks);
+ return this;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationBuilder.java
new file mode 100644
index 00000000000..d6dd18026a2
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultDuplicationBuilder.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import com.google.common.base.Preconditions;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
+
+import java.util.ArrayList;
+
+public class DefaultDuplicationBuilder implements DuplicationBuilder {
+
+ private final InputFile inputFile;
+ private final DuplicationCache duplicationCache;
+ private boolean done = false;
+ private DuplicationGroup current = null;
+ private ArrayList<DuplicationGroup> duplications;
+
+ public DefaultDuplicationBuilder(InputFile inputFile, DuplicationCache duplicationCache) {
+ this.inputFile = inputFile;
+ this.duplicationCache = duplicationCache;
+ duplications = new ArrayList<DuplicationGroup>();
+ }
+
+ @Override
+ public DuplicationBuilder originBlock(int startLine, int endLine) {
+ if (current != null) {
+ duplications.add(current);
+ }
+ current = new DuplicationGroup(new DuplicationGroup.Block(((DefaultInputFile) inputFile).key(), startLine, endLine - startLine + 1));
+ return this;
+ }
+
+ @Override
+ public DuplicationBuilder isDuplicatedBy(InputFile sameOrOtherFile, int startLine, int endLine) {
+ return isDuplicatedBy(((DefaultInputFile) sameOrOtherFile).key(), startLine, endLine);
+ }
+
+ /**
+ * For internal use. Global duplications are referencing files outside of current project so
+ * no way to manipulate an InputFile.
+ */
+ public DuplicationBuilder isDuplicatedBy(String fileKey, int startLine, int endLine) {
+ Preconditions.checkNotNull(current, "Call originBlock() first");
+ current.addDuplicate(new DuplicationGroup.Block(fileKey, startLine, endLine - startLine + 1));
+ return this;
+ }
+
+ @Override
+ public void done() {
+ Preconditions.checkState(!done, "done() already called");
+ Preconditions.checkNotNull(current, "Call originBlock() first");
+ duplications.add(current);
+ duplicationCache.put(((DefaultInputFile) inputFile).key(), duplications);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java
new file mode 100644
index 00000000000..6c7836d9e39
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DefaultTokenBuilder.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import com.google.common.base.Preconditions;
+import net.sourceforge.pmd.cpd.TokenEntry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.duplication.TokenBuilder;
+import org.sonar.duplications.block.Block;
+import org.sonar.duplications.block.FileBlocks;
+import org.sonar.duplications.internal.pmd.PmdBlockChunker;
+import org.sonar.duplications.internal.pmd.TokenizerBridge;
+import org.sonar.duplications.internal.pmd.TokensLine;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultTokenBuilder implements TokenBuilder {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DefaultTokenBuilder.class);
+
+ private final BlockCache cache;
+ private final InputFile inputFile;
+ private final List<TokenEntry> tokens = new ArrayList<TokenEntry>();
+ private final PmdBlockChunker blockChunker;
+ private boolean done = false;
+ private int previousLine = 0;
+
+ public DefaultTokenBuilder(InputFile inputFile, BlockCache cache, PmdBlockChunker blockChunker) {
+ this.inputFile = inputFile;
+ this.cache = cache;
+ this.blockChunker = blockChunker;
+ TokenEntry.clearImages();
+ }
+
+ @Override
+ public DefaultTokenBuilder addToken(int line, String image) {
+ Preconditions.checkState(!done, "done() already called");
+ Preconditions.checkState(line >= previousLine, "Token should be created in order. Previous line was " + previousLine + " and you tried to create a token at line " + line);
+ TokenEntry cpdToken = new TokenEntry(image, inputFile.absolutePath(), line);
+ tokens.add(cpdToken);
+ previousLine = line;
+ return this;
+ }
+
+ @Override
+ public void done() {
+ Preconditions.checkState(!done, "done() already called");
+ tokens.add(TokenEntry.getEOF());
+ TokenEntry.clearImages();
+ List<TokensLine> tokensLines = TokenizerBridge.convert(tokens);
+ ArrayList<Block> blocks = blockChunker.chunk(((DefaultInputFile) inputFile).key(), tokensLines);
+
+ cache.put(((DefaultInputFile) inputFile).key(), new FileBlocks(((DefaultInputFile) inputFile).key(), blocks));
+ tokens.clear();
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/Xoo.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java
index 1922fd7aa35..ab1dad47009 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/Xoo.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationBlockValueCoder.java
@@ -17,24 +17,27 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.batch.mediumtest.xoo.plugin.base;
+package org.sonar.batch.duplication;
-import org.sonar.api.resources.AbstractLanguage;
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
-public class Xoo extends AbstractLanguage {
+class DuplicationBlockValueCoder implements ValueCoder {
- public static final String KEY = "xoo";
- public static final String NAME = "Xoo";
-
- public Xoo() {
- super(KEY, NAME);
+ @Override
+ public void put(Value value, Object object, CoderContext context) {
+ DuplicationGroup.Block b = (DuplicationGroup.Block) object;
+ value.putUTF(b.resourceKey());
+ value.put(b.startLine());
+ value.put(b.length());
}
- /**
- * ${@inheritDoc}
- */
- public String[] getFileSuffixes() {
- return XooConstants.FILE_SUFFIXES;
+ @Override
+ public Object get(Value value, Class clazz, CoderContext context) {
+ String resourceKey = value.getString();
+ int startLine = value.getInt();
+ int length = value.getInt();
+ return new DuplicationGroup.Block(resourceKey, startLine, length);
}
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java
new file mode 100644
index 00000000000..e0265215efc
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationCache.java
@@ -0,0 +1,58 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import org.sonar.api.BatchComponent;
+import org.sonar.batch.index.Cache;
+import org.sonar.batch.index.Cache.Entry;
+import org.sonar.batch.index.Caches;
+
+import javax.annotation.CheckForNull;
+
+import java.util.ArrayList;
+
+/**
+ * Cache of duplication blocks. This cache is shared amongst all project modules.
+ */
+public class DuplicationCache implements BatchComponent {
+
+ private final Cache<ArrayList<DuplicationGroup>> cache;
+
+ public DuplicationCache(Caches caches) {
+ caches.registerValueCoder(DuplicationGroup.class, new DuplicationGroupValueCoder());
+ caches.registerValueCoder(DuplicationGroup.Block.class, new DuplicationBlockValueCoder());
+ cache = caches.createCache("duplications");
+ }
+
+ public Iterable<Entry<ArrayList<DuplicationGroup>>> entries() {
+ return cache.entries();
+ }
+
+ @CheckForNull
+ public ArrayList<DuplicationGroup> byComponent(String effectiveKey) {
+ return cache.get(effectiveKey);
+ }
+
+ public DuplicationCache put(String effectiveKey, ArrayList<DuplicationGroup> blocks) {
+ cache.put(effectiveKey, blocks);
+ return this;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroup.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroup.java
new file mode 100644
index 00000000000..dc9a7aa2602
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroup.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DuplicationGroup {
+
+ public static class Block {
+ private final String resourceKey;
+ private final int startLine;
+ private final int length;
+
+ public Block(String resourceKey, int startLine, int length) {
+ this.resourceKey = resourceKey;
+ this.startLine = startLine;
+ this.length = length;
+ }
+
+ public String resourceKey() {
+ return resourceKey;
+ }
+
+ public int startLine() {
+ return startLine;
+ }
+
+ public int length() {
+ return length;
+ }
+ }
+
+ private final Block originBlock;
+
+ private List<Block> duplicates = new ArrayList<DuplicationGroup.Block>();
+
+ public DuplicationGroup(Block originBlock) {
+ this.originBlock = originBlock;
+ }
+
+ public void setDuplicates(List<Block> duplicates) {
+ this.duplicates = duplicates;
+ }
+
+ public DuplicationGroup addDuplicate(Block anotherBlock) {
+ this.duplicates.add(anotherBlock);
+ return this;
+ }
+
+ public Block originBlock() {
+ return originBlock;
+ }
+
+ public List<Block> duplicates() {
+ return duplicates;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java
new file mode 100644
index 00000000000..244cffccd5f
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/DuplicationGroupValueCoder.java
@@ -0,0 +1,54 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
+import org.sonar.batch.duplication.DuplicationGroup.Block;
+
+import java.util.ArrayList;
+
+class DuplicationGroupValueCoder implements ValueCoder {
+
+ private DuplicationBlockValueCoder blockCoder = new DuplicationBlockValueCoder();
+
+ @Override
+ public void put(Value value, Object object, CoderContext context) {
+ DuplicationGroup c = (DuplicationGroup) object;
+ value.put(c.originBlock());
+ value.put(c.duplicates().size());
+ for (DuplicationGroup.Block block : c.duplicates()) {
+ blockCoder.put(value, block, context);
+ }
+ }
+
+ @Override
+ public Object get(Value value, Class clazz, CoderContext context) {
+ DuplicationGroup g = new DuplicationGroup((DuplicationGroup.Block) value.get());
+ int count = value.getInt();
+ ArrayList<DuplicationGroup.Block> blocks = new ArrayList<DuplicationGroup.Block>(count);
+ for (int i = 0; i < count; i++) {
+ blocks.add((Block) blockCoder.get(value, DuplicationGroup.Block.class, context));
+ }
+ g.setDuplicates(blocks);
+ return g;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/duplication/FileBlocksValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/FileBlocksValueCoder.java
new file mode 100644
index 00000000000..99b3467c921
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/FileBlocksValueCoder.java
@@ -0,0 +1,69 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
+import org.sonar.duplications.block.Block;
+import org.sonar.duplications.block.ByteArray;
+import org.sonar.duplications.block.FileBlocks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class FileBlocksValueCoder implements ValueCoder {
+
+ @Override
+ public void put(Value value, Object object, CoderContext context) {
+ FileBlocks blocks = (FileBlocks) object;
+ value.putUTF(blocks.resourceId());
+ value.put(blocks.blocks().size());
+ for (Block b : blocks.blocks()) {
+ value.putByteArray(b.getBlockHash().getBytes());
+ value.put(b.getIndexInFile());
+ value.put(b.getStartLine());
+ value.put(b.getEndLine());
+ value.put(b.getStartUnit());
+ value.put(b.getEndUnit());
+ }
+ }
+
+ @Override
+ public Object get(Value value, Class clazz, CoderContext context) {
+ String resourceId = value.getString();
+ int count = value.getInt();
+ List<Block> blocks = new ArrayList<Block>(count);
+ for (int i = 0; i < count; i++) {
+ Block.Builder b = Block.builder();
+ b.setResourceId(resourceId);
+ b.setBlockHash(new ByteArray(value.getByteArray()));
+ b.setIndexInFile(value.getInt());
+ int startLine = value.getInt();
+ int endLine = value.getInt();
+ b.setLines(startLine, endLine);
+ int startUnit = value.getInt();
+ int endUnit = value.getInt();
+ b.setUnit(startUnit, endUnit);
+ blocks.add(b.build());
+ }
+ return new FileBlocks(resourceId, blocks);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/XooConstants.java b/sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java
index c59091fb0f6..103e90ab281 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/base/XooConstants.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/duplication/package-info.java
@@ -17,20 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-package org.sonar.batch.mediumtest.xoo.plugin.base;
+@ParametersAreNonnullByDefault
+package org.sonar.batch.duplication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public interface XooConstants {
-
- String PLUGIN_KEY = "xoo";
- String PLUGIN_NAME = "Xoo";
-
- String REPOSITORY_KEY = PLUGIN_KEY;
- String REPOSITORY_NAME = PLUGIN_NAME;
-
- String[] FILE_SUFFIXES = {"xoo"};
-
- Logger LOG = LoggerFactory.getLogger("xoo");
-}
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
index 38ae875af98..3a74dbf4884 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingDataBuilder.java
@@ -32,9 +32,6 @@ import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
-/**
- * @since 3.6
- */
public class SyntaxHighlightingDataBuilder {
private List<SyntaxHighlightingRule> syntaxHighlightingRuleSet;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
index 08985752d60..e6faa7651b4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/highlighting/SyntaxHighlightingRule.java
@@ -21,9 +21,6 @@ package org.sonar.batch.highlighting;
import java.io.Serializable;
-/**
- * @since 3.6
- */
public class SyntaxHighlightingRule implements Serializable {
private final int startPosition;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java b/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java
index ff57e4c065d..c98b88773e6 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/Cache.java
@@ -28,7 +28,6 @@ import org.apache.commons.lang.builder.ToStringBuilder;
import javax.annotation.CheckForNull;
-import java.io.Serializable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -38,7 +37,7 @@ import java.util.Set;
* This cache is not thread-safe, due to direct usage of {@link com.persistit.Exchange}
* </p>
*/
-public class Cache<V extends Serializable> {
+public class Cache<V> {
private final String name;
private final Exchange exchange;
@@ -383,7 +382,7 @@ public class Cache<V extends Serializable> {
// LAZY ITERATORS AND ITERABLES
//
- private static class ValueIterable<T extends Serializable> implements Iterable<T> {
+ private static class ValueIterable<T> implements Iterable<T> {
private final Iterator<T> iterator;
private ValueIterable(Exchange exchange, KeyFilter keyFilter) {
@@ -396,7 +395,7 @@ public class Cache<V extends Serializable> {
}
}
- private static class ValueIterator<T extends Serializable> implements Iterator<T> {
+ private static class ValueIterator<T> implements Iterator<T> {
private final Exchange exchange;
private final KeyFilter keyFilter;
@@ -434,7 +433,7 @@ public class Cache<V extends Serializable> {
}
}
- private static class EntryIterable<T extends Serializable> implements Iterable<Entry<T>> {
+ private static class EntryIterable<T> implements Iterable<Entry<T>> {
private final EntryIterator<T> it;
private EntryIterable(Exchange exchange, KeyFilter keyFilter) {
@@ -447,7 +446,7 @@ public class Cache<V extends Serializable> {
}
}
- private static class EntryIterator<T extends Serializable> implements Iterator<Entry<T>> {
+ private static class EntryIterator<T> implements Iterator<Entry<T>> {
private final Exchange exchange;
private final KeyFilter keyFilter;
@@ -491,7 +490,7 @@ public class Cache<V extends Serializable> {
}
}
- public static class Entry<V extends Serializable> {
+ public static class Entry<V> {
private final Object[] key;
private final V value;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
index 1e8c53d8853..ca2a33a5014 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java
@@ -36,7 +36,6 @@ import org.sonar.api.BatchComponent;
import org.sonar.api.utils.TempFolder;
import java.io.File;
-import java.io.Serializable;
import java.util.Properties;
import java.util.Set;
@@ -85,7 +84,7 @@ public class Caches implements BatchComponent, Startable {
cm.registerValueCoder(clazz, coder);
}
- public <V extends Serializable> Cache<V> createCache(String cacheName) {
+ public <V> Cache<V> createCache(String cacheName) {
Preconditions.checkState(volume != null && volume.isOpened(), "Caches are not initialized");
Preconditions.checkState(!cacheNames.contains(cacheName), "Cache is already created: " + cacheName);
try {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
index 2a63d4b8b9e..0f7691728a1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
@@ -20,10 +20,13 @@
package org.sonar.batch.index;
import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.lang.StringEscapeUtils;
import org.sonar.api.database.model.MeasureMapper;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
+import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
@@ -31,6 +34,8 @@ import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.technicaldebt.batch.Characteristic;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationGroup;
import org.sonar.batch.index.Cache.Entry;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.persistence.DbSession;
@@ -38,20 +43,27 @@ import org.sonar.core.persistence.MyBatis;
import javax.annotation.Nullable;
+import java.util.ArrayList;
+
public final class MeasurePersister implements ScanPersister {
private final MyBatis mybatis;
private final RuleFinder ruleFinder;
private final MeasureCache measureCache;
private final SnapshotCache snapshotCache;
private final ResourceCache resourceCache;
+ private final DuplicationCache duplicationCache;
+ private final org.sonar.api.measures.MetricFinder metricFinder;
public MeasurePersister(MyBatis mybatis, RuleFinder ruleFinder,
- MeasureCache measureCache, SnapshotCache snapshotCache, ResourceCache resourceCache) {
+ MeasureCache measureCache, SnapshotCache snapshotCache, ResourceCache resourceCache,
+ DuplicationCache duplicationCache, org.sonar.api.measures.MetricFinder metricFinder) {
this.mybatis = mybatis;
this.ruleFinder = ruleFinder;
this.measureCache = measureCache;
this.snapshotCache = snapshotCache;
this.resourceCache = resourceCache;
+ this.duplicationCache = duplicationCache;
+ this.metricFinder = metricFinder;
}
@Override
@@ -72,6 +84,19 @@ public final class MeasurePersister implements ScanPersister {
}
}
+ org.sonar.api.measures.Metric duplicationMetricWithId = metricFinder.findByKey(CoreMetrics.DUPLICATIONS_DATA_KEY);
+ for (Entry<ArrayList<DuplicationGroup>> entry : duplicationCache.entries()) {
+ String effectiveKey = entry.key()[0].toString();
+ Measure measure = new Measure(duplicationMetricWithId, toXml(entry.value())).setPersistenceMode(PersistenceMode.DATABASE);
+ Resource resource = resourceCache.get(effectiveKey);
+
+ if (shouldPersistMeasure(resource, measure)) {
+ Snapshot snapshot = snapshotCache.get(effectiveKey);
+ MeasureModel measureModel = model(measure).setSnapshotId(snapshot.getId());
+ mapper.insert(measureModel);
+ }
+ }
+
session.commit();
} catch (Exception e) {
throw new IllegalStateException("Unable to save some measures", e);
@@ -80,6 +105,28 @@ public final class MeasurePersister implements ScanPersister {
}
}
+ private static String toXml(Iterable<DuplicationGroup> duplications) {
+ StringBuilder xml = new StringBuilder();
+ xml.append("<duplications>");
+ for (DuplicationGroup duplication : duplications) {
+ xml.append("<g>");
+ toXml(xml, duplication.originBlock());
+ for (DuplicationGroup.Block part : duplication.duplicates()) {
+ toXml(xml, part);
+ }
+ xml.append("</g>");
+ }
+ xml.append("</duplications>");
+ return xml.toString();
+ }
+
+ private static void toXml(StringBuilder xml, DuplicationGroup.Block part) {
+ xml.append("<b s=\"").append(part.startLine())
+ .append("\" l=\"").append(part.length())
+ .append("\" r=\"").append(StringEscapeUtils.escapeXml(part.resourceKey()))
+ .append("\"/>");
+ }
+
@VisibleForTesting
static boolean shouldPersistMeasure(@Nullable Resource resource, @Nullable Measure measure) {
if (resource == null || measure == null) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index fc7a89ebad8..58cc4f461af 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -41,8 +41,11 @@ import org.sonar.api.resources.Languages;
import org.sonar.batch.bootstrap.PluginsReferential;
import org.sonar.batch.bootstrapper.Batch;
import org.sonar.batch.bootstrapper.EnvironmentInformation;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationGroup;
import org.sonar.batch.highlighting.SyntaxHighlightingData;
import org.sonar.batch.highlighting.SyntaxHighlightingRule;
+import org.sonar.batch.index.Cache.Entry;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.protocol.input.ActiveRule;
import org.sonar.batch.protocol.input.GlobalReferentials;
@@ -222,6 +225,7 @@ public class BatchMediumTester {
private List<Issue> issues = new ArrayList<Issue>();
private List<Measure> measures = new ArrayList<Measure>();
+ private Map<String, List<DuplicationGroup>> duplications = new HashMap<String, List<DuplicationGroup>>();
private List<InputFile> inputFiles = new ArrayList<InputFile>();
private List<InputDir> inputDirs = new ArrayList<InputDir>();
private Map<InputFile, SyntaxHighlightingData> highlightingPerFile = new HashMap<InputFile, SyntaxHighlightingData>();
@@ -259,6 +263,12 @@ public class BatchMediumTester {
}
}
+ DuplicationCache duplicationCache = container.getComponentByType(DuplicationCache.class);
+ for (Entry<ArrayList<DuplicationGroup>> entry : duplicationCache.entries()) {
+ String effectiveKey = entry.key()[0].toString();
+ duplications.put(effectiveKey, entry.value());
+ }
+
}
public List<Issue> issues() {
@@ -277,6 +287,10 @@ public class BatchMediumTester {
return inputDirs;
}
+ public List<DuplicationGroup> duplicationsFor(InputFile inputFile) {
+ return duplications.get(((DefaultInputFile) inputFile).key());
+ }
+
/**
* Get highlighting type at a given position in an inputfile
* @param charIndex 0-based offset in file
diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java b/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java
index 75a063eb119..ac08e40f5fa 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java
@@ -20,14 +20,24 @@
package org.sonar.batch.referential;
import org.picocontainer.injectors.ProviderAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.TimeProfiler;
import org.sonar.batch.protocol.input.ProjectReferentials;
public class ProjectReferentialsProvider extends ProviderAdapter {
+ private static final Logger LOG = LoggerFactory.getLogger(ProjectReferentialsProvider.class);
+
public ProjectReferentials provide(ProjectReferentialsLoader loader, ProjectReactor reactor, Settings settings, Languages languages) {
- return loader.load(reactor, settings, languages);
+ TimeProfiler profiler = new TimeProfiler(LOG).start("Load project referentials");
+ try {
+ return loader.load(reactor, settings, languages);
+ } finally {
+ profiler.stop();
+ }
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index c5e21b89a66..3a209b91961 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -42,6 +42,8 @@ import org.sonar.batch.bootstrap.MetricProvider;
import org.sonar.batch.components.PeriodsDefinition;
import org.sonar.batch.debt.DebtModelProvider;
import org.sonar.batch.debt.IssueChangelogDebtCalculator;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.index.Caches;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.index.ComponentDataPersister;
@@ -194,6 +196,10 @@ public class ProjectScanContainer extends ComponentContainer {
new RulesProvider(),
new DebtModelProvider(),
+ // Duplications
+ BlockCache.class,
+ DuplicationCache.class,
+
ProjectSettings.class);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java
index 1de8fd7201c..d285a6c8646 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorContextAdaptor.java
@@ -27,6 +27,8 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
+import org.sonar.api.batch.sensor.duplication.TokenBuilder;
import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.IssueBuilder;
@@ -49,9 +51,14 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.Scopes;
import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DefaultDuplicationBuilder;
+import org.sonar.batch.duplication.DefaultTokenBuilder;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
+import org.sonar.duplications.internal.pmd.PmdBlockChunker;
import java.io.Serializable;
@@ -61,17 +68,20 @@ import java.io.Serializable;
*/
public class SensorContextAdaptor implements SensorContext {
- private org.sonar.api.batch.SensorContext sensorContext;
- private MetricFinder metricFinder;
- private Project project;
- private ResourcePerspectives perspectives;
- private Settings settings;
- private FileSystem fs;
- private ActiveRules activeRules;
- private ComponentDataCache componentDataCache;
+ private final org.sonar.api.batch.SensorContext sensorContext;
+ private final MetricFinder metricFinder;
+ private final Project project;
+ private final ResourcePerspectives perspectives;
+ private final Settings settings;
+ private final FileSystem fs;
+ private final ActiveRules activeRules;
+ private final ComponentDataCache componentDataCache;
+ private final BlockCache blockCache;
+ private final DuplicationCache duplicationCache;
public SensorContextAdaptor(org.sonar.api.batch.SensorContext sensorContext, MetricFinder metricFinder, Project project, ResourcePerspectives perspectives,
- Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache) {
+ Settings settings, FileSystem fs, ActiveRules activeRules, ComponentDataCache componentDataCache, BlockCache blockCache,
+ DuplicationCache duplicationCache) {
this.sensorContext = sensorContext;
this.metricFinder = metricFinder;
this.project = project;
@@ -80,6 +90,8 @@ public class SensorContextAdaptor implements SensorContext {
this.fs = fs;
this.activeRules = activeRules;
this.componentDataCache = componentDataCache;
+ this.blockCache = blockCache;
+ this.duplicationCache = duplicationCache;
}
@Override
@@ -254,4 +266,33 @@ public class SensorContextAdaptor implements SensorContext {
return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
}
+ @Override
+ public TokenBuilder tokenBuilder(InputFile inputFile) {
+ PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
+ return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
+ }
+
+ @Override
+ public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
+ return new DefaultDuplicationBuilder(inputFile, duplicationCache);
+ }
+
+ private int getBlockSize(String languageKey) {
+ int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
+ if (blockSize == 0) {
+ blockSize = getDefaultBlockSize(languageKey);
+ }
+ return blockSize;
+ }
+
+ private static int getDefaultBlockSize(String languageKey) {
+ if ("cobol".equals(languageKey)) {
+ return 30;
+ } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
+ return 20;
+ } else {
+ return 10;
+ }
+ }
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
index b5929008269..32a49a16492 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/SensorWrapper.java
@@ -33,19 +33,23 @@ import java.util.List;
public class SensorWrapper implements org.sonar.api.batch.Sensor {
- private Sensor analyzer;
+ private Sensor wrappedSensor;
private SensorContext adaptor;
private DefaultSensorDescriptor descriptor;
private AnalyzerOptimizer optimizer;
public SensorWrapper(Sensor newSensor, SensorContext adaptor, AnalyzerOptimizer optimizer) {
- this.analyzer = newSensor;
+ this.wrappedSensor = newSensor;
this.optimizer = optimizer;
descriptor = new DefaultSensorDescriptor();
newSensor.describe(descriptor);
this.adaptor = adaptor;
}
+ public Sensor wrappedSensor() {
+ return wrappedSensor;
+ }
+
@DependedUpon
public List<Metric> provides() {
return Arrays.asList(descriptor.provides());
@@ -63,7 +67,7 @@ public class SensorWrapper implements org.sonar.api.batch.Sensor {
@Override
public void analyse(Project module, org.sonar.api.batch.SensorContext context) {
- analyzer.execute(adaptor);
+ wrappedSensor.execute(adaptor);
}
@Override
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java
new file mode 100644
index 00000000000..d60cbac0088
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/DefaultInputFileValueCoder.java
@@ -0,0 +1,76 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.scan.filesystem;
+
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
+
+import javax.annotation.Nullable;
+
+import java.io.File;
+
+class DefaultInputFileValueCoder implements ValueCoder {
+
+ @Override
+ public void put(Value value, Object object, CoderContext context) {
+ DeprecatedDefaultInputFile f = (DeprecatedDefaultInputFile) object;
+ putUTFOrNull(value, f.relativePath());
+ putUTFOrNull(value, f.getFileBaseDir().toString());
+ putUTFOrNull(value, f.deprecatedKey());
+ putUTFOrNull(value, f.sourceDirAbsolutePath());
+ putUTFOrNull(value, f.pathRelativeToSourceDir());
+ putUTFOrNull(value, f.absolutePath());
+ putUTFOrNull(value, f.language());
+ putUTFOrNull(value, f.type().name());
+ putUTFOrNull(value, f.status().name());
+ putUTFOrNull(value, f.hash());
+ value.put(f.lines());
+ putUTFOrNull(value, f.key());
+ }
+
+ private void putUTFOrNull(Value value, @Nullable String utfOrNull) {
+ if (utfOrNull != null) {
+ value.putUTF(utfOrNull);
+ } else {
+ value.putNull();
+ }
+ }
+
+ @Override
+ public Object get(Value value, Class clazz, CoderContext context) {
+ DeprecatedDefaultInputFile file = new DeprecatedDefaultInputFile(value.getString());
+ file.setBasedir(new File(value.getString()));
+ file.setDeprecatedKey(value.getString());
+ file.setSourceDirAbsolutePath(value.getString());
+ file.setPathRelativeToSourceDir(value.getString());
+ file.setAbsolutePath(value.getString());
+ file.setLanguage(value.getString());
+ file.setType(InputFile.Type.valueOf(value.getString()));
+ file.setStatus(InputFile.Status.valueOf(value.getString()));
+ file.setHash(value.getString());
+ file.setLines(value.getInt());
+ file.setKey(value.getString());
+ return file;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
index 5d901a517ae..39672d7f7c5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/InputPathCache.java
@@ -23,6 +23,7 @@ import org.sonar.api.BatchComponent;
import org.sonar.api.batch.fs.InputDir;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputPath;
+import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
import org.sonar.batch.index.Cache;
import org.sonar.batch.index.Caches;
@@ -44,6 +45,7 @@ public class InputPathCache implements BatchComponent {
private final Cache<InputPath> cache;
public InputPathCache(Caches caches) {
+ caches.registerValueCoder(DeprecatedDefaultInputFile.class, new DefaultInputFileValueCoder());
cache = caches.createCache("inputFiles");
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java
index 7f010d97d0a..c0906b51d6d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java
@@ -30,6 +30,8 @@ import org.sonar.api.technicaldebt.batch.Characteristic;
import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
+import javax.annotation.Nullable;
+
class MeasureValueCoder implements ValueCoder {
private final MetricFinder metricFinder;
@@ -42,12 +44,12 @@ class MeasureValueCoder implements ValueCoder {
public void put(Value value, Object object, CoderContext context) {
Measure<?> m = (Measure) object;
- value.putString(m.getMetricKey());
+ value.putUTF(m.getMetricKey());
value.put(m.getValue());
- value.putString(m.getData());
- value.putString(m.getDescription());
- value.putString(m.getAlertStatus() != null ? m.getAlertStatus().name() : null);
- value.putString(m.getAlertText());
+ putUTFOrNull(value, m.getData());
+ putUTFOrNull(value, m.getDescription());
+ putUTFOrNull(value, m.getAlertStatus() != null ? m.getAlertStatus().name() : null);
+ putUTFOrNull(value, m.getAlertText());
value.put(m.getTendency());
value.putDate(m.getDate());
value.put(m.getVariation1());
@@ -55,7 +57,7 @@ class MeasureValueCoder implements ValueCoder {
value.put(m.getVariation3());
value.put(m.getVariation4());
value.put(m.getVariation5());
- value.putString(m.getUrl());
+ putUTFOrNull(value, m.getUrl());
Characteristic characteristic = m.getCharacteristic();
value.put(characteristic != null ? characteristic.id() : null);
Requirement requirement = m.getRequirement();
@@ -63,7 +65,15 @@ class MeasureValueCoder implements ValueCoder {
Integer personId = m.getPersonId();
value.put(personId != null ? personId.intValue() : null);
PersistenceMode persistenceMode = m.getPersistenceMode();
- value.putString(persistenceMode != null ? persistenceMode.name() : null);
+ putUTFOrNull(value, persistenceMode != null ? persistenceMode.name() : null);
+ }
+
+ private void putUTFOrNull(Value value, @Nullable String utfOrNull) {
+ if (utfOrNull != null) {
+ value.putUTF(utfOrNull);
+ } else {
+ value.putNull();
+ }
}
public Object get(Value value, Class clazz, CoderContext context) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java
index 75d0e31932c..801744de2c7 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/AnalyzerMeasureCache.java
@@ -19,10 +19,10 @@
*/
package org.sonar.batch.scan2;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-
import com.google.common.base.Preconditions;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.batch.index.Cache;
import org.sonar.batch.index.Cache.Entry;
import org.sonar.batch.index.Caches;
@@ -35,7 +35,8 @@ public class AnalyzerMeasureCache implements BatchComponent {
// project key -> component key -> metric key -> measure
private final Cache<DefaultMeasure> cache;
- public AnalyzerMeasureCache(Caches caches) {
+ public AnalyzerMeasureCache(Caches caches, MetricFinder metricFinder) {
+ caches.registerValueCoder(DefaultMeasure.class, new DefaultMeasureValueCoder(metricFinder));
cache = caches.createCache("measures");
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java
new file mode 100644
index 00000000000..8b82a684dd0
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultMeasureValueCoder.java
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.scan2;
+
+import com.persistit.Value;
+import com.persistit.encoding.CoderContext;
+import com.persistit.encoding.ValueCoder;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.measure.MetricFinder;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder;
+
+import java.io.Serializable;
+
+class DefaultMeasureValueCoder implements ValueCoder {
+
+ private MetricFinder metricFinder;
+
+ public DefaultMeasureValueCoder(MetricFinder metricFinder) {
+ this.metricFinder = metricFinder;
+ }
+
+ @Override
+ public void put(Value value, Object object, CoderContext context) {
+ DefaultMeasure m = (DefaultMeasure) object;
+ value.put(m.inputFile());
+ value.putUTF(m.metric().key());
+ value.put(m.value());
+ }
+
+ @Override
+ public Object get(Value value, Class clazz, CoderContext context) {
+ DefaultMeasureBuilder builder = new DefaultMeasureBuilder();
+ InputFile f = (InputFile) value.get();
+ if (f != null) {
+ builder.onFile(f);
+ } else {
+ builder.onProject();
+ }
+ Metric m = metricFinder.findByKey(value.getString());
+ builder.forMetric(m);
+ builder.withValue((Serializable) value.get());
+ return builder.build();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
index dcd6efd1ca4..73d6429bfcd 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/DefaultSensorContext.java
@@ -28,6 +28,8 @@ import org.sonar.api.batch.measure.Metric;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.DefaultActiveRule;
import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.duplication.DuplicationBuilder;
+import org.sonar.api.batch.sensor.duplication.TokenBuilder;
import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.IssueBuilder;
@@ -41,12 +43,17 @@ import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
import org.sonar.api.config.Settings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DefaultDuplicationBuilder;
+import org.sonar.batch.duplication.DefaultTokenBuilder;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.highlighting.DefaultHighlightingBuilder;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.issue.IssueFilters;
import org.sonar.batch.scan.SensorContextAdaptor;
import org.sonar.batch.symbol.DefaultSymbolTableBuilder;
import org.sonar.core.component.ComponentKeys;
+import org.sonar.duplications.internal.pmd.PmdBlockChunker;
import java.io.Serializable;
@@ -60,9 +67,12 @@ public class DefaultSensorContext implements SensorContext {
private final ActiveRules activeRules;
private final IssueFilters issueFilters;
private final ComponentDataCache componentDataCache;
+ private final BlockCache blockCache;
+ private final DuplicationCache duplicationCache;
public DefaultSensorContext(ProjectDefinition def, AnalyzerMeasureCache measureCache, AnalyzerIssueCache issueCache,
- Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache) {
+ Settings settings, FileSystem fs, ActiveRules activeRules, IssueFilters issueFilters, ComponentDataCache componentDataCache,
+ BlockCache blockCache, DuplicationCache duplicationCache) {
this.def = def;
this.measureCache = measureCache;
this.issueCache = issueCache;
@@ -71,6 +81,8 @@ public class DefaultSensorContext implements SensorContext {
this.activeRules = activeRules;
this.issueFilters = issueFilters;
this.componentDataCache = componentDataCache;
+ this.blockCache = blockCache;
+ this.duplicationCache = duplicationCache;
}
@Override
@@ -175,4 +187,34 @@ public class DefaultSensorContext implements SensorContext {
return new DefaultSymbolTableBuilder(((DefaultInputFile) inputFile).key(), componentDataCache);
}
+ @Override
+ public TokenBuilder tokenBuilder(InputFile inputFile) {
+ PmdBlockChunker blockChunker = new PmdBlockChunker(getBlockSize(inputFile.language()));
+
+ return new DefaultTokenBuilder(inputFile, blockCache, blockChunker);
+ }
+
+ @Override
+ public DuplicationBuilder duplicationBuilder(InputFile inputFile) {
+ return new DefaultDuplicationBuilder(inputFile, duplicationCache);
+ }
+
+ private int getBlockSize(String languageKey) {
+ int blockSize = settings.getInt("sonar.cpd." + languageKey + ".minimumLines");
+ if (blockSize == 0) {
+ blockSize = getDefaultBlockSize(languageKey);
+ }
+ return blockSize;
+ }
+
+ private static int getDefaultBlockSize(String languageKey) {
+ if ("cobol".equals(languageKey)) {
+ return 30;
+ } else if ("abap".equals(languageKey) || "natur".equals(languageKey)) {
+ return 20;
+ } else {
+ return 10;
+ }
+ }
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
index e13fca37d28..b0a2b3e0af5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/ProjectScanContainer.java
@@ -33,6 +33,8 @@ import org.sonar.api.scan.filesystem.PathResolver;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
import org.sonar.batch.bootstrap.ExtensionUtils;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.index.Caches;
import org.sonar.batch.index.ComponentDataCache;
import org.sonar.batch.languages.DefaultLanguagesReferential;
@@ -107,6 +109,10 @@ public class ProjectScanContainer extends ComponentContainer {
ComponentDataCache.class,
+ // Duplications
+ BlockCache.class,
+ DuplicationCache.class,
+
ScanTaskObservers.class);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan2/SensorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan2/SensorsExecutor.java
index d437eadb6fd..ea872c4c1bf 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan2/SensorsExecutor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan2/SensorsExecutor.java
@@ -53,7 +53,7 @@ public class SensorsExecutor implements BatchComponent {
continue;
}
- LOG.info("Execute analyzer: " + descriptor.name());
+ LOG.info("Execute sensor: " + descriptor.name());
executeSensor(context, analyzer);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java
new file mode 100644
index 00000000000..ade701fce45
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/duplication/DuplicationCacheTest.java
@@ -0,0 +1,82 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.duplication;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.batch.index.Caches;
+import org.sonar.batch.index.CachesTest;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DuplicationCacheTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ Caches caches;
+
+ @Before
+ public void start() throws Exception {
+ caches = CachesTest.createCacheOnTemp(temp);
+ caches.start();
+ }
+
+ @After
+ public void stop() {
+ caches.stop();
+ }
+
+ @Test
+ public void should_add_clone_groups() throws Exception {
+ DuplicationCache cache = new DuplicationCache(caches);
+
+ DuplicationGroup group1 = new DuplicationGroup(new DuplicationGroup.Block("foo", 1, 2))
+ .addDuplicate(new DuplicationGroup.Block("foo", 1, 2))
+ .addDuplicate(new DuplicationGroup.Block("foo2", 12, 22))
+ .addDuplicate(new DuplicationGroup.Block("foo3", 13, 23));
+
+ DuplicationGroup group2 = new DuplicationGroup(new DuplicationGroup.Block("2foo", 1, 2))
+ .addDuplicate(new DuplicationGroup.Block("2foo", 1, 2))
+ .addDuplicate(new DuplicationGroup.Block("2foo2", 12, 22))
+ .addDuplicate(new DuplicationGroup.Block("2foo3", 13, 23));
+
+ assertThat(cache.entries()).hasSize(0);
+
+ cache.put("foo", new ArrayList<DuplicationGroup>(Arrays.asList(group1, group2)));
+
+ assertThat(cache.entries()).hasSize(1);
+
+ ArrayList<DuplicationGroup> entry = cache.byComponent("foo");
+ assertThat(entry.get(0).originBlock().resourceKey()).isEqualTo("foo");
+
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
index fe8a1a45a65..dfed349e696 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
@@ -27,6 +27,7 @@ import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.MetricFinder;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Directory;
@@ -35,10 +36,14 @@ import org.sonar.api.resources.Project;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RulePriority;
+import org.sonar.batch.duplication.DuplicationCache;
+import org.sonar.batch.duplication.DuplicationGroup;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.core.persistence.AbstractDaoTestCase;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -70,6 +75,8 @@ public class MeasurePersisterTest extends AbstractDaoTestCase {
public void mockResourcePersister() {
snapshotCache = mock(SnapshotCache.class);
measureCache = mock(MeasureCache.class);
+ DuplicationCache duplicationCache = mock(DuplicationCache.class);
+ when(duplicationCache.entries()).thenReturn(Collections.<Cache.Entry<ArrayList<DuplicationGroup>>>emptyList());
ResourceCache resourceCache = mock(ResourceCache.class);
when(snapshotCache.get("foo")).thenReturn(projectSnapshot);
when(snapshotCache.get("foo:org/foo")).thenReturn(packageSnapshot);
@@ -77,7 +84,7 @@ public class MeasurePersisterTest extends AbstractDaoTestCase {
when(resourceCache.get("foo:org/foo/Bar.java")).thenReturn(aFile);
when(resourceCache.get("foo:org/foo")).thenReturn(aDirectory);
- measurePersister = new MeasurePersister(getMyBatis(), ruleFinder, measureCache, snapshotCache, resourceCache);
+ measurePersister = new MeasurePersister(getMyBatis(), ruleFinder, measureCache, snapshotCache, resourceCache, duplicationCache, mock(MetricFinder.class));
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java
index 674f472d0b5..19d7aea020a 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/FileSystemMediumTest.java
@@ -31,8 +31,8 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
index 259b2ffcec0..b9fab7ba450 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/highlighting/HighlightingMediumTest.java
@@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
index 875e7e6d510..f3eebf971e3 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
@@ -29,8 +29,8 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java
index fdf6b15e857..fb3e8d16edd 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java
@@ -28,8 +28,8 @@ import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.internal.DefaultInputDir;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
index bb93ae4b7ba..146b89eb316 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
@@ -30,7 +30,7 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasureBuilder;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
index c3875c625f3..8772d371ba2 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/symbol/SymbolMediumTest.java
@@ -28,7 +28,7 @@ import org.junit.rules.TemporaryFolder;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskResult;
-import org.sonar.batch.mediumtest.xoo.plugin.XooPlugin;
+import org.sonar.xoo.XooPlugin;
import java.io.File;
import java.io.IOException;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/XooPlugin.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/XooPlugin.java
deleted file mode 100644
index 78718da3682..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/XooPlugin.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin;
-
-import org.sonar.api.SonarPlugin;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.lang.MeasureSensor;
-import org.sonar.batch.mediumtest.xoo.plugin.lang.ScmActivitySensor;
-import org.sonar.batch.mediumtest.xoo.plugin.lang.SymbolReferencesSensor;
-import org.sonar.batch.mediumtest.xoo.plugin.lang.SyntaxHighlightingSensor;
-import org.sonar.batch.mediumtest.xoo.plugin.rule.CreateIssueByInternalKeySensor;
-import org.sonar.batch.mediumtest.xoo.plugin.rule.OneIssueOnDirPerFileSensor;
-import org.sonar.batch.mediumtest.xoo.plugin.rule.OneIssuePerLineSensor;
-
-import java.util.Arrays;
-import java.util.List;
-
-public final class XooPlugin extends SonarPlugin {
-
- @Override
- public List getExtensions() {
- return Arrays.asList(
- // language
- MeasureSensor.class,
- ScmActivitySensor.class,
- SyntaxHighlightingSensor.class,
- SymbolReferencesSensor.class,
- Xoo.class,
-
- // sensors
- OneIssuePerLineSensor.class,
- OneIssueOnDirPerFileSensor.class,
- CreateIssueByInternalKeySensor.class
- );
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/MeasureSensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/MeasureSensor.java
deleted file mode 100644
index c28ebd5a05c..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/MeasureSensor.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.lang;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.measure.MetricFinder;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.MeasureBuilder;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * Parse files *.xoo.measures
- */
-public class MeasureSensor implements Sensor {
-
- private static final String MEASURES_EXTENSION = ".measures";
-
- private MetricFinder metricFinder;
-
- public MeasureSensor(MetricFinder metricFinder) {
- this.metricFinder = metricFinder;
- }
-
- private void processFileMeasures(InputFile inputFile, SensorContext context) {
- File ioFile = inputFile.file();
- File measureFile = new File(ioFile.getParentFile(), ioFile.getName() + MEASURES_EXTENSION);
- if (measureFile.exists()) {
- XooConstants.LOG.debug("Processing " + measureFile.getAbsolutePath());
- try {
- List<String> lines = FileUtils.readLines(measureFile, context.fileSystem().encoding().name());
- int lineNumber = 0;
- for (String line : lines) {
- lineNumber++;
- if (StringUtils.isBlank(line)) {
- continue;
- }
- if (line.startsWith("#")) {
- continue;
- }
- try {
- String metricKey = StringUtils.substringBefore(line, ":");
- String value = line.substring(metricKey.length() + 1);
- context.addMeasure(createMeasure(context, inputFile, metricKey, value));
- } catch (Exception e) {
- throw new IllegalStateException("Error processing line " + lineNumber + " of file " + measureFile.getAbsolutePath(), e);
- }
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- private Measure<?> createMeasure(SensorContext context, InputFile xooFile, String metricKey, String value) {
- org.sonar.api.batch.measure.Metric<Serializable> metric = metricFinder.findByKey(metricKey);
- MeasureBuilder<Serializable> builder = context.measureBuilder()
- .forMetric(metric)
- .onFile(xooFile);
- if (Boolean.class.equals(metric.valueType())) {
- builder.withValue(Boolean.parseBoolean(value));
- } else if (Integer.class.equals(metric.valueType())) {
- builder.withValue(Integer.valueOf(value));
- } else if (Double.class.equals(metric.valueType())) {
- builder.withValue(Double.valueOf(value));
- } else if (String.class.equals(metric.valueType())) {
- builder.withValue(value);
- } else if (Long.class.equals(metric.valueType())) {
- builder.withValue(Long.valueOf(value));
- } else {
- throw new UnsupportedOperationException("Unsupported type :" + metric.valueType());
- }
- return builder.build();
- }
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("Xoo Measure Sensor")
- .provides(CoreMetrics.LINES)
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- processFileMeasures(file, context);
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/ScmActivitySensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/ScmActivitySensor.java
deleted file mode 100644
index b3352dba62a..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/ScmActivitySensor.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.lang;
-
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.FileLinesContext;
-import org.sonar.api.measures.FileLinesContextFactory;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Date;
-import java.util.List;
-
-public class ScmActivitySensor implements Sensor {
-
- private static final Logger LOG = LoggerFactory.getLogger(ScmActivitySensor.class);
-
- private static final String SCM_EXTENSION = ".scm";
-
- private final FileSystem fs;
- private final FileLinesContextFactory fileLinesContextFactory;
-
- public ScmActivitySensor(FileLinesContextFactory fileLinesContextFactory, FileSystem fileSystem) {
- this.fs = fileSystem;
- this.fileLinesContextFactory = fileLinesContextFactory;
- }
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name(this.getClass().getSimpleName())
- .provides(CoreMetrics.SCM_AUTHORS_BY_LINE,
- CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
- CoreMetrics.SCM_REVISIONS_BY_LINE)
- .workOnLanguages(Xoo.KEY);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(Xoo.KEY))) {
- processFile(inputFile);
- }
-
- }
-
- @VisibleForTesting
- protected void processFile(InputFile inputFile) {
- File ioFile = inputFile.file();
- File scmDataFile = new java.io.File(ioFile.getParentFile(), ioFile.getName() + SCM_EXTENSION);
- if (!scmDataFile.exists()) {
- LOG.debug("Skipping SCM data injection for " + inputFile.relativePath());
- return;
- }
-
- FileLinesContext fileLinesContext = fileLinesContextFactory.createFor(inputFile);
- try {
- List<String> lines = FileUtils.readLines(scmDataFile, Charsets.UTF_8.name());
- int lineNumber = 0;
- for (String line : lines) {
- lineNumber++;
- if (StringUtils.isNotBlank(line)) {
- // revision,author,dateTime
- String[] fields = StringUtils.split(line, ',');
- if (fields.length < 3) {
- throw new IllegalStateException("Not enough fields on line " + lineNumber);
- }
- String revision = fields[0];
- String author = fields[1];
- // Will throw an exception, when date is not in format "yyyy-MM-dd"
- Date date = DateUtils.parseDate(fields[2]);
-
- fileLinesContext.setStringValue(CoreMetrics.SCM_REVISIONS_BY_LINE_KEY, lineNumber, revision);
- fileLinesContext.setStringValue(CoreMetrics.SCM_AUTHORS_BY_LINE_KEY, lineNumber, author);
- fileLinesContext.setStringValue(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, lineNumber, DateUtils.formatDateTime(date));
- }
- }
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- fileLinesContext.save();
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SymbolReferencesSensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SymbolReferencesSensor.java
deleted file mode 100644
index 91fa61e5c78..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SymbolReferencesSensor.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.lang;
-
-import com.google.common.base.Splitter;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.symbol.Symbol;
-import org.sonar.api.batch.sensor.symbol.SymbolTableBuilder;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Parse files *.xoo.symbol
- */
-public class SymbolReferencesSensor implements Sensor {
-
- private static final String SYMBOL_EXTENSION = ".symbol";
-
- private void processFileHighlighting(InputFile inputFile, SensorContext context) {
- File ioFile = inputFile.file();
- File symbolFile = new File(ioFile.getParentFile(), ioFile.getName() + SYMBOL_EXTENSION);
- if (symbolFile.exists()) {
- XooConstants.LOG.debug("Processing " + symbolFile.getAbsolutePath());
- try {
- List<String> lines = FileUtils.readLines(symbolFile, context.fileSystem().encoding().name());
- int lineNumber = 0;
- SymbolTableBuilder symbolTableBuilder = context.symbolTableBuilder(inputFile);
- for (String line : lines) {
- lineNumber++;
- if (StringUtils.isBlank(line)) {
- continue;
- }
- if (line.startsWith("#")) {
- continue;
- }
- try {
- Iterator<String> split = Splitter.on(",").split(line).iterator();
- int startOffset = Integer.parseInt(split.next());
- int endOffset = Integer.parseInt(split.next());
- Symbol s = symbolTableBuilder.newSymbol(startOffset, endOffset);
- while (split.hasNext()) {
- symbolTableBuilder.newReference(s, Integer.parseInt(split.next()));
- }
- } catch (Exception e) {
- throw new IllegalStateException("Error processing line " + lineNumber + " of file " + symbolFile.getAbsolutePath(), e);
- }
- }
- symbolTableBuilder.done();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("Xoo Highlighting Sensor")
- .provides(CoreMetrics.LINES)
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- processFileHighlighting(file, context);
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SyntaxHighlightingSensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SyntaxHighlightingSensor.java
deleted file mode 100644
index 5b78759dbb9..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/lang/SyntaxHighlightingSensor.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.lang;
-
-import com.google.common.base.Splitter;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.highlighting.HighlightingBuilder;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Parse files *.xoo.highlighting
- */
-public class SyntaxHighlightingSensor implements Sensor {
-
- private static final String HIGHLIGHTING_EXTENSION = ".highlighting";
-
- private void processFileHighlighting(InputFile inputFile, SensorContext context) {
- File ioFile = inputFile.file();
- File highlightingFile = new File(ioFile.getParentFile(), ioFile.getName() + HIGHLIGHTING_EXTENSION);
- if (highlightingFile.exists()) {
- XooConstants.LOG.debug("Processing " + highlightingFile.getAbsolutePath());
- try {
- List<String> lines = FileUtils.readLines(highlightingFile, context.fileSystem().encoding().name());
- int lineNumber = 0;
- HighlightingBuilder highlightingBuilder = context.highlightingBuilder(inputFile);
- for (String line : lines) {
- lineNumber++;
- if (StringUtils.isBlank(line)) {
- continue;
- }
- if (line.startsWith("#")) {
- continue;
- }
- try {
- Iterator<String> split = Splitter.on(":").split(line).iterator();
- int startOffset = Integer.parseInt(split.next());
- int endOffset = Integer.parseInt(split.next());
- HighlightingBuilder.TypeOfText type = HighlightingBuilder.TypeOfText.forCssClass(split.next());
- highlightingBuilder.highlight(startOffset, endOffset, type);
- } catch (Exception e) {
- throw new IllegalStateException("Error processing line " + lineNumber + " of file " + highlightingFile.getAbsolutePath(), e);
- }
- }
- highlightingBuilder.done();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("Xoo Highlighting Sensor")
- .provides(CoreMetrics.LINES)
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- processFileHighlighting(file, context);
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java
deleted file mode 100644
index 1ee150a5c01..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/CreateIssueByInternalKeySensor.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.rule;
-
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.rule.ActiveRule;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-public class CreateIssueByInternalKeySensor implements Sensor {
-
- private static final String INTERNAL_KEY_PROPERTY = "sonar.xoo.internalKey";
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("CreateIssueByInternalKeySensor")
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- createIssues(file, context);
- }
- }
-
- private void createIssues(InputFile file, SensorContext context) {
- ActiveRule rule = context.activeRules().findByInternalKey(XooConstants.REPOSITORY_KEY,
- context.settings().getString(INTERNAL_KEY_PROPERTY));
- if (rule != null) {
- context.addIssue(context.issueBuilder()
- .ruleKey(rule.ruleKey())
- .onFile(file)
- .message("This issue is generated on each file")
- .build());
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssueOnDirPerFileSensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssueOnDirPerFileSensor.java
deleted file mode 100644
index 2a02ebef9dd..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssueOnDirPerFileSensor.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.rule;
-
-import org.sonar.api.batch.fs.InputDir;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-public class OneIssueOnDirPerFileSensor implements Sensor {
-
- public static final String RULE_KEY = "OneIssueOnDirPerFile";
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("One Issue On Dir Per File")
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- createIssues(file, context);
- }
- }
-
- private void createIssues(InputFile file, SensorContext context) {
- RuleKey ruleKey = RuleKey.of(XooConstants.REPOSITORY_KEY, RULE_KEY);
- InputDir inputDir = context.fileSystem().inputDir(file.file().getParentFile());
- if (inputDir != null) {
- context.addIssue(context.issueBuilder()
- .ruleKey(ruleKey)
- .onDir(inputDir)
- .message("This issue is generated for file " + file.relativePath())
- .build());
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssuePerLineSensor.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssuePerLineSensor.java
deleted file mode 100644
index 2a811068e54..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/xoo/plugin/rule/OneIssuePerLineSensor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch.mediumtest.xoo.plugin.rule;
-
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.issue.IssueBuilder;
-import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.batch.mediumtest.xoo.plugin.base.Xoo;
-import org.sonar.batch.mediumtest.xoo.plugin.base.XooConstants;
-
-public class OneIssuePerLineSensor implements Sensor {
-
- public static final String RULE_KEY = "OneIssuePerLine";
- private static final String EFFORT_TO_FIX_PROPERTY = "sonar.oneIssuePerLine.effortToFix";
- private static final String FORCE_SEVERITY_PROPERTY = "sonar.oneIssuePerLine.forceSeverity";
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor
- .name("One Issue Per Line")
- .dependsOn(CoreMetrics.LINES)
- .workOnLanguages(Xoo.KEY)
- .workOnFileTypes(InputFile.Type.MAIN, InputFile.Type.TEST);
- }
-
- @Override
- public void execute(SensorContext context) {
- for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) {
- createIssues(file, context);
- }
- }
-
- private void createIssues(InputFile file, SensorContext context) {
- RuleKey ruleKey = RuleKey.of(XooConstants.REPOSITORY_KEY, RULE_KEY);
- Measure<Integer> linesMeasure = context.getMeasure(file, CoreMetrics.LINES);
- if (linesMeasure == null) {
- LoggerFactory.getLogger(getClass()).warn("Missing measure " + CoreMetrics.LINES_KEY + " on " + file);
- } else {
- IssueBuilder issueBuilder = context.issueBuilder();
- for (int line = 1; line <= (Integer) linesMeasure.value(); line++) {
- context.addIssue(issueBuilder
- .ruleKey(ruleKey)
- .onFile(file)
- .atLine(line)
- .effortToFix(context.settings().getDouble(EFFORT_TO_FIX_PROPERTY))
- .severity(context.settings().getString(FORCE_SEVERITY_PROPERTY))
- .message("This issue is generated on each line")
- .build());
- }
- }
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
index 7b7eb21ee58..a93bf9bae83 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/SensorContextAdapterTest.java
@@ -42,6 +42,8 @@ import org.sonar.api.measures.MetricFinder;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.rule.RuleKey;
+import org.sonar.batch.duplication.BlockCache;
+import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.index.ComponentDataCache;
import static org.fest.assertions.Assertions.assertThat;
@@ -71,8 +73,9 @@ public class SensorContextAdapterTest {
settings = new Settings();
resourcePerspectives = mock(ResourcePerspectives.class);
ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ BlockCache blockCache = mock(BlockCache.class);
adaptor = new SensorContextAdaptor(sensorContext, metricFinder, new Project("myProject"),
- resourcePerspectives, settings, fs, activeRules, componentDataCache);
+ resourcePerspectives, settings, fs, activeRules, componentDataCache, blockCache, mock(DuplicationCache.class));
}
@Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
index f1bf43f37e3..03dbec79af8 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputPathCacheTest.java
@@ -24,6 +24,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.InputFile.Status;
+import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.fs.InputPath;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
@@ -55,7 +57,18 @@ public class InputPathCacheTest {
InputPathCache cache = new InputPathCache(caches);
DefaultInputFile fooFile = new DefaultInputFile("src/main/java/Foo.java").setFile(temp.newFile("Foo.java"));
cache.put("struts", fooFile);
- cache.put("struts-core", new DeprecatedDefaultInputFile("src/main/java/Bar.java").setFile(temp.newFile("Bar.java")));
+ cache.put("struts-core", new DeprecatedDefaultInputFile("src/main/java/Bar.java")
+ .setBasedir(temp.newFolder())
+ .setDeprecatedKey("foo")
+ .setSourceDirAbsolutePath("foo")
+ .setPathRelativeToSourceDir("foo")
+ .setLanguage("bla")
+ .setType(Type.MAIN)
+ .setStatus(Status.ADDED)
+ .setHash("xyz")
+ .setLines(1)
+ .setKey("foo")
+ .setFile(temp.newFile("Bar.java")));
assertThat(cache.getFile("struts", "src/main/java/Foo.java").relativePath())
.isEqualTo("src/main/java/Foo.java");
@@ -75,5 +88,4 @@ public class InputPathCacheTest {
assertThat(cache.filesByModule("struts-core")).hasSize(1);
assertThat(cache.all()).hasSize(1);
}
-
}