aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2014-03-25 23:10:45 +0100
committerSimon Brandhof <simon.brandhof@gmail.com>2014-03-25 23:10:46 +0100
commit1b8416c73a97f61899286d2e1f4e3e7685135e9a (patch)
tree2894a01e8efd50df65264f7f31328f46f0a756a0 /sonar-plugin-api
parent0abfc8ad75bb91dceba66f9e5905268312bed038 (diff)
downloadsonarqube-1b8416c73a97f61899286d2e1f4e3e7685135e9a.tar.gz
sonarqube-1b8416c73a97f61899286d2e1f4e3e7685135e9a.zip
SONAR-4908 extract RulesDefinitionAnnotationLoader
+ refactor the classes RegisterXXX used during server startup
Diffstat (limited to 'sonar-plugin-api')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java213
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoader.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromAnnotations.java)22
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java33
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoaderTest.java (renamed from sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromAnnotationsTest.java)26
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java2
5 files changed, 241 insertions, 55 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
index fff3f96e797..7c01f5836c7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
@@ -139,6 +139,170 @@ import java.util.Set;
public interface RulesDefinition extends ServerExtension {
/**
+ * Default sub-characteristics of technical debt model. See http://www.sqale.org
+ */
+ final class SubCharacteristics {
+ private SubCharacteristics() {
+ // only constants
+ }
+
+ /**
+ * Related to characteristic REUSABILITY
+ */
+ public static final String MODULARITY = "MODULARITY";
+
+ /**
+ * Related to characteristic REUSABILITY
+ */
+ public static final String TRANSPORTABILITY = "TRANSPORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String COMPILER_RELATED_PORTABILITY = "COMPILER_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String HARDWARE_RELATED_PORTABILITY = "HARDWARE_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String LANGUAGE_RELATED_PORTABILITY = "LANGUAGE_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String OS_RELATED_PORTABILITY = "OS_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String SOFTWARE_RELATED_PORTABILITY = "SOFTWARE_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic PORTABILITY
+ */
+ public static final String TIME_ZONE_RELATED_PORTABILITY = "TIME_ZONE_RELATED_PORTABILITY";
+
+ /**
+ * Related to characteristic MAINTAINABILITY
+ */
+ public static final String READABILITY = "READABILITY";
+
+ /**
+ * Related to characteristic MAINTAINABILITY
+ */
+ public static final String UNDERSTANDABILITY = "UNDERSTANDABILITY";
+
+ /**
+ * Related to characteristic SECURITY
+ */
+ public static final String API_ABUSE = "API_ABUSE";
+
+ /**
+ * Related to characteristic SECURITY
+ */
+ public static final String ERRORS = "ERRORS";
+
+ /**
+ * Related to characteristic SECURITY
+ */
+ public static final String INPUT_VALIDATION_AND_REPRESENTATION = "INPUT_VALIDATION_AND_REPRESENTATION";
+
+ /**
+ * Related to characteristic SECURITY
+ */
+ public static final String SECURITY_FEATURES = "SECURITY_FEATURES";
+
+ /**
+ * Related to characteristic EFFICIENCY
+ */
+ public static final String CPU_EFFICIENCY = "CPU_EFFICIENCY";
+
+ /**
+ * Related to characteristic EFFICIENCY
+ */
+ public static final String MEMORY_EFFICIENCY = "MEMORY_EFFICIENCY";
+
+ /**
+ * Related to characteristic EFFICIENCY
+ */
+ public static final String NETWORK_USE = "NETWORK_USE";
+
+ /**
+ * Related to characteristic CHANGEABILITY
+ */
+ public static final String ARCHITECTURE_CHANGEABILITY = "ARCHITECTURE_CHANGEABILITY";
+
+ /**
+ * Related to characteristic CHANGEABILITY
+ */
+ public static final String DATA_CHANGEABILITY = "DATA_CHANGEABILITY";
+
+ /**
+ * Related to characteristic CHANGEABILITY
+ */
+ public static final String LOGIC_CHANGEABILITY = "LOGIC_CHANGEABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String ARCHITECTURE_RELIABILITY = "ARCHITECTURE_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String DATA_RELIABILITY = "DATA_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String EXCEPTION_HANDLING = "EXCEPTION_HANDLING";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String FAULT_TOLERANCE = "FAULT_TOLERANCE";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String INSTRUCTION_RELIABILITY = "INSTRUCTION_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String LOGIC_RELIABILITY = "LOGIC_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String RESOURCE_RELIABILITY = "RESOURCE_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String SYNCHRONIZATION_RELIABILITY = "SYNCHRONIZATION_RELIABILITY";
+
+ /**
+ * Related to characteristic RELIABILITY
+ */
+ public static final String UNIT_TESTS = "UNIT_TESTS";
+
+ /**
+ * Related to characteristic TESTABILITY
+ */
+ public static final String INTEGRATION_TESTABILITY = "INTEGRATION_TESTABILITY";
+
+ /**
+ * Related to characteristic TESTABILITY
+ */
+ public static final String UNIT_TESTABILITY = "UNIT_TESTABILITY";
+ }
+
+ /**
* Instantiated by core but not by plugins
*/
class Context {
@@ -186,28 +350,18 @@ public interface RulesDefinition extends ServerExtension {
interface NewExtendedRepository {
NewRule createRule(String ruleKey);
- /**
- * Reads definition of rule from the annotations provided by the library sonar-check-api.
- */
- NewRule loadAnnotatedClass(Class clazz);
+ @CheckForNull
+ NewRule rule(String ruleKey);
- /**
- * Reads definitions of rules from the annotations provided by the library sonar-check-api.
- */
- NewExtendedRepository loadAnnotatedClasses(Class... classes);
+ Collection<NewRule> rules();
+
+ String key();
void done();
}
interface NewRepository extends NewExtendedRepository {
NewRepository setName(String s);
-
- @CheckForNull
- NewRule rule(String ruleKey);
-
- Collection<NewRule> rules();
-
- String key();
}
class NewRepositoryImpl implements NewRepository {
@@ -263,17 +417,6 @@ public interface RulesDefinition extends ServerExtension {
}
@Override
- public NewRepositoryImpl loadAnnotatedClasses(Class... classes) {
- new RuleDefinitionsFromAnnotations().loadRules(this, classes);
- return this;
- }
-
- @Override
- public RulesDefinition.NewRule loadAnnotatedClass(Class clazz) {
- return new RuleDefinitionsFromAnnotations().loadRule(this, clazz);
- }
-
- @Override
public void done() {
// note that some validations can be done here, for example for
// verifying that at least one rule is declared
@@ -362,6 +505,9 @@ public interface RulesDefinition extends ServerExtension {
}
}
+ /**
+ * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction}.
+ */
interface DebtRemediationFunctions {
DebtRemediationFunction linear(String factor);
@@ -393,7 +539,10 @@ public interface RulesDefinition extends ServerExtension {
return this.key;
}
- public NewRule setName(@Nullable String s) {
+ /**
+ * Required rule name
+ */
+ public NewRule setName(String s) {
this.name = StringUtils.trim(s);
return this;
}
@@ -432,6 +581,11 @@ public interface RulesDefinition extends ServerExtension {
return this;
}
+ /**
+ * Default value is {@link org.sonar.api.rule.RuleStatus#READY}. The value
+ * {@link org.sonar.api.rule.RuleStatus#REMOVED} is not accepted and raises an
+ * {@link java.lang.IllegalArgumentException}.
+ */
public NewRule setStatus(RuleStatus status) {
if (status.equals(RuleStatus.REMOVED)) {
throw new IllegalArgumentException(String.format("Status 'REMOVED' is not accepted on rule '%s'", this));
@@ -440,6 +594,11 @@ public interface RulesDefinition extends ServerExtension {
return this;
}
+ /**
+ * SQALE sub-characteristic. See http://www.sqale.org
+ *
+ * @see org.sonar.api.server.rule.RulesDefinition.SubCharacteristics for constant values
+ */
public NewRule setDebtSubCharacteristic(@Nullable String s) {
this.debtSubCharacteristic = s;
return this;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromAnnotations.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoader.java
index a5ad00af839..2a2585110d7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromAnnotations.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoader.java
@@ -32,30 +32,27 @@ import org.sonar.api.utils.FieldUtils2;
import org.sonar.check.Cardinality;
import javax.annotation.CheckForNull;
-
import java.lang.reflect.Field;
import java.util.List;
/**
- * Read definitions of rules based on the annotations provided by sonar-check-api.
- * </p>
- * It is internally used by {@link RulesDefinition} and can't be directly
- * used by plugins.
+ * Read definitions of rules based on the annotations provided by sonar-check-api. It is used
+ * to feed {@link RulesDefinition}.
*
- * @since 4.2
+ * @since 4.3
*/
-class RuleDefinitionsFromAnnotations {
+public class RulesDefinitionAnnotationLoader {
- private static final Logger LOG = LoggerFactory.getLogger(RuleDefinitionsFromAnnotations.class);
+ private static final Logger LOG = LoggerFactory.getLogger(RulesDefinitionAnnotationLoader.class);
- void loadRules(RulesDefinition.NewRepository repo, Class... annotatedClasses) {
+ public void load(RulesDefinition.NewExtendedRepository repo, Class... annotatedClasses) {
for (Class annotatedClass : annotatedClasses) {
loadRule(repo, annotatedClass);
}
}
@CheckForNull
- RulesDefinition.NewRule loadRule(RulesDefinition.NewRepository repo, Class clazz) {
+ RulesDefinition.NewRule loadRule(RulesDefinition.NewExtendedRepository repo, Class clazz) {
org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getAnnotation(clazz, org.sonar.check.Rule.class);
if (ruleAnnotation != null) {
return loadRule(repo, clazz, ruleAnnotation);
@@ -65,7 +62,7 @@ class RuleDefinitionsFromAnnotations {
}
}
- private RulesDefinition.NewRule loadRule(RulesDefinition.NewRepository repo, Class clazz, org.sonar.check.Rule ruleAnnotation) {
+ private RulesDefinition.NewRule loadRule(RulesDefinition.NewExtendedRepository repo, Class clazz, org.sonar.check.Rule ruleAnnotation) {
String ruleKey = StringUtils.defaultIfEmpty(ruleAnnotation.key(), clazz.getCanonicalName());
String ruleName = StringUtils.defaultIfEmpty(ruleAnnotation.name(), null);
String description = StringUtils.defaultIfEmpty(ruleAnnotation.description(), null);
@@ -114,7 +111,8 @@ class RuleDefinitionsFromAnnotations {
.put(Boolean.class, RuleParamType.BOOLEAN)
.put(boolean.class, RuleParamType.BOOLEAN)
.build(),
- RuleParamType.STRING);
+ RuleParamType.STRING
+ );
@VisibleForTesting
static RuleParamType guessType(Class<?> type) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java
index f8e2c79ba44..48b04d938e9 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/text/JsonWriter.java
@@ -26,6 +26,27 @@ import java.io.Writer;
import java.util.Date;
/**
+ * Writes JSON as a stream. This class allows plugins to not directly depend
+ * on the underlying JSON library.
+ *
+ * <h3>How to use</h3>
+ * <pre>
+ * StringWriter json = new StringWriter();
+ * JsonWriter writer = JsonWriter.of(json);
+ * writer
+ * .beginObject()
+ * .prop("aBoolean", true)
+ * .prop("aInt", 123)
+ * .prop("aString", "foo")
+ * .beginObject().name("aList")
+ * .beginArray()
+ * .beginObject().prop("key", "ABC").endObject()
+ * .beginObject().prop("key", "DEF").endObject()
+ * .endArray()
+ * .endObject()
+ * .close();
+ * </pre>
+ *
* @since 4.2
*/
public class JsonWriter {
@@ -64,6 +85,7 @@ public class JsonWriter {
/**
* Ends encoding the current array. Output is <code>]</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter endArray() {
@@ -78,6 +100,7 @@ public class JsonWriter {
/**
* Begins encoding a new object. Each call to this method must be paired
* with a call to {@link #endObject}. Output is <code>{</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter beginObject() {
@@ -91,6 +114,7 @@ public class JsonWriter {
/**
* Ends encoding the current object. Output is <code>}</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter endObject() {
@@ -104,6 +128,7 @@ public class JsonWriter {
/**
* Encodes the property name. Output is <code>"theName":</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter name(String name) {
@@ -117,6 +142,7 @@ public class JsonWriter {
/**
* Encodes {@code value}. Output is <code>true</code> or <code>false</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter value(boolean value) {
@@ -157,7 +183,7 @@ public class JsonWriter {
*/
public JsonWriter valueDate(@Nullable Date value) {
try {
- stream.value(value==null ? null : DateUtils.formatDate(value));
+ stream.value(value == null ? null : DateUtils.formatDate(value));
return this;
} catch (Exception e) {
throw rethrow(e);
@@ -166,7 +192,7 @@ public class JsonWriter {
public JsonWriter valueDateTime(@Nullable Date value) {
try {
- stream.value(value==null ? null : DateUtils.formatDateTime(value));
+ stream.value(value == null ? null : DateUtils.formatDateTime(value));
return this;
} catch (Exception e) {
throw rethrow(e);
@@ -199,6 +225,7 @@ public class JsonWriter {
/**
* Encodes the property name and value. Output is for example <code>"theName":123</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter prop(String name, @Nullable Number value) {
@@ -208,6 +235,7 @@ public class JsonWriter {
/**
* Encodes the property name and date value (ISO format).
* Output is for example <code>"theDate":"2013-01-24"</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter propDate(String name, @Nullable Date value) {
@@ -217,6 +245,7 @@ public class JsonWriter {
/**
* Encodes the property name and datetime value (ISO format).
* Output is for example <code>"theDate":"2013-01-24T13:12:45+01"</code>.
+ *
* @throws org.sonar.api.utils.text.WriterException on any failure
*/
public JsonWriter propDateTime(String name, @Nullable Date value) {
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromAnnotationsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoaderTest.java
index 65efa9d1258..da45d7d5dea 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromAnnotationsTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionAnnotationLoaderTest.java
@@ -28,11 +28,13 @@ import org.sonar.check.Priority;
import static org.fest.assertions.Assertions.assertThat;
-public class RulesDefinitionFromAnnotationsTest {
+public class RulesDefinitionAnnotationLoaderTest {
@org.junit.Rule
public final ExpectedException thrown = ExpectedException.none();
+ RulesDefinitionAnnotationLoader annotationLoader = new RulesDefinitionAnnotationLoader();
+
@Test
public void rule_with_property() {
RulesDefinition.Repository repository = load(RuleWithProperty.class);
@@ -57,7 +59,7 @@ public class RulesDefinitionFromAnnotationsTest {
public void override_annotation_programmatically() {
RulesDefinition.Context context = new RulesDefinition.Context();
RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java");
- NewRule newRule = newRepository.loadAnnotatedClass(RuleWithProperty.class);
+ NewRule newRule = annotationLoader.loadRule(newRepository, RuleWithProperty.class);
newRule.setName("Overriden name");
newRule.param("property").setDefaultValue("true");
newRule.param("property").setDescription("Overriden");
@@ -102,14 +104,14 @@ public class RulesDefinitionFromAnnotationsTest {
@Test
public void should_recognize_type() {
- assertThat(RuleDefinitionsFromAnnotations.guessType(Integer.class)).isEqualTo(RuleParamType.INTEGER);
- assertThat(RuleDefinitionsFromAnnotations.guessType(int.class)).isEqualTo(RuleParamType.INTEGER);
- assertThat(RuleDefinitionsFromAnnotations.guessType(Float.class)).isEqualTo(RuleParamType.FLOAT);
- assertThat(RuleDefinitionsFromAnnotations.guessType(float.class)).isEqualTo(RuleParamType.FLOAT);
- assertThat(RuleDefinitionsFromAnnotations.guessType(Boolean.class)).isEqualTo(RuleParamType.BOOLEAN);
- assertThat(RuleDefinitionsFromAnnotations.guessType(boolean.class)).isEqualTo(RuleParamType.BOOLEAN);
- assertThat(RuleDefinitionsFromAnnotations.guessType(String.class)).isEqualTo(RuleParamType.STRING);
- assertThat(RuleDefinitionsFromAnnotations.guessType(Object.class)).isEqualTo(RuleParamType.STRING);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(Integer.class)).isEqualTo(RuleParamType.INTEGER);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(int.class)).isEqualTo(RuleParamType.INTEGER);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(Float.class)).isEqualTo(RuleParamType.FLOAT);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(float.class)).isEqualTo(RuleParamType.FLOAT);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(Boolean.class)).isEqualTo(RuleParamType.BOOLEAN);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(boolean.class)).isEqualTo(RuleParamType.BOOLEAN);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(String.class)).isEqualTo(RuleParamType.STRING);
+ assertThat(RulesDefinitionAnnotationLoader.guessType(Object.class)).isEqualTo(RuleParamType.STRING);
}
@Test
@@ -143,8 +145,8 @@ public class RulesDefinitionFromAnnotationsTest {
private RulesDefinition.Repository load(Class annotatedClass) {
RulesDefinition.Context context = new RulesDefinition.Context();
- RulesDefinition.NewExtendedRepository newRepository = context.createRepository("squid", "java")
- .loadAnnotatedClasses(annotatedClass);
+ RulesDefinition.NewExtendedRepository newRepository = context.createRepository("squid", "java");
+ annotationLoader.load(newRepository, annotatedClass);
newRepository.done();
return context.repository("squid");
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java
index 3d1675168d5..ea9de6560d5 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/text/JsonWriterTest.java
@@ -23,8 +23,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.utils.text.WriterException;
import java.io.IOException;
import java.io.StringWriter;