<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
- <version>18.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.4</version>
</dependency>
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- <version>3.3.2</version>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
- <version>3.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
package org.sonar.xoo.coverage;
import com.google.common.base.Splitter;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+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.utils.log.Loggers;
import org.sonar.xoo.Xoo;
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
public abstract class AbstractCoverageSensor implements Sensor {
private static final Logger LOG = Loggers.get(AbstractCoverageSensor.class);
import java.io.Serializable;
import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+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 java.util.Iterator;
import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+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 java.util.Iterator;
import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+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;
package org.sonar.xoo.scm;
import com.google.common.annotations.VisibleForTesting;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.batch.scm.BlameCommand;
-import org.sonar.api.batch.scm.BlameLine;
-import org.sonar.api.utils.DateUtils;
-
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.scm.BlameCommand;
+import org.sonar.api.batch.scm.BlameLine;
+import org.sonar.api.utils.DateUtils;
public class XooBlameCommand extends BlameCommand {
package org.sonar.xoo.test;
import com.google.common.base.Splitter;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.DependsUpon;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.utils.log.Loggers;
import org.sonar.xoo.Xoo;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
/**
* Parse files *.xoo.testcoverage
*/
package org.sonar.xoo.test;
import com.google.common.base.Splitter;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.DependedUpon;
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.utils.log.Loggers;
import org.sonar.xoo.Xoo;
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
/**
* Parse files *.xoo.test
*/
}
private List<FilePathWithHashDto> searchFilesWithHashAndRevision(DbSession session, ComponentDto module) {
- return module.isRootProject() ?
- dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid())
+ return module.isRootProject() ? dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid())
: dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid());
}
}
}
- private void addSettingsToChildrenModules(ProjectRepositories ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings,
+ private static void addSettingsToChildrenModules(ProjectRepositories ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings,
boolean hasScanPerm) {
Map<String, String> currentParentProperties = newHashMap();
currentParentProperties.putAll(parentProperties);
return results;
}
- private void evaluateClass(Class extensionClass, Class annotationClass, List<Object> results) {
+ private static void evaluateClass(Class extensionClass, Class annotationClass, List<Object> results) {
Annotation annotation = extensionClass.getAnnotation(annotationClass);
if (annotation != null) {
if (annotation.annotationType().isAssignableFrom(DependsUpon.class)) {
* @param o
* @return
*/
- private String toStringOrSimpleName(Object o) {
+ private static String toStringOrSimpleName(Object o) {
String toString = o.toString();
if (toString == null || toString.startsWith(o.getClass().getName())) {
return o.getClass().getSimpleName();
*/
package org.sonar.batch.scan.report;
-import org.sonar.batch.issue.tracking.TrackedIssue;
-
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.Properties;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.issue.IssueCache;
+import org.sonar.batch.issue.tracking.TrackedIssue;
import org.sonar.batch.scan.filesystem.InputPathCache;
@Properties({
- @Property(key = ConsoleReport.CONSOLE_REPORT_ENABLED_KEY, name = "Enable console report", description = "Set this to true to generate a report in console output",
- type = PropertyType.BOOLEAN, defaultValue = "false")})
+ @Property(key = ConsoleReport.CONSOLE_REPORT_ENABLED_KEY, defaultValue = "false", name = "Enable console report",
+ description = "Set this to true to generate a report in console output", type = PropertyType.BOOLEAN)})
public class ConsoleReport implements Reporter {
@VisibleForTesting
LOG.info(sb.toString());
}
- private void printNewIssues(Report r, StringBuilder sb) {
+ private static void printNewIssues(Report r, StringBuilder sb) {
int newIssues = r.totalNewIssues;
if (newIssues > 0) {
sb.append(StringUtils.leftPad("+" + newIssues, LEFT_PAD)).append(" issue" + (newIssues > 1 ? "s" : "")).append("\n\n");
import com.google.common.collect.Maps;
import freemarker.template.Template;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.Properties;
-import org.sonar.api.Property;
-import org.sonar.api.PropertyType;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.config.Settings;
-
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.net.URISyntaxException;
import java.util.Map;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.PropertyType;
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.config.Settings;
@Properties({
- @Property(key = HtmlReport.HTML_REPORT_ENABLED_KEY, name = "Enable HTML report", description = "Set this to true to generate an HTML report",
- type = PropertyType.BOOLEAN, defaultValue = "false"),
- @Property(key = HtmlReport.HTML_REPORT_LOCATION_KEY, name = "HTML Report location",
- description = "Location of the generated report. Can be absolute or relative to working directory",
- type = PropertyType.STRING, defaultValue = HtmlReport.HTML_REPORT_LOCATION_DEFAULT, global = false, project = false),
- @Property(key = HtmlReport.HTML_REPORT_NAME_KEY, name = "HTML Report name",
- description = "Name of the generated report. Will be suffixed by .html or -light.html",
- type = PropertyType.STRING, defaultValue = HtmlReport.HTML_REPORT_NAME_DEFAULT, global = false, project = false),
- @Property(key = HtmlReport.HTML_REPORT_LIGHTMODE_ONLY, name = "Html report in light mode only", project = true,
- description = "Set this to true to only generate the new issues report (light report)",
- type = PropertyType.BOOLEAN, defaultValue = "false")})
+ @Property(key = HtmlReport.HTML_REPORT_ENABLED_KEY, defaultValue = "false", name = "Enable HTML report", description = "Set this to true to generate an HTML report",
+ type = PropertyType.BOOLEAN),
+ @Property(key = HtmlReport.HTML_REPORT_LOCATION_KEY, defaultValue = HtmlReport.HTML_REPORT_LOCATION_DEFAULT, name = "HTML Report location",
+ description = "Location of the generated report. Can be absolute or relative to working directory", project = false, global = false, type = PropertyType.STRING),
+ @Property(key = HtmlReport.HTML_REPORT_NAME_KEY, defaultValue = HtmlReport.HTML_REPORT_NAME_DEFAULT, name = "HTML Report name",
+ description = "Name of the generated report. Will be suffixed by .html or -light.html", project = false, global = false, type = PropertyType.STRING),
+ @Property(key = HtmlReport.HTML_REPORT_LIGHTMODE_ONLY, defaultValue = "false", name = "Html report in light mode only",
+ description = "Set this to true to only generate the new issues report (light report)", project = true, type = PropertyType.BOOLEAN)})
public class HtmlReport implements Reporter {
private static final Logger LOG = LoggerFactory.getLogger(HtmlReport.class);
if (!reportFileDir.isAbsolute()) {
reportFileDir = new File(fs.workDir(), reportFileDirStr);
}
- if (reportFileDirStr.endsWith(".html")) {
+ if (StringUtils.endsWith(reportFileDirStr, ".html")) {
LOG.warn(HTML_REPORT_LOCATION_KEY + " should indicate a directory. Using parent folder.");
reportFileDir = reportFileDir.getParentFile();
}
import com.google.common.base.Joiner;
import java.util.LinkedHashMap;
import java.util.Map;
+import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
import org.sonar.api.CoreProperties;
import org.sonar.api.Properties;
@Property(
key = ScmConfiguration.FORCE_RELOAD_KEY,
defaultValue = "false",
- type = PropertyType.BOOLEAN,
name = "Force reloading of SCM information for all files",
description = "By default only files modified since previous analysis are inspected. Set this parameter to true to force the reloading.",
- module = false,
+ category = CoreProperties.CATEGORY_SCM,
project = false,
+ module = false,
global = false,
- category = CoreProperties.CATEGORY_SCM)
+ type = PropertyType.BOOLEAN)
})
@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
@BatchSide
if (providerPerKey.containsKey(forcedProviderKey)) {
this.provider = providerPerKey.get(forcedProviderKey);
} else {
- String supportedProviders = providerPerKey.isEmpty() ? "No SCM provider installed" : "Supported SCM providers are " + Joiner.on(",").join(providerPerKey.keySet());
+ String supportedProviders = providerPerKey.isEmpty() ? "No SCM provider installed" : ("Supported SCM providers are " + Joiner.on(",").join(providerPerKey.keySet()));
throw new IllegalArgumentException("SCM provider was set to \"" + forcedProviderKey + "\" but no SCM provider found for this key. " + supportedProviders);
}
}
private void considerOldScmUrl() {
if (settings.hasKey(CoreProperties.LINKS_SOURCES_DEV)) {
String url = settings.getString(CoreProperties.LINKS_SOURCES_DEV);
- if (url.startsWith("scm:")) {
+ if (StringUtils.startsWith(url, "scm:")) {
String[] split = url.split(":");
if (split.length > 1) {
setProviderIfSupported(split[1]);
}
}
- private void log(String message) {
+ private static void log(String message) {
synchronized (LOG) {
LOG.info(message);
LOG.notifyAll();
return this;
}
- private String getName(Object extension) {
+ private static String getName(Object extension) {
if (extension instanceof Class) {
return ((Class<?>) extension).getName();
}
return result;
}
- private void addBlock(int blockId, Block block, Map<Integer, StringBuilder> dupPerLine) {
+ private static void addBlock(int blockId, Block block, Map<Integer, StringBuilder> dupPerLine) {
int currentLine = block.start;
for (int i = 0; i < block.length; i++) {
if (dupPerLine.get(currentLine) == null) {
}
@Override
- public NewCpdTokens addToken(TextRange range, String image) {
+ public DefaultCpdTokens addToken(TextRange range, String image) {
Preconditions.checkNotNull(range, "Range should not be null");
+ Preconditions.checkNotNull(image, "Image should not be null");
Preconditions.checkState(inputFile != null, "Call onFile() first");
- Preconditions.checkState(lastRange == null || lastRange.end().compareTo(range.start()) >= 0,
- "Tokens of file %s should be provided in order. \nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
+ Preconditions.checkState(lastRange == null || lastRange.end().compareTo(range.start()) <= 0,
+ "Tokens of file %s should be provided in order.\nPrevious token: %s\nLast token: %s", inputFile, lastRange, range);
String value = image;
}
currentIndex++;
sb.append(value);
+ lastRange = range;
return this;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.api.batch.sensor.cpd.internal;
+
+import org.junit.Test;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DefaultCpdTokensTest {
+
+ private static final DefaultInputFile INPUT_FILE = new DefaultInputFile("foo", "src/Foo.java")
+ .setLines(2)
+ .setOriginalLineOffsets(new int[] {0, 50})
+ .setLastValidOffset(100);
+
+ @Test
+ public void save_no_tokens() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(INPUT_FILE);
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.inputFile()).isEqualTo(INPUT_FILE);
+ }
+
+ @Test
+ public void save_one_token() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(INPUT_FILE)
+ .addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo");
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.getTokenLines()).extracting("value", "startLine", "hashCode", "startUnit", "endUnit").containsExactly(tuple("foo", 1, "foo".hashCode(), 1, 1));
+ }
+
+ @Test
+ public void save_many_tokens() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(INPUT_FILE)
+ .addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo")
+ .addToken(INPUT_FILE.newRange(1, 6, 1, 10), "bar")
+ .addToken(INPUT_FILE.newRange(1, 20, 1, 25), "biz")
+ .addToken(INPUT_FILE.newRange(2, 1, 2, 10), "next");
+
+ tokens.save();
+
+ verify(sensorStorage).store(tokens);
+
+ assertThat(tokens.getTokenLines())
+ .extracting("value", "startLine", "hashCode", "startUnit", "endUnit")
+ .containsExactly(
+ tuple("foobarbiz", 1, "foobarbiz".hashCode(), 1, 3),
+ tuple("next", 2, "next".hashCode(), 4, 4));
+ }
+
+ @Test
+ public void basic_validation() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage);
+ try {
+ tokens.save();
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Call onFile() first");
+ }
+ try {
+ tokens.addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Call onFile() first");
+ }
+ try {
+ tokens.addToken(null, "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Range should not be null");
+ }
+ try {
+ tokens.addToken(INPUT_FILE.newRange(1, 2, 1, 5), null);
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Image should not be null");
+ }
+ }
+
+ @Test
+ public void validate_tokens_order() {
+ SensorStorage sensorStorage = mock(SensorStorage.class);
+ DefaultCpdTokens tokens = new DefaultCpdTokens(sensorStorage)
+ .onFile(INPUT_FILE)
+ .addToken(INPUT_FILE.newRange(1, 6, 1, 10), "bar");
+
+ try {
+ tokens.addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo");
+ fail("Expected exception");
+ } catch (Exception e) {
+ assertThat(e).hasMessage("Tokens of file [moduleKey=foo, relative=src/Foo.java, basedir=null] should be provided in order.\n" +
+ "Previous token: Range[from [line=1, lineOffset=6] to [line=1, lineOffset=10]]\n" +
+ "Last token: Range[from [line=1, lineOffset=2] to [line=1, lineOffset=5]]");
+ }
+ }
+
+}