<pluginKey>xoo</pluginKey>
<pluginName>Xoo</pluginName>
<pluginClass>org.sonar.xoo.XooPlugin</pluginClass>
+ <sonarLintSupported>true</sonarLintSupported>
</configuration>
</plugin>
</plugins>
import org.sonar.xoo.rule.DeprecatedResourceApiSensor;
import org.sonar.xoo.rule.HasTagSensor;
import org.sonar.xoo.rule.MultilineIssuesSensor;
+import org.sonar.xoo.rule.NoSonarSensor;
import org.sonar.xoo.rule.OneBlockerIssuePerFileSensor;
import org.sonar.xoo.rule.OneBugIssuePerLineSensor;
import org.sonar.xoo.rule.OneDayDebtPerFileSensor;
import org.sonar.xoo.test.CoveragePerTestSensor;
import org.sonar.xoo.test.TestExecutionSensor;
-import static org.sonar.api.SonarQubeVersion.V5_5;
+import static org.sonar.api.SonarRuntime.V5_5;
/**
* Plugin entry-point, as declared in pom.xml.
ChecksSensor.class,
RandomAccessSensor.class,
SaveDataTwiceSensor.class,
+ NoSonarSensor.class,
OneBlockerIssuePerFileSensor.class,
OneIssuePerLineSensor.class,
// Other
XooProjectBuilder.class,
XooPostJob.class);
-
- if(context.getRuntimeProduct() != SonarProduct.SONARLINT) {
+
+ if (context.getRuntimeProduct() != SonarProduct.SONARLINT) {
context.addExtensions(MeasureSensor.class,
DeprecatedResourceApiSensor.class);
}
--- /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.xoo.rule;
+
+import org.sonar.api.batch.fs.FileSystem;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.rule.ActiveRules;
+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.xoo.Xoo;
+
+public abstract class AbstractXooRuleSensor implements Sensor {
+
+ private final FileSystem fs;
+ private final ActiveRules activeRules;
+
+ public AbstractXooRuleSensor(FileSystem fs, ActiveRules activeRules) {
+ this.fs = fs;
+ this.activeRules = activeRules;
+ }
+
+ protected abstract String getRuleKey();
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor
+ .onlyOnLanguage(Xoo.KEY)
+ .createIssuesForRuleRepository(XooRulesDefinition.XOO_REPOSITORY);
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ doAnalyse(context, Xoo.KEY);
+ }
+
+ private void doAnalyse(SensorContext context, String languageKey) {
+ RuleKey ruleKey = RuleKey.of(XooRulesDefinition.XOO_REPOSITORY, getRuleKey());
+ if (activeRules.find(ruleKey) == null) {
+ return;
+ }
+ for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(languageKey))) {
+ processFile(inputFile, context, ruleKey, languageKey);
+ }
+ }
+
+ protected abstract void processFile(InputFile inputFile, SensorContext context, RuleKey ruleKey, String languageKey);
+}
package org.sonar.xoo.rule;
import java.io.IOException;
-import java.util.List;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.batch.SensorContext;
+import java.nio.file.Files;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.Issuable;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.issue.NewIssue;
import org.sonar.api.rule.RuleKey;
/**
* Generate issues on all the occurrences of a given tag in xoo sources.
*/
-public class HasTagSensor extends AbstractDeprecatedXooRuleSensor {
+public class HasTagSensor extends AbstractXooRuleSensor {
public static final String RULE_KEY = "HasTag";
private static final String EFFORT_TO_FIX_PROPERTY = "sonar.hasTag.effortToFix";
- private final ResourcePerspectives perspectives;
- private final Settings settings;
private final ActiveRules activeRules;
- private FileSystem fs;
-
- public HasTagSensor(FileSystem fs, ResourcePerspectives perspectives, Settings settings, ActiveRules activeRules) {
+ public HasTagSensor(FileSystem fs, ActiveRules activeRules) {
super(fs, activeRules);
- this.fs = fs;
- this.perspectives = perspectives;
- this.settings = settings;
this.activeRules = activeRules;
}
}
@Override
- protected void processFile(InputFile inputFile, org.sonar.api.resources.File sonarFile, SensorContext context, RuleKey ruleKey, String languageKey) {
+ protected void processFile(InputFile inputFile, SensorContext context, RuleKey ruleKey, String languageKey) {
org.sonar.api.batch.rule.ActiveRule activeRule = activeRules.find(ruleKey);
String tag = activeRule.param("tag");
if (tag == null) {
throw new IllegalStateException("Rule is badly configured. The parameter 'tag' is missing.");
}
try {
- Issuable issuable = perspectives.as(Issuable.class, sonarFile);
- List<String> lines = FileUtils.readLines(inputFile.file(), fs.encoding().name());
- for (int index = 0; index < lines.size(); index++) {
- if (lines.get(index).contains(tag)) {
- issuable.addIssue(issuable.newIssueBuilder()
- .effortToFix(settings.getDouble(EFFORT_TO_FIX_PROPERTY))
- .line(index + 1)
- .ruleKey(ruleKey)
- .build());
+ int[] lineCounter = {1};
+ Files.lines(inputFile.path(), context.fileSystem().encoding()).forEachOrdered(lineStr -> {
+ int startIndex = -1;
+ while ((startIndex = lineStr.indexOf(tag, startIndex + 1)) != -1) {
+ NewIssue newIssue = context.newIssue();
+ newIssue
+ .forRule(ruleKey)
+ .gap(context.settings().getDouble(EFFORT_TO_FIX_PROPERTY))
+ .at(newIssue.newLocation()
+ .on(inputFile)
+ .at(inputFile.newRange(lineCounter[0], startIndex, lineCounter[0], startIndex + tag.length())))
+ .save();
}
- }
+ lineCounter[0]++;
+ });
} catch (IOException e) {
throw new IllegalStateException("Fail to process " + inputFile, e);
}
--- /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.xoo.rule;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.HashSet;
+import java.util.Set;
+import org.sonar.api.batch.Phase;
+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.issue.NoSonarFilter;
+import org.sonar.xoo.Xoo;
+
+@Phase(name = Phase.Name.PRE)
+public class NoSonarSensor implements Sensor {
+
+ private NoSonarFilter noSonarFilter;
+
+ public NoSonarSensor(NoSonarFilter noSonarFilter) {
+ this.noSonarFilter = noSonarFilter;
+ }
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor
+ .onlyOnLanguage(Xoo.KEY);
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+ for (InputFile inputFile : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguage(Xoo.KEY))) {
+ processFile(inputFile, context);
+ }
+ }
+
+ private void processFile(InputFile inputFile, SensorContext context) {
+ try {
+ Set<Integer> noSonarLines = new HashSet<>();
+ int[] lineCounter = {1};
+ Files.lines(inputFile.path(), context.fileSystem().encoding()).forEachOrdered(lineStr -> {
+ if (lineStr.contains("//NOSONAR")) {
+ noSonarLines.add(lineCounter[0]);
+ }
+ lineCounter[0]++;
+ });
+ noSonarFilter.noSonarInFile(inputFile, noSonarLines);
+ } catch (IOException e) {
+ throw new IllegalStateException("Fail to process " + inputFile, e);
+ }
+ }
+}
new RulesDefinitionAnnotationLoader().load(repo, Check.ALL);
NewRule hasTag = repo.createRule(HasTagSensor.RULE_KEY).setName("Has Tag")
+ .setActivatedByDefault(true)
.setHtmlDescription("Search for a given tag in Xoo files");
hasTag
.setDebtRemediationFunction(hasTag.debtRemediationFunctions().constantPerIssue("2min"));
NewRule oneIssuePerLine = repo.createRule(OneIssuePerLineSensor.RULE_KEY).setName("One Issue Per Line")
.setHtmlDescription("Generate an issue on each line of a file. It requires the metric \"lines\".");
oneIssuePerLine
- .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1min"))
+ .setDebtRemediationFunction(oneIssuePerLine.debtRemediationFunctions().linear("1min"))
.setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code");
repo.createRule(OneIssueOnDirPerFileSensor.RULE_KEY).setName("One Issue On Dir Per File")
NewRule oneIssuePerFile = repo.createRule(OneIssuePerFileSensor.RULE_KEY).setName("One Issue Per File")
.setHtmlDescription("Generate an issue on each file");
- oneIssuePerFile.setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("10min"));
+ oneIssuePerFile.setDebtRemediationFunction(oneIssuePerFile.debtRemediationFunctions().linear("10min"));
NewRule oneDayDebtPerFile = repo.createRule(OneDayDebtPerFileSensor.RULE_KEY).setName("One Day Debt Per File")
.setHtmlDescription("Generate an issue on each file with a debt of one day");
- oneDayDebtPerFile.setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("1d"));
+ oneDayDebtPerFile.setDebtRemediationFunction(oneDayDebtPerFile.debtRemediationFunctions().linear("1d"));
NewRule oneIssuePerModule = repo.createRule(OneIssuePerModuleSensor.RULE_KEY).setName("One Issue Per Module")
.setHtmlDescription("Generate an issue on each module");
oneIssuePerModule
- .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linearWithOffset("25min", "1h"))
+ .setDebtRemediationFunction(oneIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h"))
.setGapDescription("A certified architect will need roughly half an hour to start working on removal of modules, " +
"then it's about one hour per module.");
.setHtmlDescription("Generate a bug issue on each line of a file. It requires the metric \"lines\".")
.setType(RuleType.BUG);
oneBugIssuePerLine
- .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linear("5min"));
+ .setDebtRemediationFunction(oneBugIssuePerLine.debtRemediationFunctions().linear("5min"));
NewRule oneVulnerabilityIssuePerModule = repo.createRule(OneVulnerabilityIssuePerModuleSensor.RULE_KEY).setName("One Vulnerability Issue Per Module")
.setHtmlDescription("Generate an issue on each module")
.setType(RuleType.VULNERABILITY);
oneVulnerabilityIssuePerModule
- .setDebtRemediationFunction(hasTag.debtRemediationFunctions().linearWithOffset("25min", "1h"))
+ .setDebtRemediationFunction(oneVulnerabilityIssuePerModule.debtRemediationFunctions().linearWithOffset("25min", "1h"))
.setGapDescription("A certified architect will need roughly half an hour to start working on removal of modules, " +
"then it's about one hour per module.");
public void provide_extensions_for_5_5() {
Plugin.Context context = new Plugin.Context(new SonarRuntime(Version.parse("5.5"), SonarProduct.SONARQUBE, SonarQubeSide.SCANNER));
new XooPlugin().define(context);
- assertThat(context.getExtensions()).hasSize(42).contains(CpdTokenizerSensor.class);
+ assertThat(context.getExtensions()).hasSize(43).contains(CpdTokenizerSensor.class);
context = new Plugin.Context(new SonarRuntime(Version.parse("5.4"), SonarProduct.SONARLINT, null));
new XooPlugin().define(context);
- assertThat(context.getExtensions()).hasSize(39).doesNotContain(CpdTokenizerSensor.class);
+ assertThat(context.getExtensions()).hasSize(40).doesNotContain(CpdTokenizerSensor.class);
}
}
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
- <version>1.15</version>
+ <version>1.17-build269</version>
</plugin>
<plugin>
<groupId>org.owasp</groupId>