diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2016-07-11 17:46:57 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2016-07-12 11:21:35 +0200 |
commit | 0acf0fe5f8bd8cf7c188dca14ed3c379b8fe93fb (patch) | |
tree | 6621a94a80857d739b9cdebd5231a6d90839fce8 /plugins | |
parent | 43864c2159afd6b0eaf45a2c8e7129475e0f0136 (diff) | |
download | sonarqube-0acf0fe5f8bd8cf7c188dca14ed3c379b8fe93fb.tar.gz sonarqube-0acf0fe5f8bd8cf7c188dca14ed3c379b8fe93fb.zip |
Make Xoo a SonarLint plugin
Diffstat (limited to 'plugins')
7 files changed, 172 insertions, 37 deletions
diff --git a/plugins/sonar-xoo-plugin/pom.xml b/plugins/sonar-xoo-plugin/pom.xml index 6145bee37ea..5240a80f499 100644 --- a/plugins/sonar-xoo-plugin/pom.xml +++ b/plugins/sonar-xoo-plugin/pom.xml @@ -67,6 +67,7 @@ <pluginKey>xoo</pluginKey> <pluginName>Xoo</pluginName> <pluginClass>org.sonar.xoo.XooPlugin</pluginClass> + <sonarLintSupported>true</sonarLintSupported> </configuration> </plugin> </plugins> diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index c1d757812a7..9b443628856 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -40,6 +40,7 @@ import org.sonar.xoo.rule.CustomMessageSensor; 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; @@ -62,7 +63,7 @@ import org.sonar.xoo.scm.XooScmProvider; 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. @@ -99,6 +100,7 @@ public class XooPlugin implements Plugin { ChecksSensor.class, RandomAccessSensor.class, SaveDataTwiceSensor.class, + NoSonarSensor.class, OneBlockerIssuePerFileSensor.class, OneIssuePerLineSensor.class, @@ -128,8 +130,8 @@ public class XooPlugin implements Plugin { // Other XooProjectBuilder.class, XooPostJob.class); - - if(context.getRuntimeProduct() != SonarProduct.SONARLINT) { + + if (context.getRuntimeProduct() != SonarProduct.SONARLINT) { context.addExtensions(MeasureSensor.class, DeprecatedResourceApiSensor.class); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/AbstractXooRuleSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/AbstractXooRuleSensor.java new file mode 100644 index 00000000000..b1fa099e6e7 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/AbstractXooRuleSensor.java @@ -0,0 +1,66 @@ +/* + * 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); +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HasTagSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HasTagSensor.java index 465d3105172..9f030e6db69 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HasTagSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HasTagSensor.java @@ -20,37 +20,27 @@ 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; } @@ -60,24 +50,28 @@ public class HasTagSensor extends AbstractDeprecatedXooRuleSensor { } @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); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/NoSonarSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/NoSonarSensor.java new file mode 100644 index 00000000000..45d6b9dcb75 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/NoSonarSensor.java @@ -0,0 +1,71 @@ +/* + * 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); + } + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java index 3233ab2d369..0940a41eec2 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java @@ -62,6 +62,7 @@ public class XooRulesDefinition implements RulesDefinition { 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")); @@ -80,7 +81,7 @@ public class XooRulesDefinition implements RulesDefinition { 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") @@ -88,16 +89,16 @@ public class XooRulesDefinition implements RulesDefinition { 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."); @@ -120,13 +121,13 @@ public class XooRulesDefinition implements RulesDefinition { .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."); diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index 33ec8a59167..6a0507af8d1 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -35,10 +35,10 @@ public class XooPluginTest { 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); } } |