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 | |||||
} | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} | |||||
} |
/* | |||||
* 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"}; | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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]; | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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(); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
/* | |||||
* 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); | |||||
} | |||||
} |
rootProject.name = 'sonarqube' | rootProject.name = 'sonarqube' | ||||
include 'plugins:sonar-xoo-plugin' | include 'plugins:sonar-xoo-plugin' | ||||
include 'plugins:sonar-education-plugin' | |||||
include 'server:sonar-auth-common' | include 'server:sonar-auth-common' | ||||
include 'server:sonar-auth-bitbucket' | include 'server:sonar-auth-bitbucket' |