<sonar.apiVersion>5.6.1</sonar.apiVersion>
<java.plugin.version>4.0</java.plugin.version>
<jdk.min.version>1.8</jdk.min.version>
- <sonar.pluginKey>helloworld</sonar.pluginKey>
+ <sonar.pluginKey>customjavaplugin</sonar.pluginKey>
</properties>
<dependencies>
<version>1.17</version>
<extensions>true</extensions>
<configuration>
- <pluginClass>de.example.plugins.helloworld.HelloWorldPlugin</pluginClass>
+ <pluginClass>de.example.plugins.custom.CustomPlugin</pluginClass>
</configuration>
</plugin>
<plugin>
--- /dev/null
+package de.example.custom.checks;
+
+import java.util.List;
+
+import org.sonar.plugins.java.api.JavaCheck;
+
+import com.google.common.collect.ImmutableList;
+
+public final class CheckList {
+ public static final String REPOSITORY_KEY = "customjava";
+ public static final String REPOSITORY_NAME = "Custom Java";
+
+ private CheckList() {
+ }
+
+ public static List<Class> getChecks() {
+ return ImmutableList.<Class>builder()
+ .addAll(getJavaChecks())
+ .addAll(getJavaTestChecks())
+ .addAll(getXmlChecks())
+ .build();
+ }
+
+ public static List<Class<? extends JavaCheck>> getJavaChecks() {
+ return ImmutableList.<Class<? extends JavaCheck>>builder()
+ .add(ParameterCheck.class)
+ .add(SpringServiceInstanceFieldCheck.class)
+ .build();
+ }
+
+ public static List<Class<? extends JavaCheck>> getJavaTestChecks() {
+ return ImmutableList.<Class<? extends JavaCheck>>builder()
+ .build();
+ }
+
+ public static List<Class<? extends JavaCheck>> getXmlChecks() {
+ return ImmutableList.<Class<? extends JavaCheck>>builder()
+ .build();
+ }
+
+ private static List<Class<? extends JavaCheck>> getMavenChecks() {
+ return ImmutableList.<Class<? extends JavaCheck>>builder()
+ .build();
+ }
+}
--- /dev/null
+package de.example.custom.checks;
+
+import java.util.List;
+
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.check.Rule;
+import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
+import org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol;
+import org.sonar.plugins.java.api.semantic.Type;
+import org.sonar.plugins.java.api.tree.MethodTree;
+import org.sonar.plugins.java.api.tree.Tree;
+import org.sonar.plugins.java.api.tree.Tree.Kind;
+
+import com.google.common.collect.ImmutableList;
+
+@Rule(key = "GU0001")
+public class ParameterCheck extends IssuableSubscriptionVisitor {
+ private static final Logger LOG = Loggers.get(ParameterCheck.class);
+
+
+ @Override
+ public List<Kind> nodesToVisit() {
+ return ImmutableList.of(Kind.METHOD);
+ }
+
+ @Override
+ public void visitNode(Tree tree) {
+ LOG.info("Visiting Node");
+
+ MethodTree method = (MethodTree) tree;
+
+ if (method.parameters().size() == 1) {
+ MethodSymbol symbol = method.symbol();
+ Type firstParameterType = symbol.parameterTypes().get(0);
+ Type returnType = symbol.returnType().type();
+ if(returnType.is(firstParameterType.fullyQualifiedName())) {
+ reportIssue(method.simpleName(), "Never do that!");
+ }
+ }
+
+ }
+}
--- /dev/null
+package de.example.custom.checks;
+
+import java.util.List;
+
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.check.Rule;
+import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
+import org.sonar.plugins.java.api.JavaFileScannerContext;
+import org.sonar.plugins.java.api.semantic.Symbol;
+import org.sonar.plugins.java.api.tree.ClassTree;
+import org.sonar.plugins.java.api.tree.Tree;
+import org.sonar.plugins.java.api.tree.Tree.Kind;
+import org.sonar.plugins.java.api.tree.VariableTree;
+
+import com.google.common.collect.ImmutableList;
+
+@Rule(key = "GU0002")
+public class SpringServiceInstanceFieldCheck extends IssuableSubscriptionVisitor {
+ private static final Logger LOG = Loggers.get(SpringServiceInstanceFieldCheck.class);
+
+ private JavaFileScannerContext context;
+
+
+ @Override
+ public List<Kind> nodesToVisit() {
+ return ImmutableList.of(Kind.CLASS, Kind.VARIABLE);
+ }
+
+ @Override
+ public void visitNode(Tree tree) {
+ if (tree.is(Kind.CLASS) && isSpringService((ClassTree) tree)) {
+
+ }
+
+ }
+
+
+ private static boolean isOwnedByASpringService(VariableTree variable) {
+ Symbol owner = variable.symbol().owner();
+ return owner.isTypeSymbol() && (owner.type().isSubtypeOf("javax.servlet.http.HttpServlet") || owner.type().isSubtypeOf("org.apache.struts.action.Action"));
+ }
+
+ private static boolean isSpringService(ClassTree tree) {
+ tree.symbol().metadata().isAnnotatedWith("javax.inject.Inject");
+ return true;
+
+ }
+
+
+}
+++ /dev/null
-package de.example.helloworld.checks;
-
-import java.util.List;
-
-import org.sonar.plugins.java.api.JavaCheck;
-
-import com.google.common.collect.ImmutableList;
-
-public final class CheckList {
- public static final String REPOSITORY_KEY = "helloworld";
- public static final String REPOSITORY_NAME = "Hello World";
-
- private CheckList() {
- }
-
- public static List<Class> getChecks() {
- return ImmutableList.<Class>builder()
- .addAll(getJavaChecks())
- .addAll(getJavaTestChecks())
- .addAll(getXmlChecks())
- .build();
- }
-
- public static List<Class<? extends JavaCheck>> getJavaChecks() {
- return ImmutableList.<Class<? extends JavaCheck>>builder()
- .add(HelloWorldCheck.class)
- .add(SpringServiceInstanceFieldCheck.class)
- .build();
- }
-
- public static List<Class<? extends JavaCheck>> getJavaTestChecks() {
- return ImmutableList.<Class<? extends JavaCheck>>builder()
- .build();
- }
-
- public static List<Class<? extends JavaCheck>> getXmlChecks() {
- return ImmutableList.<Class<? extends JavaCheck>>builder()
- .build();
- }
-
- private static List<Class<? extends JavaCheck>> getMavenChecks() {
- return ImmutableList.<Class<? extends JavaCheck>>builder()
- .build();
- }
-}
+++ /dev/null
-package de.example.helloworld.checks;
-
-import java.util.List;
-
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.check.Rule;
-import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
-import org.sonar.plugins.java.api.semantic.Symbol.MethodSymbol;
-import org.sonar.plugins.java.api.semantic.Type;
-import org.sonar.plugins.java.api.tree.MethodTree;
-import org.sonar.plugins.java.api.tree.Tree;
-import org.sonar.plugins.java.api.tree.Tree.Kind;
-
-import com.google.common.collect.ImmutableList;
-
-@Rule(key = "GU0001")
-public class HelloWorldCheck extends IssuableSubscriptionVisitor {
- private static final Logger LOG = Loggers.get(HelloWorldCheck.class);
-
-
- @Override
- public List<Kind> nodesToVisit() {
- return ImmutableList.of(Kind.METHOD);
- }
-
- @Override
- public void visitNode(Tree tree) {
- LOG.info("Visiting Node");
-
- MethodTree method = (MethodTree) tree;
-
- if (method.parameters().size() == 1) {
- MethodSymbol symbol = method.symbol();
- Type firstParameterType = symbol.parameterTypes().get(0);
- Type returnType = symbol.returnType().type();
- if(returnType.is(firstParameterType.fullyQualifiedName())) {
- reportIssue(method.simpleName(), "Never do that!");
- }
- }
-
- }
-}
+++ /dev/null
-package de.example.helloworld.checks;
-
-import java.util.List;
-
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.check.Rule;
-import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
-import org.sonar.plugins.java.api.JavaFileScannerContext;
-import org.sonar.plugins.java.api.semantic.Symbol;
-import org.sonar.plugins.java.api.tree.ClassTree;
-import org.sonar.plugins.java.api.tree.Tree;
-import org.sonar.plugins.java.api.tree.Tree.Kind;
-import org.sonar.plugins.java.api.tree.VariableTree;
-
-import com.google.common.collect.ImmutableList;
-
-@Rule(key = "GU0002")
-public class SpringServiceInstanceFieldCheck extends IssuableSubscriptionVisitor {
- private static final Logger LOG = Loggers.get(SpringServiceInstanceFieldCheck.class);
-
- private JavaFileScannerContext context;
-
-
- @Override
- public List<Kind> nodesToVisit() {
- return ImmutableList.of(Kind.CLASS, Kind.VARIABLE);
- }
-
- @Override
- public void visitNode(Tree tree) {
- if (tree.is(Kind.CLASS) && isSpringService((ClassTree) tree)) {
-
- }
-
- }
-
-
- private static boolean isOwnedByASpringService(VariableTree variable) {
- Symbol owner = variable.symbol().owner();
- return owner.isTypeSymbol() && (owner.type().isSubtypeOf("javax.servlet.http.HttpServlet") || owner.type().isSubtypeOf("org.apache.struts.action.Action"));
- }
-
- private static boolean isSpringService(ClassTree tree) {
- tree.symbol().metadata().isAnnotatedWith("javax.inject.Inject");
- return true;
-
- }
-
-
-}
--- /dev/null
+package de.example.plugins.custom;
+
+import org.sonar.api.Plugin;
+
+import com.google.common.collect.ImmutableList;
+
+
+public class CustomPlugin implements Plugin {
+
+ @Override
+ public void define(Context context) {
+
+ ImmutableList.Builder<Object> builder = ImmutableList.builder();
+ builder.add(
+ CustomRulesDefinition.class,
+ CustomRulesCheckRegistrar.class);
+
+ context.addExtensions(builder.build());
+ }
+}
--- /dev/null
+package de.example.plugins.custom;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.sonar.api.profiles.ProfileDefinition;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.utils.AnnotationUtils;
+import org.sonar.api.utils.ValidationMessages;
+import org.sonar.java.checks.CheckList;
+import org.sonar.plugins.java.Java;
+import org.sonar.plugins.java.JavaRulesDefinition;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Resources;
+import com.google.gson.Gson;
+
+public class CustomProfile extends ProfileDefinition {
+
+ private final Gson gson = new Gson();
+ private final RuleFinder ruleFinder;
+ public CustomProfile(RuleFinder ruleFinder) {
+ this.ruleFinder = ruleFinder;
+ }
+
+ @Override
+ public RulesProfile createProfile(ValidationMessages messages) {
+ RulesProfile profile = RulesProfile.create("Sonar way", Java.KEY);
+ URL resource = JavaRulesDefinition.class.getResource("/org/sonar/l10n/java/rules/custom/Custom_profile.json");
+ Profile jsonProfile = gson.fromJson(readResource(resource), Profile.class);
+ Map<String, String> keys = legacyKeys();
+ for (String key : jsonProfile.ruleKeys) {
+ profile.activateRule(ruleFinder.findByKey(CheckList.REPOSITORY_KEY, keys.get(key)), null);
+ }
+ return profile;
+ }
+
+ private static String readResource(URL resource) {
+ try {
+ return Resources.toString(resource, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read: " + resource, e);
+ }
+ }
+
+ private static Map<String, String> legacyKeys() {
+ Map<String, String> result = new HashMap<>();
+ for (Class checkClass : CheckList.getChecks()) {
+ org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getAnnotation(checkClass, org.sonar.check.Rule.class);
+ String key = ruleAnnotation.key();
+ org.sonar.java.RspecKey rspecKeyAnnotation = AnnotationUtils.getAnnotation(checkClass, org.sonar.java.RspecKey.class);
+ String rspecKey = key;
+ if(rspecKeyAnnotation != null) {
+ rspecKey = rspecKeyAnnotation.value();
+ }
+ result.put(rspecKey, key);
+ }
+ return result;
+ }
+
+ private static class Profile {
+ String name;
+ List<String> ruleKeys;
+ }
+
+ }
--- /dev/null
+package de.example.plugins.custom;
+
+import org.sonar.plugins.java.api.CheckRegistrar;
+
+import de.example.custom.checks.CheckList;
+
+public class CustomRulesCheckRegistrar implements CheckRegistrar {
+
+ @Override
+ public void register(RegistrarContext registrarContext) {
+ registrarContext.registerClassesForRepository(CheckList.REPOSITORY_KEY, CheckList.getJavaChecks(), CheckList.getJavaTestChecks());
+ }
+
+}
--- /dev/null
+package de.example.plugins.custom;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.server.debt.DebtRemediationFunction;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.server.rule.RulesDefinitionAnnotationLoader;
+import org.sonar.api.utils.AnnotationUtils;
+import org.sonar.check.Cardinality;
+import org.sonar.plugins.java.Java;
+import org.sonar.squidbridge.annotations.RuleTemplate;
+import org.sonar.squidbridge.rules.ExternalDescriptionLoader;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Resources;
+import com.google.gson.Gson;
+
+import de.example.custom.checks.CheckList;
+
+/**
+ * Definition of rules.
+ */
+public class CustomRulesDefinition implements RulesDefinition {
+ private static final String RESOURCE_BASE_PATH = "/de/example/l10n/java/rules/custom";
+
+ private final Gson gson = new Gson();
+
+ @Override
+ public void define(Context context) {
+ NewRepository repository = context
+ .createRepository(CheckList.REPOSITORY_KEY, Java.KEY)
+ .setName(CheckList.REPOSITORY_NAME);
+ List<Class> checks = CheckList.getChecks();
+ new RulesDefinitionAnnotationLoader().load(repository, Iterables.toArray(checks, Class.class));
+ for (Class ruleClass : checks) {
+ newRule(ruleClass, repository);
+ }
+ repository.done();
+ }
+
+ @VisibleForTesting
+ protected void newRule(Class<?> ruleClass, NewRepository repository) {
+
+ org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getAnnotation(ruleClass, org.sonar.check.Rule.class);
+ if (ruleAnnotation == null) {
+ throw new IllegalArgumentException("No Rule annotation was found on " + ruleClass);
+ }
+ String ruleKey = ruleAnnotation.key();
+ if (StringUtils.isEmpty(ruleKey)) {
+ throw new IllegalArgumentException("No key is defined in Rule annotation of " + ruleClass);
+ }
+ NewRule rule = repository.rule(ruleKey);
+ if (rule == null) {
+ throw new IllegalStateException("No rule was created for " + ruleClass + " in " + repository.key());
+ }
+ rule.setTemplate(AnnotationUtils.getAnnotation(ruleClass, RuleTemplate.class) != null);
+ if (ruleAnnotation.cardinality() == Cardinality.MULTIPLE) {
+ throw new IllegalArgumentException("Cardinality is not supported, use the RuleTemplate annotation instead for " + ruleClass);
+ }
+ ruleMetadata(ruleClass, rule);
+ }
+
+ private void ruleMetadata(Class<?> ruleClass, NewRule rule) {
+ String metadataKey = rule.key();
+ org.sonar.java.RspecKey rspecKeyAnnotation = AnnotationUtils.getAnnotation(ruleClass, org.sonar.java.RspecKey.class);
+ if (rspecKeyAnnotation != null) {
+ metadataKey = rspecKeyAnnotation.value();
+ rule.setInternalKey(metadataKey);
+ }
+ addHtmlDescription(rule, metadataKey);
+ addMetadata(rule, metadataKey);
+
+ }
+
+ private void addMetadata(NewRule rule, String metadataKey) {
+ URL resource = ExternalDescriptionLoader.class.getResource(RESOURCE_BASE_PATH + "/" + metadataKey + "_java.json");
+ if (resource != null) {
+ RuleMetatada metatada = gson.fromJson(readResource(resource), RuleMetatada.class);
+ rule.setSeverity(metatada.defaultSeverity.toUpperCase());
+ rule.setName(metatada.title);
+ rule.addTags(metatada.tags);
+ rule.setStatus(RuleStatus.valueOf(metatada.status.toUpperCase()));
+ if(metatada.remediation != null) {
+ rule.setDebtRemediationFunction(metatada.remediation.remediationFunction(rule.debtRemediationFunctions()));
+ rule.setGapDescription(metatada.remediation.linearDesc);
+ }
+ }
+ }
+
+ private static void addHtmlDescription(NewRule rule, String metadataKey) {
+ URL resource = CustomRulesDefinition.class.getResource(RESOURCE_BASE_PATH + "/" + metadataKey + "_java.html");
+ if (resource != null) {
+ rule.setHtmlDescription(readResource(resource));
+ }
+ }
+
+ private static String readResource(URL resource) {
+ try {
+ return Resources.toString(resource, Charsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read: " + resource, e);
+ }
+ }
+
+ private static class RuleMetatada {
+ String title;
+ String status;
+ @Nullable
+ Remediation remediation;
+
+ String[] tags;
+ String defaultSeverity;
+ }
+
+ private static class Remediation {
+ String func;
+ String constantCost;
+ String linearDesc;
+ String linearOffset;
+ String linearFactor;
+
+ public DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) {
+ if(func.startsWith("Constant")) {
+ return drf.constantPerIssue(constantCost.replace("mn", "min"));
+ }
+ if("Linear".equals(func)) {
+ return drf.linear(linearFactor.replace("mn", "min"));
+ }
+ return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min"));
+ }
+ }
+
+}
--- /dev/null
+package de.example.plugins.custom;
+
+import org.sonar.api.batch.sensor.Sensor;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.SensorDescriptor;
+import org.sonar.plugins.java.Java;
+
+public class CustomSensor implements Sensor {
+
+ @Override
+ public void describe(SensorDescriptor descriptor) {
+ descriptor.onlyOnLanguage(Java.KEY);
+ descriptor.name("Custom Sensor");
+ }
+
+ @Override
+ public void execute(SensorContext context) {
+
+ }
+
+}
+++ /dev/null
-package de.example.plugins.helloworld;
-
-import org.sonar.api.Plugin;
-
-import com.google.common.collect.ImmutableList;
-
-
-public class HelloWorldPlugin implements Plugin {
-
- @Override
- public void define(Context context) {
-
- ImmutableList.Builder<Object> builder = ImmutableList.builder();
- builder.add(
- HelloWorldRulesDefinition.class,
- HelloWorldRulesCheckRegistrar.class);
-
- context.addExtensions(builder.build());
- }
-}
+++ /dev/null
-package de.example.plugins.helloworld;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.sonar.api.profiles.ProfileDefinition;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.utils.AnnotationUtils;
-import org.sonar.api.utils.ValidationMessages;
-import org.sonar.java.checks.CheckList;
-import org.sonar.plugins.java.Java;
-import org.sonar.plugins.java.JavaRulesDefinition;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
-import com.google.gson.Gson;
-
-public class HelloWorldProfile extends ProfileDefinition {
-
- private final Gson gson = new Gson();
- private final RuleFinder ruleFinder;
- public HelloWorldProfile(RuleFinder ruleFinder) {
- this.ruleFinder = ruleFinder;
- }
-
- @Override
- public RulesProfile createProfile(ValidationMessages messages) {
- RulesProfile profile = RulesProfile.create("Sonar way", Java.KEY);
- URL resource = JavaRulesDefinition.class.getResource("/org/sonar/l10n/java/rules/squid/Sonar_way_profile.json");
- Profile jsonProfile = gson.fromJson(readResource(resource), Profile.class);
- Map<String, String> keys = legacyKeys();
- for (String key : jsonProfile.ruleKeys) {
- profile.activateRule(ruleFinder.findByKey(CheckList.REPOSITORY_KEY, keys.get(key)), null);
- }
- return profile;
- }
-
- private static String readResource(URL resource) {
- try {
- return Resources.toString(resource, Charsets.UTF_8);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read: " + resource, e);
- }
- }
-
- private static Map<String, String> legacyKeys() {
- Map<String, String> result = new HashMap<>();
- for (Class checkClass : CheckList.getChecks()) {
- org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getAnnotation(checkClass, org.sonar.check.Rule.class);
- String key = ruleAnnotation.key();
- org.sonar.java.RspecKey rspecKeyAnnotation = AnnotationUtils.getAnnotation(checkClass, org.sonar.java.RspecKey.class);
- String rspecKey = key;
- if(rspecKeyAnnotation != null) {
- rspecKey = rspecKeyAnnotation.value();
- }
- result.put(rspecKey, key);
- }
- return result;
- }
-
- private static class Profile {
- String name;
- List<String> ruleKeys;
- }
-
- }
+++ /dev/null
-package de.example.plugins.helloworld;
-
-import org.sonar.plugins.java.api.CheckRegistrar;
-
-import de.example.helloworld.checks.CheckList;
-
-public class HelloWorldRulesCheckRegistrar implements CheckRegistrar {
-
- @Override
- public void register(RegistrarContext registrarContext) {
- registrarContext.registerClassesForRepository(CheckList.REPOSITORY_KEY, CheckList.getJavaChecks(), CheckList.getJavaTestChecks());
- }
-
-}
+++ /dev/null
-package de.example.plugins.helloworld;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.server.debt.DebtRemediationFunction;
-import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.server.rule.RulesDefinitionAnnotationLoader;
-import org.sonar.api.utils.AnnotationUtils;
-import org.sonar.check.Cardinality;
-import org.sonar.plugins.java.Java;
-import org.sonar.squidbridge.annotations.RuleTemplate;
-import org.sonar.squidbridge.rules.ExternalDescriptionLoader;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.collect.Iterables;
-import com.google.common.io.Resources;
-import com.google.gson.Gson;
-
-import de.example.helloworld.checks.CheckList;
-
-/**
- * Definition of rules.
- */
-public class HelloWorldRulesDefinition implements RulesDefinition {
- private static final String RESOURCE_BASE_PATH = "/de/example/l10n/helloworld/rules/helloworld";
-
- private final Gson gson = new Gson();
-
- @Override
- public void define(Context context) {
- NewRepository repository = context
- .createRepository(CheckList.REPOSITORY_KEY, Java.KEY)
- .setName(CheckList.REPOSITORY_NAME);
- List<Class> checks = CheckList.getChecks();
- new RulesDefinitionAnnotationLoader().load(repository, Iterables.toArray(checks, Class.class));
- for (Class ruleClass : checks) {
- newRule(ruleClass, repository);
- }
- repository.done();
- }
-
- @VisibleForTesting
- protected void newRule(Class<?> ruleClass, NewRepository repository) {
-
- org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getAnnotation(ruleClass, org.sonar.check.Rule.class);
- if (ruleAnnotation == null) {
- throw new IllegalArgumentException("No Rule annotation was found on " + ruleClass);
- }
- String ruleKey = ruleAnnotation.key();
- if (StringUtils.isEmpty(ruleKey)) {
- throw new IllegalArgumentException("No key is defined in Rule annotation of " + ruleClass);
- }
- NewRule rule = repository.rule(ruleKey);
- if (rule == null) {
- throw new IllegalStateException("No rule was created for " + ruleClass + " in " + repository.key());
- }
- rule.setTemplate(AnnotationUtils.getAnnotation(ruleClass, RuleTemplate.class) != null);
- if (ruleAnnotation.cardinality() == Cardinality.MULTIPLE) {
- throw new IllegalArgumentException("Cardinality is not supported, use the RuleTemplate annotation instead for " + ruleClass);
- }
- ruleMetadata(ruleClass, rule);
- }
-
- private void ruleMetadata(Class<?> ruleClass, NewRule rule) {
- String metadataKey = rule.key();
- org.sonar.java.RspecKey rspecKeyAnnotation = AnnotationUtils.getAnnotation(ruleClass, org.sonar.java.RspecKey.class);
- if (rspecKeyAnnotation != null) {
- metadataKey = rspecKeyAnnotation.value();
- rule.setInternalKey(metadataKey);
- }
- addHtmlDescription(rule, metadataKey);
- addMetadata(rule, metadataKey);
-
- }
-
- private void addMetadata(NewRule rule, String metadataKey) {
- URL resource = ExternalDescriptionLoader.class.getResource(RESOURCE_BASE_PATH + "/" + metadataKey + "_java.json");
- if (resource != null) {
- RuleMetatada metatada = gson.fromJson(readResource(resource), RuleMetatada.class);
- rule.setSeverity(metatada.defaultSeverity.toUpperCase());
- rule.setName(metatada.title);
- rule.addTags(metatada.tags);
- rule.setStatus(RuleStatus.valueOf(metatada.status.toUpperCase()));
- if(metatada.remediation != null) {
- rule.setDebtRemediationFunction(metatada.remediation.remediationFunction(rule.debtRemediationFunctions()));
- rule.setGapDescription(metatada.remediation.linearDesc);
- }
- }
- }
-
- private static void addHtmlDescription(NewRule rule, String metadataKey) {
- URL resource = HelloWorldRulesDefinition.class.getResource(RESOURCE_BASE_PATH + "/" + metadataKey + "_java.html");
- if (resource != null) {
- rule.setHtmlDescription(readResource(resource));
- }
- }
-
- private static String readResource(URL resource) {
- try {
- return Resources.toString(resource, Charsets.UTF_8);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read: " + resource, e);
- }
- }
-
- private static class RuleMetatada {
- String title;
- String status;
- @Nullable
- Remediation remediation;
-
- String[] tags;
- String defaultSeverity;
- }
-
- private static class Remediation {
- String func;
- String constantCost;
- String linearDesc;
- String linearOffset;
- String linearFactor;
-
- public DebtRemediationFunction remediationFunction(DebtRemediationFunctions drf) {
- if(func.startsWith("Constant")) {
- return drf.constantPerIssue(constantCost.replace("mn", "min"));
- }
- if("Linear".equals(func)) {
- return drf.linear(linearFactor.replace("mn", "min"));
- }
- return drf.linearWithOffset(linearFactor.replace("mn", "min"), linearOffset.replace("mn", "min"));
- }
- }
-
-}
+++ /dev/null
-package de.example.plugins.helloworld;
-
-import org.sonar.api.batch.sensor.Sensor;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.plugins.java.Java;
-
-public class HelloWorldSensor implements Sensor {
-
- @Override
- public void describe(SensorDescriptor descriptor) {
- descriptor.onlyOnLanguage(Java.KEY);
- descriptor.name("HelloWorld Sensor");
- }
-
- @Override
- public void execute(SensorContext context) {
-
- }
-
-}
+++ /dev/null
-<p>HelloWorld rule description.</p>
-<h2>Noncompliant Code Example</h2>
-<pre>
-class MyClass {
-
- int foo1(int value) { return 0; }
-
- MyClass foo2(MyClass value) { return null; }
-
- ...
-
-}
-</pre>
-<h2>See</h2>
-<ul>
- <li> <a href="https://www.securecoding.cert.org/confluence/x/EYBUC">CERT, MSC11-J.</a> - Do not let session information leak within a servlet </li>
-</ul>
-
+++ /dev/null
-{
- "title": "HelloWorld SonarQube rule",
- "status": "ready",
- "remediation": {
- "func": "Constant\/Issue",
- "constantCost": "5min"
- },
- "tags": [
- "bad-practice"
- ],
- "defaultSeverity": "Major"
-}
--- /dev/null
+{
+ "name": "Custom profile",
+ "ruleKeys": [
+ "GU0001",
+ "GU0002"
+ ]
+}
--- /dev/null
+<p>Custom rule description.</p>
+<h2>Noncompliant Code Example</h2>
+<pre>
+class MyClass {
+
+ int foo1(int value) { return 0; }
+
+ MyClass foo2(MyClass value) { return null; }
+
+ ...
+
+}
+</pre>
+<h2>See</h2>
+<ul>
+ <li> <a href="https://www.securecoding.cert.org/confluence/x/EYBUC">CERT, MSC11-J.</a> - You are doing wrong!!! </li>
+</ul>
+
--- /dev/null
+{
+ "title": "Custom SonarQube rule",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "bad-practice"
+ ],
+ "defaultSeverity": "Major"
+}
+++ /dev/null
-class MyClass {
-
- MyClass(MyClass mc) { }
-
- int foo1() { return 0; }
-
- void foo2(int value) { }
-
- // Noncompliant@+1 [[startColumn=6;endLine=+0;endColumn=10;effortToFix=4]] {{Never do that!}}
- int foo3(int value) { return 0; }
-
- Object foo4(int value) { return null; }
-
- // Noncompliant@+1 [[startColumn=10;endLine=+0;endColumn=14;effortToFix=4]] {{Never do that!}}
- MyClass foo5(MyClass value) { return null; }
-
-}
--- /dev/null
+class MyClass {
+
+ MyClass(MyClass mc) { }
+
+ int foo1() { return 0; }
+
+ void foo2(int value) { }
+
+ // Noncompliant@+1 [[startColumn=6;endLine=+0;endColumn=10;effortToFix=4]] {{Never do that!}}
+ int foo3(int value) { return 0; }
+
+ Object foo4(int value) { return null; }
+
+ // Noncompliant@+1 [[startColumn=10;endLine=+0;endColumn=14;effortToFix=4]] {{Never do that!}}
+ MyClass foo5(MyClass value) { return null; }
+
+}
--- /dev/null
+package de.example.custom.checks;
+
+import org.junit.Test;
+import org.sonar.java.checks.verifier.JavaCheckVerifier;
+
+public class ParameterCheckTest {
+
+ @Test
+ public void test() {
+ JavaCheckVerifier.verify("src/test/files/checks/ParameterCheck.java", new ParameterCheck());
+ }
+}
--- /dev/null
+package de.example.custom.checks;
+
+import org.junit.Test;
+import org.sonar.java.checks.verifier.JavaCheckVerifier;
+
+public class SpringServiceInstanceFieldCheckTest {
+ private static final String FILENAME = "src/test/files/checks/SpringServiceInstanceFieldCheck.java";
+
+ //@Test
+ public void test() {
+ JavaCheckVerifier.verify(FILENAME, new SpringServiceInstanceFieldCheck());
+ }
+}
+++ /dev/null
-package de.example.helloworld.checks;
-
-import org.junit.Test;
-import org.sonar.java.checks.verifier.JavaCheckVerifier;
-
-public class HelloWorldCheckTest {
-
- @Test
- public void test() {
- JavaCheckVerifier.verify("src/test/files/checks/HelloWorldCheck.java", new HelloWorldCheck());
- }
-}
+++ /dev/null
-package de.example.helloworld.checks;
-
-import org.junit.Test;
-import org.sonar.java.checks.verifier.JavaCheckVerifier;
-
-public class SpringServiceInstanceFieldCheckTest {
- private static final String FILENAME = "src/test/files/checks/SpringServiceInstanceFieldCheck.java";
-
- @Test
- public void test() {
- JavaCheckVerifier.verify(FILENAME, new SpringServiceInstanceFieldCheck());
- }
-}