@@ -64,6 +64,7 @@ import org.sonar.xoo.rule.OneIssuePerTestFileSensor; | |||
import org.sonar.xoo.rule.OneIssuePerUnknownFileSensor; | |||
import org.sonar.xoo.rule.OnePredefinedAndAdHocRuleExternalIssuePerLineSensor; | |||
import org.sonar.xoo.rule.OnePredefinedRuleExternalIssuePerLineSensor; | |||
import org.sonar.xoo.rule.OneQuickFixPerLineSensor; | |||
import org.sonar.xoo.rule.OneVulnerabilityIssuePerModuleSensor; | |||
import org.sonar.xoo.rule.RandomAccessSensor; | |||
import org.sonar.xoo.rule.SaveDataTwiceSensor; | |||
@@ -146,6 +147,7 @@ public class XooPlugin implements Plugin { | |||
OneIssuePerModuleSensor.class, | |||
OneIssueOnDirPerFileSensor.class, | |||
OneIssuePerUnknownFileSensor.class, | |||
OneQuickFixPerLineSensor.class, | |||
OneExternalIssuePerLineSensor.class, | |||
OneExternalIssuePerLineWithoutMessageSensor.class, |
@@ -0,0 +1,77 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2021 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.xoo.rule; | |||
import org.sonar.api.batch.fs.FilePredicates; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.fs.InputFile; | |||
import org.sonar.api.batch.fs.InputFile.Type; | |||
import org.sonar.api.batch.rule.Severity; | |||
import org.sonar.api.batch.sensor.Sensor; | |||
import org.sonar.api.batch.sensor.SensorContext; | |||
import org.sonar.api.batch.sensor.SensorDescriptor; | |||
import org.sonar.api.batch.sensor.issue.NewIssue; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.utils.Version; | |||
import org.sonar.xoo.Xoo; | |||
import org.sonar.xoo.Xoo2; | |||
public class OneQuickFixPerLineSensor implements Sensor { | |||
public static final String RULE_KEY = "OneQuickFixPerLine"; | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("One Quick Fix Per Line") | |||
.onlyOnLanguages(Xoo.KEY, Xoo2.KEY) | |||
.createIssuesForRuleRepositories(XooRulesDefinition.XOO_REPOSITORY, XooRulesDefinition.XOO2_REPOSITORY); | |||
} | |||
@Override | |||
public void execute(SensorContext context) { | |||
analyse(context, Xoo.KEY, XooRulesDefinition.XOO_REPOSITORY); | |||
analyse(context, Xoo2.KEY, XooRulesDefinition.XOO2_REPOSITORY); | |||
} | |||
private void analyse(SensorContext context, String language, String repo) { | |||
FileSystem fs = context.fileSystem(); | |||
FilePredicates p = fs.predicates(); | |||
for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(language), p.hasType(Type.MAIN)))) { | |||
createIssues(file, context, repo); | |||
} | |||
} | |||
private void createIssues(InputFile file, SensorContext context, String repo) { | |||
RuleKey ruleKey = RuleKey.of(repo, RULE_KEY); | |||
for (int line = 1; line <= file.lines(); line++) { | |||
NewIssue newIssue = context.newIssue(); | |||
newIssue | |||
.setQuickFixAvailable(true) | |||
.forRule(ruleKey) | |||
.at(newIssue.newLocation() | |||
.on(file) | |||
.at(file.selectLine(line)) | |||
.message("This quick fix issue is generated on each line")) | |||
.save(); | |||
} | |||
} | |||
} |
@@ -103,6 +103,13 @@ public class XooRulesDefinition implements RulesDefinition { | |||
.setDebtRemediationFunction(oneIssuePerLine.debtRemediationFunctions().linear("1min")) | |||
.setGapDescription("It takes about 1 minute to an experienced software craftsman to remove a line of code"); | |||
NewRule oneQuickFixPerLine = repo.createRule(OneQuickFixPerLineSensor.RULE_KEY).setName("One Quick Fix Per Line") | |||
.setHtmlDescription("Generate an issue with quick fix available on each line of a file. It requires the metric \"lines\".") | |||
.setTags("line"); | |||
oneQuickFixPerLine | |||
.setDebtRemediationFunction(oneQuickFixPerLine.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") | |||
.setHtmlDescription("Generate issues on directories"); | |||
@@ -0,0 +1,73 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2021 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.xoo.rule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.SonarQubeSide; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; | |||
import org.sonar.api.batch.rule.Severity; | |||
import org.sonar.api.batch.sensor.internal.DefaultSensorDescriptor; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import org.sonar.api.batch.sensor.issue.Issue; | |||
import org.sonar.api.config.internal.MapSettings; | |||
import org.sonar.api.internal.SonarRuntimeImpl; | |||
import org.sonar.api.utils.Version; | |||
import org.sonar.xoo.Xoo; | |||
import java.io.IOException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class OneQuickFixPerLineSensorTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
private OneQuickFixPerLineSensor sensor = new OneQuickFixPerLineSensor(); | |||
@Test | |||
public void testDescriptor() { | |||
DefaultSensorDescriptor descriptor = new DefaultSensorDescriptor(); | |||
sensor.describe(descriptor); | |||
assertThat(descriptor.ruleRepositories()).containsOnly(XooRulesDefinition.XOO_REPOSITORY, XooRulesDefinition.XOO2_REPOSITORY); | |||
} | |||
@Test | |||
public void testRule() throws IOException { | |||
DefaultInputFile inputFile = new TestInputFileBuilder("foo", "src/Foo.xoo") | |||
.setLanguage(Xoo.KEY) | |||
.initMetadata("a\nb\nc\nd\ne\nf\ng\nh\ni\n") | |||
.build(); | |||
SensorContextTester context = SensorContextTester.create(temp.newFolder()); | |||
context.fileSystem().add(inputFile); | |||
sensor.execute(context); | |||
assertThat(context.allIssues()).hasSize(10); // One issue per line | |||
for (Issue issue : context.allIssues()) { | |||
assertThat(issue.isQuickFixAvailable()).isTrue(); | |||
} | |||
} | |||
} |
@@ -48,7 +48,7 @@ public class XooRulesDefinitionTest { | |||
assertThat(repo).isNotNull(); | |||
assertThat(repo.name()).isEqualTo("Xoo"); | |||
assertThat(repo.language()).isEqualTo("xoo"); | |||
assertThat(repo.rules()).hasSize(22); | |||
assertThat(repo.rules()).hasSize(23); | |||
RulesDefinition.Rule rule = repo.rule(OneIssuePerLineSensor.RULE_KEY); | |||
assertThat(rule.name()).isNotEmpty(); | |||
@@ -64,7 +64,7 @@ public class XooRulesDefinitionTest { | |||
assertThat(repo).isNotNull(); | |||
assertThat(repo.name()).isEqualTo("Xoo"); | |||
assertThat(repo.language()).isEqualTo("xoo"); | |||
assertThat(repo.rules()).hasSize(22); | |||
assertThat(repo.rules()).hasSize(23); | |||
RulesDefinition.Rule rule = repo.rule(HotspotSensor.RULE_KEY); | |||
assertThat(rule.name()).isNotEmpty(); |
@@ -72,7 +72,7 @@ export default function IssueMessage(props: IssueMessageProps) { | |||
/> | |||
} | |||
mouseLeaveDelay={0.5}> | |||
<SonarLintIcon className="spacer-right" size={15} /> | |||
<SonarLintIcon className="it__issues-sonarlint-quick-fix spacer-right" size={15} /> | |||
</Tooltip> | |||
)} | |||
<ButtonLink |
@@ -207,7 +207,7 @@ exports[`should render correctly: with quick fix 1`] = ` | |||
} | |||
> | |||
<SonarLintIcon | |||
className="spacer-right" | |||
className="it__issues-sonarlint-quick-fix spacer-right" | |||
size={15} | |||
/> | |||
</Tooltip> |