@@ -0,0 +1,43 @@ | |||
configurations { | |||
testImplementation.extendsFrom(compileOnly) | |||
} | |||
dependencies { | |||
compileOnly 'org.sonarsource.api.plugin:sonar-plugin-api' | |||
testCompile 'junit:junit' | |||
testCompile 'org.assertj:assertj-core' | |||
testCompile 'org.mockito:mockito-core' | |||
testCompile project(':sonar-plugin-api-impl') | |||
} | |||
jar { | |||
manifest { | |||
attributes( | |||
'Plugin-Key': 'education', | |||
'Plugin-Version': project.version, | |||
'Plugin-Class': 'org.sonar.education.EducationPlugin', | |||
'Plugin-ChildFirstClassLoader': 'false', | |||
'Sonar-Version': project.version, | |||
'SonarLint-Supported': 'true', | |||
'Plugin-Name': 'Education' | |||
) | |||
} | |||
into('META-INF/lib') { | |||
from configurations.compileClasspath | |||
} | |||
} | |||
artifactoryPublish.skip = false | |||
publishing { | |||
publications { | |||
mavenJava(MavenPublication) { | |||
from components.java | |||
if (release) { | |||
artifact sourcesJar | |||
artifact javadocJar | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; | |||
import static org.sonar.education.EducationRulesDefinition.EDUCATION_RULE_REPOSITORY_KEY; | |||
import static org.sonar.education.sensors.EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; | |||
import static org.sonar.education.sensors.EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY; | |||
import static org.sonar.education.sensors.EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY; | |||
import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; | |||
public class EducationBuiltInQualityProfileDefinition implements BuiltInQualityProfilesDefinition { | |||
@Override | |||
public void define(Context context) { | |||
NewBuiltInQualityProfile profile = context.createBuiltInQualityProfile("Built in QP for Education", EDUCATION_KEY); | |||
profile.setDefault(true); | |||
profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); | |||
profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); | |||
profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_CONTEXTS_RULE_KEY); | |||
profile.activateRule(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); | |||
profile.done(); | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.sonar.api.resources.Language; | |||
public class EducationLanguage implements Language { | |||
@Override | |||
public String getKey() { | |||
return EducationRulesDefinition.EDUCATION_KEY; | |||
} | |||
@Override | |||
public String getName() { | |||
return "Education"; | |||
} | |||
@Override | |||
public String[] getFileSuffixes() { | |||
return new String[]{".edu"}; | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.sonar.education.sensors.EducationWithContextsSensor; | |||
import org.sonar.education.sensors.EducationWithDetectedContextSensor; | |||
import org.sonar.education.sensors.EducationPrinciplesSensor; | |||
import org.sonar.education.sensors.EducationWithSingleContextSensor; | |||
import org.sonar.api.Plugin; | |||
public class EducationPlugin implements Plugin { | |||
@Override | |||
public void define(Context context) { | |||
context.addExtensions( | |||
EducationRulesDefinition.class, | |||
EducationLanguage.class, | |||
EducationWithContextsSensor.class, | |||
EducationWithDetectedContextSensor.class, | |||
EducationPrinciplesSensor.class, | |||
EducationWithSingleContextSensor.class, | |||
EducationBuiltInQualityProfileDefinition.class); | |||
} | |||
} |
@@ -0,0 +1,149 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.sonar.api.server.rule.RuleDescriptionSection; | |||
import org.sonar.api.server.rule.RulesDefinition; | |||
import org.sonar.education.sensors.EducationPrinciplesSensor; | |||
import org.sonar.education.sensors.EducationWithContextsSensor; | |||
import org.sonar.education.sensors.EducationWithDetectedContextSensor; | |||
import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; | |||
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ASSESS_THE_PROBLEM_SECTION_KEY; | |||
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.HOW_TO_FIX_SECTION_KEY; | |||
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.INTRODUCTION_SECTION_KEY; | |||
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.RESOURCES_SECTION_KEY; | |||
import static org.sonar.api.server.rule.RuleDescriptionSection.RuleDescriptionSectionKeys.ROOT_CAUSE_SECTION_KEY; | |||
public class EducationRulesDefinition implements RulesDefinition { | |||
public static final String EDUCATION_RULE_REPOSITORY_KEY = "edu"; | |||
public static final String EDUCATION_KEY = "education"; | |||
private static final String IGNORED_FAKE_SECTION = "fake_section_to_be_ignored"; | |||
public static final String[] CONTEXTS = {"spring", "hibernate", "apache-commons", "vaadin", "mybatis"}; | |||
private static final String HTML_LOREM_IPSUM = "<a href=\"https://google.com\">Lorem</a> ipsum dolor sit amet, consectetur adipiscing " + | |||
"elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco " + | |||
"laboris nisi ut aliquip ex ea commodo consequat.<br />Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu " + | |||
"fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; | |||
@Override | |||
public void define(Context context) { | |||
NewRepository repo = context.createRepository(EDUCATION_RULE_REPOSITORY_KEY, EDUCATION_KEY); | |||
createRuleWithDescriptionSectionsAndEducationPrinciples(repo); | |||
createRuleWithDescriptionSectionsAndSingleContext(repo); | |||
createRuleWithDescriptionSectionsAndMultipleContexts(repo); | |||
createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(repo); | |||
repo.done(); | |||
} | |||
private void createRuleWithDescriptionSectionsAndEducationPrinciples(NewRepository repo) { | |||
String[] educationPrinciples = {"defense_in_depth", "least_trust_principle"}; | |||
String ruleKey = EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; | |||
NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and education principles") | |||
.addTags(EDUCATION_KEY); | |||
ruleWithSingleContext | |||
.setHtmlDescription(String.format("This rule contains description sections. To trigger an issue using this rule you need to " + | |||
"scan any text file with a line containing %s key word. This rule also contains 2 education principles - %s and %s", | |||
ruleKey, educationPrinciples[0], educationPrinciples[1])) | |||
.addEducationPrincipleKeys(educationPrinciples); | |||
addNonContextualizedDescriptionSections(ruleWithSingleContext); | |||
descriptionSection(HOW_TO_FIX_SECTION_KEY); | |||
} | |||
private void createRuleWithDescriptionSectionsAndSingleContext(NewRepository repo) { | |||
String ruleKey = EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; | |||
NewRule ruleWithSingleContext = repo.createRule(ruleKey).setName("Rule with description sections and single " + | |||
"contexts for 'how to fix'") | |||
.addTags(EDUCATION_KEY); | |||
ruleWithSingleContext | |||
.setHtmlDescription(String.format("This rule contains description sections and single context for 'how to fix' section. To " + | |||
"trigger an issue using this rule you need to scan any text file with a line containing %s key word.", ruleKey)); | |||
addNonContextualizedDescriptionSections(ruleWithSingleContext); | |||
ruleWithSingleContext.addDescriptionSection(descriptionHowToFixSectionWithContext(CONTEXTS[0])); | |||
} | |||
private void createRuleWithDescriptionSectionsAndMultipleContexts(NewRepository repo) { | |||
NewRule ruleWithMultipleContexts = repo.createRule(EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY) | |||
.setName("Rule with description sections and multiple contexts for 'how to fix'") | |||
.addTags(EDUCATION_KEY); | |||
ruleWithMultipleContexts | |||
.setHtmlDescription(String.format("This rule contains description sections and multiple contexts for 'how to fix' section. To trigger " + | |||
"an issue using this rule you need to scan any text file with a line containing %s keyword.", | |||
EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY)); | |||
addNonContextualizedDescriptionSections(ruleWithMultipleContexts); | |||
for (String context : CONTEXTS) { | |||
ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context)); | |||
} | |||
} | |||
private void createRuleWithDescriptionSectionsAndMultipleContextsIncludingOneDetected(NewRepository repo) { | |||
NewRule ruleWithMultipleContexts = repo.createRule(EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY) | |||
.setName("Rule with description sections and multiple contexts (including one detected) for 'how to fix'") | |||
.addTags(EDUCATION_KEY); | |||
ruleWithMultipleContexts | |||
.setHtmlDescription(String.format("This rule contains description sections and multiple contexts (including one detected) for " + | |||
"'how to fix' section. To trigger an issue using this rule you need to scan any text file with a line containing %s keyword.", | |||
EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY)); | |||
addNonContextualizedDescriptionSections(ruleWithMultipleContexts); | |||
for (String context : CONTEXTS) { | |||
ruleWithMultipleContexts.addDescriptionSection(descriptionHowToFixSectionWithContext(context)); | |||
} | |||
} | |||
private static void addNonContextualizedDescriptionSections(NewRule newRule) { | |||
newRule.addDescriptionSection(descriptionSection(INTRODUCTION_SECTION_KEY)) | |||
.addDescriptionSection(descriptionSection(ROOT_CAUSE_SECTION_KEY)) | |||
.addDescriptionSection(descriptionSection(ASSESS_THE_PROBLEM_SECTION_KEY)) | |||
.addDescriptionSection(descriptionSection(RESOURCES_SECTION_KEY)) | |||
.addDescriptionSection(descriptionSection(IGNORED_FAKE_SECTION)); | |||
} | |||
private static RuleDescriptionSection descriptionHowToFixSectionWithContext(String context) { | |||
var ruleContext = new org.sonar.api.server.rule.Context(context, context); | |||
return RuleDescriptionSection.builder() | |||
.sectionKey(HOW_TO_FIX_SECTION_KEY) | |||
.context(ruleContext) | |||
.htmlContent(String.format("%s: %s", HOW_TO_FIX_SECTION_KEY, HTML_LOREM_IPSUM)) | |||
.build(); | |||
} | |||
private static RuleDescriptionSection descriptionSection(String sectionKey) { | |||
return RuleDescriptionSection.builder() | |||
.sectionKey(sectionKey) | |||
.htmlContent(String.format("%s: %s", sectionKey, HTML_LOREM_IPSUM)) | |||
.build(); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
public class EducationPrinciplesSensor extends EducationRuleSensor { | |||
public static final String EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY = "EDUCATION"; | |||
public EducationPrinciplesSensor(FileSystem fs, ActiveRules activeRules) { | |||
super(fs, activeRules, EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); | |||
} | |||
} |
@@ -0,0 +1,97 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
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.batch.sensor.issue.NewIssue; | |||
import org.sonar.api.rule.RuleKey; | |||
import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; | |||
import static org.sonar.education.EducationRulesDefinition.EDUCATION_RULE_REPOSITORY_KEY; | |||
public abstract class EducationRuleSensor implements Sensor { | |||
private final FileSystem fs; | |||
private final ActiveRules activeRules; | |||
private final String ruleKeyName; | |||
private final String tag; | |||
EducationRuleSensor(FileSystem fs, ActiveRules activeRules, String ruleKey) { | |||
this.fs = fs; | |||
this.activeRules = activeRules; | |||
this.ruleKeyName = ruleKey; | |||
this.tag = ruleKey; | |||
} | |||
@Override | |||
public void describe(SensorDescriptor descriptor) { | |||
descriptor | |||
.name("Education sensor for " + tag) | |||
.createIssuesForRuleRepository(EDUCATION_RULE_REPOSITORY_KEY); | |||
} | |||
@Override | |||
public void execute(SensorContext context) { | |||
RuleKey ruleKey = RuleKey.of(EDUCATION_RULE_REPOSITORY_KEY, ruleKeyName); | |||
if (activeRules.find(ruleKey) == null) { | |||
return; | |||
} | |||
for (InputFile inputFile : fs.inputFiles(fs.predicates().hasLanguage(EDUCATION_KEY))) { | |||
processFile(inputFile, context, ruleKey); | |||
} | |||
} | |||
protected String getDetectedContext() { | |||
return null; | |||
} | |||
protected void processFile(InputFile inputFile, SensorContext context, RuleKey ruleKey) { | |||
try { | |||
int[] lineCounter = {1}; | |||
try (InputStreamReader isr = new InputStreamReader(inputFile.inputStream(), inputFile.charset()); | |||
BufferedReader reader = new BufferedReader(isr)) { | |||
reader.lines().forEachOrdered(lineStr -> { | |||
int startIndex = -1; | |||
while ((startIndex = lineStr.indexOf(tag, startIndex + 1)) != -1) { | |||
NewIssue newIssue = context.newIssue(); | |||
newIssue | |||
.forRule(ruleKey) | |||
.at(newIssue.newLocation() | |||
.on(inputFile) | |||
.at(inputFile.newRange(lineCounter[0], startIndex, lineCounter[0], startIndex + tag.length()))) | |||
.setRuleDescriptionContextKey(getDetectedContext()) | |||
.save(); | |||
} | |||
lineCounter[0]++; | |||
}); | |||
} | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to process " + inputFile, e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
public class EducationWithContextsSensor extends EducationRuleSensor { | |||
public static final String EDUCATION_WITH_CONTEXTS_RULE_KEY = "CONTEXTS"; | |||
public EducationWithContextsSensor(FileSystem fs, ActiveRules activeRules) { | |||
super(fs, activeRules, EDUCATION_WITH_CONTEXTS_RULE_KEY); | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
import static org.sonar.education.EducationRulesDefinition.CONTEXTS; | |||
public class EducationWithDetectedContextSensor extends EducationRuleSensor { | |||
public static final String EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY = "DETECTED_CONTEXT"; | |||
public EducationWithDetectedContextSensor(FileSystem fs, ActiveRules activeRules) { | |||
super(fs, activeRules, EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); | |||
} | |||
@Override | |||
protected String getDetectedContext() { | |||
return CONTEXTS[0]; | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import org.sonar.api.batch.fs.FileSystem; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
public class EducationWithSingleContextSensor extends EducationRuleSensor { | |||
public static final String EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY = "SINGLE_CONTEXT"; | |||
public EducationWithSingleContextSensor(FileSystem fs, ActiveRules activeRules) { | |||
super(fs, activeRules, EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.junit.Test; | |||
import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class EducationBuiltInQualityProfileDefinitionTest { | |||
private final EducationBuiltInQualityProfileDefinition underTest = new EducationBuiltInQualityProfileDefinition(); | |||
@Test | |||
public void define_definesAtLeast4rules() { | |||
BuiltInQualityProfilesDefinition.Context context = new BuiltInQualityProfilesDefinition.Context(); | |||
underTest.define(context); | |||
BuiltInQualityProfilesDefinition.BuiltInQualityProfile profile = context.profile("education", "Built in QP for Education"); | |||
assertThat(profile.isDefault()).isTrue(); | |||
assertThat(profile.rules()).hasSizeGreaterThanOrEqualTo(4); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.junit.Test; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class EducationLanguageTest { | |||
private final EducationLanguage underTest = new EducationLanguage(); | |||
@Test | |||
public void getFileSuffixes_notEmpty() { | |||
String[] fileSuffixes = underTest.getFileSuffixes(); | |||
assertThat(fileSuffixes).isNotEmpty(); | |||
} | |||
@Test | |||
public void getName_notEmpty() { | |||
String name = underTest.getName(); | |||
assertThat(name).isNotEmpty(); | |||
} | |||
@Test | |||
public void getKey_notEmpty() { | |||
String key = underTest.getKey(); | |||
assertThat(key).isNotEmpty(); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import org.junit.Test; | |||
import org.sonar.api.Plugin; | |||
import org.sonar.api.SonarEdition; | |||
import org.sonar.api.SonarQubeSide; | |||
import org.sonar.api.SonarRuntime; | |||
import org.sonar.api.internal.PluginContextImpl; | |||
import org.sonar.api.internal.SonarRuntimeImpl; | |||
import org.sonar.api.utils.Version; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class EducationPluginTest { | |||
@Test | |||
public void define_addSomeExtensionsForSonarQube() { | |||
SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("9.5"), SonarQubeSide.SCANNER, SonarEdition.COMMUNITY); | |||
Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build(); | |||
EducationPlugin plugin = new EducationPlugin(); | |||
plugin.define(context); | |||
assertThat(context.getExtensions()).isNotEmpty(); | |||
} | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education; | |||
import java.util.List; | |||
import org.junit.Test; | |||
import org.sonar.api.server.rule.RulesDefinition; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class EducationRulesDefinitionTest { | |||
@Test | |||
public void define_addsRuleDefinitions() { | |||
EducationRulesDefinition educationRulesDefinition = new EducationRulesDefinition(); | |||
RulesDefinition.Context context = new RulesDefinition.Context(); | |||
educationRulesDefinition.define(context); | |||
List<RulesDefinition.Repository> repositories = context.repositories(); | |||
assertThat(repositories).hasSize(1); | |||
RulesDefinition.Repository repository = context.repositories().get(0); | |||
List<RulesDefinition.Rule> rules = repository.rules(); | |||
assertThat(rules).hasSizeGreaterThanOrEqualTo(4); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.io.IOException; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.education.sensors.EducationPrinciplesSensor.EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY; | |||
public class EducationPrinciplesSensorTest extends EducationSensorTest { | |||
@Test | |||
public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { | |||
DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_GENERIC_CONCEPTS_RULE_KEY); | |||
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); | |||
fs.add(inputFile); | |||
SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); | |||
var sensor = new EducationPrinciplesSensor(fs, activeRules); | |||
sensor.execute(sensorContextTester); | |||
assertThat(sensorContextTester.allIssues()).hasSize(1); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.nio.charset.Charset; | |||
import org.junit.Before; | |||
import org.junit.Rule; | |||
import org.junit.rules.TemporaryFolder; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.fs.internal.TestInputFileBuilder; | |||
import org.sonar.api.batch.rule.ActiveRule; | |||
import org.sonar.api.batch.rule.ActiveRules; | |||
import static org.mockito.ArgumentMatchers.any; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import static org.sonar.education.EducationRulesDefinition.EDUCATION_KEY; | |||
public class EducationSensorTest { | |||
@Rule | |||
public TemporaryFolder temp = new TemporaryFolder(); | |||
protected final ActiveRules activeRules = mock(ActiveRules.class); | |||
@Before | |||
public void before() { | |||
when(activeRules.find(any())).thenReturn(mock(ActiveRule.class)); | |||
} | |||
protected DefaultInputFile newTestFile(String content) { | |||
return new TestInputFileBuilder("foo", "hello.edu") | |||
.setLanguage(EDUCATION_KEY) | |||
.setContents(content) | |||
.setCharset(Charset.defaultCharset()) | |||
.build(); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.io.IOException; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.education.sensors.EducationWithContextsSensor.EDUCATION_WITH_CONTEXTS_RULE_KEY; | |||
public class EducationWithContextsSensorTest extends EducationSensorTest { | |||
@Test | |||
public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { | |||
DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_CONTEXTS_RULE_KEY); | |||
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); | |||
fs.add(inputFile); | |||
SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); | |||
var sensor = new EducationWithContextsSensor(fs, activeRules); | |||
sensor.execute(sensorContextTester); | |||
assertThat(sensorContextTester.allIssues()).hasSize(1); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.io.IOException; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.education.sensors.EducationWithDetectedContextSensor.EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY; | |||
public class EducationWithDetectedContextSensorTest extends EducationSensorTest { | |||
@Test | |||
public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { | |||
DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_DETECTED_CONTEXT_RULE_KEY); | |||
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); | |||
fs.add(inputFile); | |||
SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); | |||
var sensor = new EducationWithDetectedContextSensor(fs, activeRules); | |||
sensor.execute(sensorContextTester); | |||
assertThat(sensorContextTester.allIssues()).hasSize(1); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2022 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.education.sensors; | |||
import java.io.IOException; | |||
import org.junit.Test; | |||
import org.sonar.api.batch.fs.internal.DefaultFileSystem; | |||
import org.sonar.api.batch.fs.internal.DefaultInputFile; | |||
import org.sonar.api.batch.sensor.internal.SensorContextTester; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.education.sensors.EducationWithSingleContextSensor.EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY; | |||
public class EducationWithSingleContextSensorTest extends EducationSensorTest { | |||
@Test | |||
public void processFile_givenCorrectTagPassed_oneSecurityHotspotWithContextsIsRaised() throws IOException { | |||
DefaultInputFile inputFile = newTestFile(EDUCATION_WITH_SINGLE_CONTEXT_RULE_KEY); | |||
DefaultFileSystem fs = new DefaultFileSystem(temp.newFolder()); | |||
fs.add(inputFile); | |||
SensorContextTester sensorContextTester = SensorContextTester.create(temp.newFolder().toPath()); | |||
var sensor = new EducationWithSingleContextSensor(fs, activeRules); | |||
sensor.execute(sensorContextTester); | |||
assertThat(sensorContextTester.allIssues()).hasSize(1); | |||
} | |||
} |
@@ -13,6 +13,7 @@ pluginManagement { | |||
rootProject.name = 'sonarqube' | |||
include 'plugins:sonar-xoo-plugin' | |||
include 'plugins:sonar-education-plugin' | |||
include 'server:sonar-auth-common' | |||
include 'server:sonar-auth-bitbucket' |