aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-scanner-engine
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2019-06-04 10:41:54 -0500
committerSonarTech <sonartech@sonarsource.com>2019-07-12 20:21:13 +0200
commit65c61f5006221de77fff2c314d07df8fb73ddc45 (patch)
treef63e2dc7d046f421ec67ef00fb71144eb683e877 /sonar-scanner-engine
parentbe4e3879670cfe7c26bd1cfed28e29a7b20d2e2a (diff)
downloadsonarqube-65c61f5006221de77fff2c314d07df8fb73ddc45.tar.gz
sonarqube-65c61f5006221de77fff2c314d07df8fb73ddc45.zip
Extract implementation from plugin API - Scanner Sensor
Diffstat (limited to 'sonar-scanner-engine')
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java56
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java2
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractDefaultIssue.java122
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java1
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java1
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java127
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java134
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssue.java93
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssueLocation.java92
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java140
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java123
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java9
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java6
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java4
-rw-r--r--sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java4
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java2
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java6
-rw-r--r--sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java4
19 files changed, 899 insertions, 29 deletions
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
index eecbbd15e84..be5b715891f 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/DefaultFileLinesContext.java
@@ -28,7 +28,7 @@ import java.util.Map.Entry;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.scanner.sensor.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.FileLinesContext;
import org.sonar.api.utils.KeyValueFormat;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java
new file mode 100644
index 00000000000..c3c23969ac6
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/postjob/DefaultPostJobDescriptor.java
@@ -0,0 +1,56 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.postjob.internal;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.sonar.api.batch.postjob.PostJobDescriptor;
+
+public class DefaultPostJobDescriptor implements PostJobDescriptor {
+
+ private String name;
+ private String[] properties = new String[0];
+
+ public String name() {
+ return name;
+ }
+
+ public Collection<String> properties() {
+ return Arrays.asList(properties);
+ }
+
+ @Override
+ public DefaultPostJobDescriptor name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public DefaultPostJobDescriptor requireProperty(String... propertyKey) {
+ return requireProperties(propertyKey);
+ }
+
+ @Override
+ public DefaultPostJobDescriptor requireProperties(String... propertyKeys) {
+ this.properties = propertyKeys;
+ return this;
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java
index 9c19a887d68..ad4ac749120 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/report/TestExecutionPublisher.java
@@ -26,7 +26,7 @@ import org.sonar.api.batch.fs.InputComponent;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.internal.DefaultInputComponent;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.scanner.sensor.DefaultMeasure;
import org.sonar.api.test.MutableTestPlan;
import org.sonar.api.test.TestCase;
import org.sonar.api.test.TestCase.Status;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractDefaultIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractDefaultIssue.java
new file mode 100644
index 00000000000..b77d1141911
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractDefaultIssue.java
@@ -0,0 +1,122 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.internal.DefaultInputDir;
+import org.sonar.api.batch.fs.internal.DefaultInputModule;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue.Flow;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+import org.sonar.api.utils.PathUtils;
+
+import static java.util.Collections.unmodifiableList;
+import static java.util.stream.Collectors.toList;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public abstract class AbstractDefaultIssue<T extends AbstractDefaultIssue> extends DefaultStorable {
+ protected IssueLocation primaryLocation;
+ protected List<List<IssueLocation>> flows = new ArrayList<>();
+ protected DefaultInputProject project;
+
+ protected AbstractDefaultIssue(DefaultInputProject project) {
+ this(project, null);
+ }
+
+ public AbstractDefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+ super(storage);
+ this.project = project;
+ }
+
+ public IssueLocation primaryLocation() {
+ return primaryLocation;
+ }
+
+ public List<Flow> flows() {
+ return this.flows.stream()
+ .<Flow>map(l -> () -> unmodifiableList(new ArrayList<>(l)))
+ .collect(toList());
+ }
+
+ public NewIssueLocation newLocation() {
+ return new DefaultIssueLocation();
+ }
+
+ public T at(NewIssueLocation primaryLocation) {
+ checkArgument(primaryLocation != null, "Cannot use a location that is null");
+ checkState(this.primaryLocation == null, "at() already called");
+ this.primaryLocation = rewriteLocation((DefaultIssueLocation) primaryLocation);
+ checkArgument(this.primaryLocation.inputComponent() != null, "Cannot use a location with no input component");
+ return (T) this;
+ }
+
+ public T addLocation(NewIssueLocation secondaryLocation) {
+ flows.add(Collections.singletonList(rewriteLocation((DefaultIssueLocation) secondaryLocation)));
+ return (T) this;
+ }
+
+ public T addFlow(Iterable<NewIssueLocation> locations) {
+ List<IssueLocation> flowAsList = new ArrayList<>();
+ for (NewIssueLocation issueLocation : locations) {
+ flowAsList.add(rewriteLocation((DefaultIssueLocation) issueLocation));
+ }
+ flows.add(flowAsList);
+ return (T) this;
+ }
+
+ private DefaultIssueLocation rewriteLocation(DefaultIssueLocation location) {
+ InputComponent component = location.inputComponent();
+ Optional<Path> dirOrModulePath = Optional.empty();
+
+ if (component instanceof DefaultInputDir) {
+ DefaultInputDir dirComponent = (DefaultInputDir) component;
+ dirOrModulePath = Optional.of(project.getBaseDir().relativize(dirComponent.path()));
+ } else if (component instanceof DefaultInputModule && !Objects.equals(project.key(), component.key())) {
+ DefaultInputModule moduleComponent = (DefaultInputModule) component;
+ dirOrModulePath = Optional.of(project.getBaseDir().relativize(moduleComponent.getBaseDir()));
+ }
+
+ if (dirOrModulePath.isPresent()) {
+ String path = PathUtils.sanitize(dirOrModulePath.get().toString());
+ DefaultIssueLocation fixedLocation = new DefaultIssueLocation();
+ fixedLocation.on(project);
+ StringBuilder fullMessage = new StringBuilder();
+ if (path != null && !path.isEmpty()) {
+ fullMessage.append("[").append(path).append("] ");
+ }
+ fullMessage.append(location.message());
+ fixedLocation.message(fullMessage.toString());
+ return fixedLocation;
+ } else {
+ return location;
+ }
+ }
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java
index f9dae8328e6..95b473e05ce 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorOptimizer.java
@@ -24,7 +24,6 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.FilePredicate;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.config.Configuration;
public abstract class AbstractSensorOptimizer {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java
index 43773f1eb1d..caba9bc9101 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/AbstractSensorWrapper.java
@@ -20,7 +20,6 @@
package org.sonar.scanner.sensor;
import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor;
import org.sonar.api.scanner.sensor.ProjectSensor;
public abstract class AbstractSensorWrapper<G extends ProjectSensor> {
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java
new file mode 100644
index 00000000000..23dbd341c36
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultAdHocRule.java
@@ -0,0 +1,127 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.rule.AdHocRule;
+import org.sonar.api.batch.sensor.rule.NewAdHocRule;
+import org.sonar.api.rules.RuleType;
+
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultAdHocRule extends DefaultStorable implements AdHocRule, NewAdHocRule {
+ private Severity severity;
+ private RuleType type;
+ private String name;
+ private String description;
+ private String engineId;
+ private String ruleId;
+
+ public DefaultAdHocRule() {
+ super(null);
+ }
+
+ public DefaultAdHocRule(@Nullable SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public DefaultAdHocRule severity(Severity severity) {
+ this.severity = severity;
+ return this;
+ }
+
+ @Override
+ public String engineId() {
+ return engineId;
+ }
+
+ @Override
+ public String ruleId() {
+ return ruleId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @CheckForNull
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public Severity severity() {
+ return this.severity;
+ }
+
+ @Override
+ public void doSave() {
+ checkState(isNotBlank(engineId), "Engine id is mandatory on ad hoc rule");
+ checkState(isNotBlank(ruleId), "Rule id is mandatory on ad hoc rule");
+ checkState(isNotBlank(name), "Name is mandatory on every ad hoc rule");
+ checkState(severity != null, "Severity is mandatory on every ad hoc rule");
+ checkState(type != null, "Type is mandatory on every ad hoc rule");
+ storage.store(this);
+ }
+
+ @Override
+ public RuleType type() {
+ return type;
+ }
+
+ @Override
+ public DefaultAdHocRule engineId(String engineId) {
+ this.engineId = engineId;
+ return this;
+ }
+
+ @Override
+ public DefaultAdHocRule ruleId(String ruleId) {
+ this.ruleId = ruleId;
+ return this;
+ }
+
+ @Override
+ public DefaultAdHocRule name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public DefaultAdHocRule description(@Nullable String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public DefaultAdHocRule type(RuleType type) {
+ this.type = type;
+ return this;
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java
new file mode 100644
index 00000000000..3c09a40aceb
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultExternalIssue.java
@@ -0,0 +1,134 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.ExternalIssue;
+import org.sonar.api.batch.sensor.issue.NewExternalIssue;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleType;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultExternalIssue extends AbstractDefaultIssue<DefaultExternalIssue> implements ExternalIssue, NewExternalIssue {
+ private Long effort;
+ private Severity severity;
+ private RuleType type;
+ private String engineId;
+ private String ruleId;
+
+ public DefaultExternalIssue(DefaultInputProject project) {
+ this(project, null);
+ }
+
+ public DefaultExternalIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+ super(project, storage);
+ }
+
+ @Override
+ public DefaultExternalIssue remediationEffortMinutes(@Nullable Long effort) {
+ checkArgument(effort == null || effort >= 0, format("effort must be greater than or equal 0 (got %s)", effort));
+ this.effort = effort;
+ return this;
+ }
+
+ @Override
+ public DefaultExternalIssue severity(Severity severity) {
+ this.severity = severity;
+ return this;
+ }
+
+ @Override
+ public String engineId() {
+ return engineId;
+ }
+
+ @Override
+ public String ruleId() {
+ return ruleId;
+ }
+
+ @Override
+ public Severity severity() {
+ return this.severity;
+ }
+
+ @Override
+ public Long remediationEffort() {
+ return this.effort;
+ }
+
+ @Override
+ public void doSave() {
+ requireNonNull(this.engineId, "Engine id is mandatory on external issue");
+ requireNonNull(this.ruleId, "Rule id is mandatory on external issue");
+ checkState(primaryLocation != null, "Primary location is mandatory on every external issue");
+ checkState(primaryLocation.inputComponent().isFile(), "External issues must be located in files");
+ checkState(primaryLocation.message() != null, "External issues must have a message");
+ checkState(severity != null, "Severity is mandatory on every external issue");
+ checkState(type != null, "Type is mandatory on every external issue");
+ storage.store(this);
+ }
+
+ @Override
+ public RuleType type() {
+ return type;
+ }
+
+ @Override
+ public NewExternalIssue engineId(String engineId) {
+ this.engineId = engineId;
+ return this;
+ }
+
+ @Override
+ public NewExternalIssue ruleId(String ruleId) {
+ this.ruleId = ruleId;
+ return this;
+ }
+
+ @Override
+ public DefaultExternalIssue forRule(RuleKey ruleKey) {
+ this.engineId = ruleKey.repository();
+ this.ruleId = ruleKey.rule();
+ return this;
+ }
+
+ @Override
+ public RuleKey ruleKey() {
+ if (engineId != null && ruleId != null) {
+ return RuleKey.of(RuleKey.EXTERNAL_RULE_REPO_PREFIX + engineId, ruleId);
+ }
+ return null;
+ }
+
+ @Override
+ public DefaultExternalIssue type(RuleType type) {
+ this.type = type;
+ return this;
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssue.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssue.java
new file mode 100644
index 00000000000..369d7314c2f
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssue.java
@@ -0,0 +1,93 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.internal.DefaultInputProject;
+import org.sonar.api.batch.rule.Severity;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssue;
+import org.sonar.api.rule.RuleKey;
+
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultIssue extends AbstractDefaultIssue<DefaultIssue> implements Issue, NewIssue {
+ private RuleKey ruleKey;
+ private Double gap;
+ private Severity overriddenSeverity;
+
+ public DefaultIssue(DefaultInputProject project) {
+ this(project, null);
+ }
+
+ public DefaultIssue(DefaultInputProject project, @Nullable SensorStorage storage) {
+ super(project, storage);
+ }
+
+ public DefaultIssue forRule(RuleKey ruleKey) {
+ this.ruleKey = ruleKey;
+ return this;
+ }
+
+ public RuleKey ruleKey() {
+ return this.ruleKey;
+ }
+
+ @Override
+ public DefaultIssue gap(@Nullable Double gap) {
+ checkArgument(gap == null || gap >= 0, format("Gap must be greater than or equal 0 (got %s)", gap));
+ this.gap = gap;
+ return this;
+ }
+
+ @Override
+ public DefaultIssue overrideSeverity(@Nullable Severity severity) {
+ this.overriddenSeverity = severity;
+ return this;
+ }
+
+ @Override
+ public Severity overriddenSeverity() {
+ return this.overriddenSeverity;
+ }
+
+ @Override
+ public Double gap() {
+ return this.gap;
+ }
+
+ @Override
+ public IssueLocation primaryLocation() {
+ return primaryLocation;
+ }
+
+ @Override
+ public void doSave() {
+ requireNonNull(this.ruleKey, "ruleKey is mandatory on issue");
+ checkState(primaryLocation != null, "Primary location is mandatory on every issue");
+ storage.store(this);
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssueLocation.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssueLocation.java
new file mode 100644
index 00000000000..b08d093c261
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultIssueLocation.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.batch.sensor.issue.NewIssueLocation;
+
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.abbreviate;
+import static org.apache.commons.lang.StringUtils.trim;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultIssueLocation implements NewIssueLocation, IssueLocation {
+
+ private InputComponent component;
+ private TextRange textRange;
+ private String message;
+
+ @Override
+ public DefaultIssueLocation on(InputComponent component) {
+ checkArgument(component != null, "Component can't be null");
+ checkState(this.component == null, "on() already called");
+ this.component = component;
+ return this;
+ }
+
+ @Override
+ public DefaultIssueLocation at(TextRange location) {
+ checkState(this.component != null, "at() should be called after on()");
+ checkState(this.component.isFile(), "at() should be called only for an InputFile.");
+ DefaultInputFile file = (DefaultInputFile) this.component;
+ file.validate(location);
+ this.textRange = location;
+ return this;
+ }
+
+ @Override
+ public DefaultIssueLocation message(String message) {
+ requireNonNull(message, "Message can't be null");
+ if (message.contains("\u0000")) {
+ throw new IllegalArgumentException(unsupportedCharacterError(message, component));
+ }
+ this.message = abbreviate(trim(message), MESSAGE_MAX_SIZE);
+ return this;
+ }
+
+ private static String unsupportedCharacterError(String message, @Nullable InputComponent component) {
+ String error = "Character \\u0000 is not supported in issue message '" + message + "'";
+ if (component != null) {
+ error += ", on component: " + component.toString();
+ }
+ return error;
+ }
+
+ @Override
+ public InputComponent inputComponent() {
+ return this.component;
+ }
+
+ @Override
+ public TextRange textRange() {
+ return textRange;
+ }
+
+ @Override
+ public String message() {
+ return this.message;
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java
new file mode 100644
index 00000000000..87d1aa18c1d
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultMeasure.java
@@ -0,0 +1,140 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import java.io.Serializable;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.sonar.api.batch.fs.InputComponent;
+import org.sonar.api.batch.measure.Metric;
+import org.sonar.api.batch.sensor.internal.DefaultStorable;
+import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.measure.Measure;
+import org.sonar.api.batch.sensor.measure.NewMeasure;
+
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.utils.Preconditions.checkArgument;
+import static org.sonar.api.utils.Preconditions.checkState;
+
+public class DefaultMeasure<G extends Serializable> extends DefaultStorable implements Measure<G>, NewMeasure<G> {
+
+ private InputComponent component;
+ private Metric<G> metric;
+ private G value;
+ private boolean fromCore = false;
+
+ public DefaultMeasure() {
+ super();
+ }
+
+ public DefaultMeasure(@Nullable SensorStorage storage) {
+ super(storage);
+ }
+
+ @Override
+ public DefaultMeasure<G> on(InputComponent component) {
+ checkArgument(component != null, "Component can't be null");
+ checkState(this.component == null, "on() already called");
+ this.component = component;
+ return this;
+ }
+
+ @Override
+ public DefaultMeasure<G> forMetric(Metric<G> metric) {
+ checkState(this.metric == null, "Metric already defined");
+ requireNonNull(metric, "metric should be non null");
+ this.metric = metric;
+ return this;
+ }
+
+ @Override
+ public DefaultMeasure<G> withValue(G value) {
+ checkState(this.value == null, "Measure value already defined");
+ requireNonNull(value, "Measure value can't be null");
+ this.value = value;
+ return this;
+ }
+
+ /**
+ * For internal use.
+ */
+ public boolean isFromCore() {
+ return fromCore;
+ }
+
+ /**
+ * For internal use. Used by core components to bypass check that prevent a plugin to store core measures.
+ */
+ public DefaultMeasure<G> setFromCore() {
+ this.fromCore = true;
+ return this;
+ }
+
+ @Override
+ public void doSave() {
+ requireNonNull(this.value, "Measure value can't be null");
+ requireNonNull(this.metric, "Measure metric can't be null");
+ checkState(this.metric.valueType().equals(this.value.getClass()), "Measure value should be of type %s", this.metric.valueType());
+ storage.store(this);
+ }
+
+ @Override
+ public Metric<G> metric() {
+ return metric;
+ }
+
+ @Override
+ public InputComponent inputComponent() {
+ return component;
+ }
+
+ @Override
+ public G value() {
+ return value;
+ }
+
+ // For testing purpose
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ DefaultMeasure<?> rhs = (DefaultMeasure<?>) obj;
+ return new EqualsBuilder()
+ .append(component, rhs.component)
+ .append(metric, rhs.metric)
+ .append(value, rhs.value)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder(27, 45).append(component).append(metric).append(value).toHashCode();
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java
new file mode 100644
index 00000000000..1bb74666aaf
--- /dev/null
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorDescriptor.java
@@ -0,0 +1,123 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info 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.scanner.sensor;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.function.Predicate;
+import javax.annotation.Nullable;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.api.config.Configuration;
+
+import static java.util.Arrays.asList;
+
+public class DefaultSensorDescriptor implements SensorDescriptor {
+
+ private String name;
+ private String[] languages = new String[0];
+ private InputFile.Type type = null;
+ private String[] ruleRepositories = new String[0];
+ private boolean global = false;
+ private Predicate<Configuration> configurationPredicate;
+
+ public String name() {
+ return name;
+ }
+
+ public Collection<String> languages() {
+ return Arrays.asList(languages);
+ }
+
+ @Nullable
+ public InputFile.Type type() {
+ return type;
+ }
+
+ public Collection<String> ruleRepositories() {
+ return Arrays.asList(ruleRepositories);
+ }
+
+ public Predicate<Configuration> configurationPredicate() {
+ return configurationPredicate;
+ }
+
+ public boolean isGlobal() {
+ return global;
+ }
+
+ @Override
+ public DefaultSensorDescriptor name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public DefaultSensorDescriptor onlyOnLanguage(String languageKey) {
+ return onlyOnLanguages(languageKey);
+ }
+
+ @Override
+ public DefaultSensorDescriptor onlyOnLanguages(String... languageKeys) {
+ this.languages = languageKeys;
+ return this;
+ }
+
+ @Override
+ public DefaultSensorDescriptor onlyOnFileType(InputFile.Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public DefaultSensorDescriptor createIssuesForRuleRepository(String... repositoryKey) {
+ return createIssuesForRuleRepositories(repositoryKey);
+ }
+
+ @Override
+ public DefaultSensorDescriptor createIssuesForRuleRepositories(String... repositoryKeys) {
+ this.ruleRepositories = repositoryKeys;
+ return this;
+ }
+
+ @Override
+ public DefaultSensorDescriptor requireProperty(String... propertyKey) {
+ return requireProperties(propertyKey);
+ }
+
+ @Override
+ public DefaultSensorDescriptor requireProperties(String... propertyKeys) {
+ this.configurationPredicate = config -> asList(propertyKeys).stream().allMatch(config::hasKey);
+ return this;
+ }
+
+ @Override
+ public SensorDescriptor global() {
+ this.global = true;
+ return this;
+ }
+
+ @Override
+ public SensorDescriptor onlyWhenConfiguration(Predicate<Configuration> configurationPredicate) {
+ this.configurationPredicate = configurationPredicate;
+ return this;
+ }
+
+}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
index 75a7806beab..415a884380b 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/DefaultSensorStorage.java
@@ -43,11 +43,10 @@ import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens;
import org.sonar.api.batch.sensor.error.AnalysisError;
import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
+import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
import org.sonar.api.batch.sensor.measure.Measure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
+import org.sonar.api.batch.sensor.rule.AdHocRule;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Configuration;
import org.sonar.api.measures.CoreMetrics;
@@ -231,7 +230,7 @@ public class DefaultSensorStorage implements SensorStorage {
* Thread safe assuming that each issues for each file are only written once.
*/
@Override
- public void store(DefaultExternalIssue externalIssue) {
+ public void store(ExternalIssue externalIssue) {
if (externalIssue.primaryLocation().inputComponent() instanceof DefaultInputFile) {
DefaultInputFile defaultInputFile = (DefaultInputFile) externalIssue.primaryLocation().inputComponent();
defaultInputFile.setPublished(true);
@@ -240,7 +239,7 @@ public class DefaultSensorStorage implements SensorStorage {
}
@Override
- public void store(DefaultAdHocRule adHocRule) {
+ public void store(AdHocRule adHocRule) {
ScannerReportWriter writer = reportPublisher.getWriter();
final ScannerReport.AdHocRule.Builder builder = ScannerReport.AdHocRule.newBuilder();
builder.setEngineId(adHocRule.engineId());
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java
index c0ec11759ed..887f1d02c66 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/InMemorySensorStorage.java
@@ -33,10 +33,8 @@ import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.rule.AdHocRule;
-import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import static org.sonar.api.utils.Preconditions.checkArgument;
@@ -74,7 +72,7 @@ class InMemorySensorStorage implements SensorStorage {
}
@Override
- public void store(DefaultAdHocRule adHocRule) {
+ public void store(AdHocRule adHocRule) {
allAdHocRules.add(adHocRule);
}
@@ -127,7 +125,7 @@ class InMemorySensorStorage implements SensorStorage {
}
@Override
- public void store(DefaultExternalIssue issue) {
+ public void store(ExternalIssue issue) {
allExternalIssues.add(issue);
}
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java
index 0fe743dfbe2..21e6d2b8f70 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java
@@ -41,12 +41,8 @@ import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
import org.sonar.api.batch.sensor.measure.NewMeasure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Configuration;
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java
index 21e5a8271ca..26777fc0a99 100644
--- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java
+++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/SensorContextTester.java
@@ -65,14 +65,10 @@ import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
import org.sonar.api.batch.sensor.issue.NewExternalIssue;
import org.sonar.api.batch.sensor.issue.NewIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
import org.sonar.api.batch.sensor.measure.Measure;
import org.sonar.api.batch.sensor.measure.NewMeasure;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.rule.AdHocRule;
import org.sonar.api.batch.sensor.rule.NewAdHocRule;
-import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule;
import org.sonar.api.batch.sensor.symbol.NewSymbolTable;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.Configuration;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
index 6bd3a77f43c..19ce32d686c 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/DefaultFileLinesContextTest.java
@@ -29,7 +29,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.api.batch.measure.MetricFinder;
import org.sonar.api.batch.sensor.internal.SensorStorage;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
+import org.sonar.scanner.sensor.DefaultMeasure;
import org.sonar.api.measures.CoreMetrics;
import static org.assertj.core.api.Assertions.assertThat;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java
index 9a89d6ad18b..50ea80aceb7 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java
@@ -38,9 +38,9 @@ import org.sonar.api.batch.fs.internal.TestInputFileBuilder;
import org.sonar.scanner.rule.ActiveRulesBuilder;
import org.sonar.scanner.rule.NewActiveRule;
import org.sonar.scanner.rule.RulesBuilder;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
+import org.sonar.scanner.sensor.DefaultExternalIssue;
+import org.sonar.scanner.sensor.DefaultIssue;
+import org.sonar.scanner.sensor.DefaultIssueLocation;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
index 264e666429f..bdefb6f3436 100644
--- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
+++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/DefaultSensorStorageTest.java
@@ -40,10 +40,6 @@ import org.sonar.api.batch.sensor.highlighting.TypeOfText;
import org.sonar.api.batch.sensor.highlighting.internal.DefaultHighlighting;
import org.sonar.api.batch.sensor.issue.ExternalIssue;
import org.sonar.api.batch.sensor.issue.Issue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssue;
-import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable;
import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.measures.CoreMetrics;