<sonar.apiVersion>5.6.1</sonar.apiVersion>
<javascript.plugin.version>2.15</javascript.plugin.version>
<jdk.min.version>1.8</jdk.min.version>
+ <maven.javadoc.version>2.10.4</maven.javadoc.version>
+ <maven.source.version>3.0.1</maven.source.version>
+ <!-- Be careful these two paths must match the ones configured in SONARQUBE JaCoCo plugin -->
+ <jacoco.it.execution.data.file>${project.basedir}/target/jacoco-it.exec</jacoco.it.execution.data.file>
+ <jacoco.ut.execution.data.file>${project.basedir}/target/jacoco.exec</jacoco.ut.execution.data.file>
+
+ <skip.unit.tests>false</skip.unit.tests>
+ <skip.integration.tests>true</skip.integration.tests>
<sonar.pluginKey>customjavascriptplugin</sonar.pluginKey>
</properties>
</dependencies>
<build>
+
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.5.1</version>
+ <dependencies>
+ <dependency><!-- add support for ssh/scp -->
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-ssh</artifactId>
+ <version>2.10</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+
<plugins>
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.7</version>
+ <configuration>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-descriptor</id>
+ <goals>
+ <goal>attach-descriptor</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <archive>
+ <manifestEntries>
+ <Specification-Title>${project.description}</Specification-Title>
+ <Specification-Version>${project.version}</Specification-Version>
+ <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+ <Implementation-Title>${project.description}</Implementation-Title>
+ <Implementation-Version>${project.version}</Implementation-Version>
+ <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+ </manifestEntries>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>${maven.javadoc.version}</version>
+ <configuration>
+ <quiet>true</quiet>
+ <docencoding>${project.build.sourceEncoding}</docencoding>
+ <charset>${project.build.sourceEncoding}</charset>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>${maven.source.version}</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.7.7.201606060606</version>
+ <executions>
+ <!-- Prepares the property pointing to the JaCoCo runtime agent which
+ is passed as VM argument when Maven the Surefire plugin is executed. -->
+ <execution>
+ <id>pre-unit-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <destFile>${jacoco.ut.execution.data.file}</destFile>
+ <!-- Sets the name of the property containing the settings for JaCoCo
+ runtime agent. -->
+ <propertyName>surefireArgLine</propertyName>
+ </configuration>
+ </execution>
+ <!-- Ensures that the code coverage report for unit tests is created
+ after unit tests have been run. -->
+ <execution>
+ <id>post-unit-test</id>
+ <phase>test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <dataFile>${jacoco.ut.execution.data.file}</dataFile>
+ <!-- Sets the output directory for the code coverage report. -->
+ <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
+ </configuration>
+ </execution>
+ <!-- Prepares the property pointing to the JaCoCo runtime agent which
+ is passed as VM argument when Maven the Failsafe plugin is executed. -->
+ <execution>
+ <id>pre-integration-test</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <destFile>${jacoco.it.execution.data.file}</destFile>
+ <!-- Sets the name of the property containing the settings for JaCoCo
+ runtime agent. -->
+ <propertyName>failsafeArgLine</propertyName>
+ </configuration>
+ </execution>
+ <!-- Ensures that the code coverage report for integration tests after
+ integration tests have been run. -->
+ <execution>
+ <id>post-integration-test</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <!-- Sets the path to the file which contains the execution data. -->
+ <dataFile>${jacoco.it.execution.data.file}</dataFile>
+ <!-- Sets the output directory for the code coverage report. -->
+ <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <versionRange>[0.5,)
+ </versionRange>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <!-- m2e doesn't know what to do with jacoco, let's ignore it or
+ annoying error markers appear see http://wiki.eclipse.org/M2E_plugin_execution_not_covered -->
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ <!-- Used for unit tests -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.surefire</groupId>
+ <artifactId>surefire-junit47</artifactId>
+ <version>2.19.1</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <!-- Sets the VM argument line used when unit tests are run. -->
+ <argLine>-Dfile.encoding=${project.build.sourceEncoding}
+ ${surefireArgLine}</argLine>
+ <!-- Skips unit tests if the value of skip.unit.tests property is true -->
+ <skipTests>${skip.unit.tests}</skipTests>
+ <!-- Excludes integration tests when unit tests are run. -->
+ <excludes>
+ <exclude>**/*IT.java</exclude>
+ <exclude>**/*IntegrationTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
</plugins>
</build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.9</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>${maven.javadoc.version}</version>
+ <reportSets>
+ <reportSet>
+ <id>html</id>
+ <configuration>
+
+ <doctitle>API for ${project.name} ${project.version}</doctitle>
+ <windowtitle>API for ${project.name} ${project.version}</windowtitle>
+ </configuration>
+ <reports>
+ <report>javadoc</report>
+ <report>aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.19.1</version>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>report-only</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ </plugins>
+ </reporting>
</project>
--- /dev/null
+package de.example.plugins.custom.javascript;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.check.Rule;
+import org.sonar.plugins.javascript.JavaScriptLanguage;
+import org.sonar.plugins.javascript.api.JavaScriptCheck;
+import org.sonar.plugins.javascript.api.tree.Tree;
+import org.sonar.plugins.javascript.api.visitors.Issue;
+import org.sonar.plugins.javascript.api.visitors.LineIssue;
+import org.sonar.plugins.javascript.api.visitors.PreciseIssue;
+import org.sonar.plugins.javascript.api.visitors.TreeVisitorContext;
+
+import de.example.custom.javascript.checks.CheckList;
+
+public class CustomRulesDefinitionTest {
+
+ @Test
+ public void whenCreatingCustomJavaRulesDefinitionThenGenerateRulesDefinition() {
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ CustomRulesDefinition rulesDefinition = new CustomRulesDefinition();
+
+ rulesDefinition.define(context);
+
+ RulesDefinition.Repository repository = context.repository(CheckList.REPOSITORY_KEY);
+ assertThat(repository.name(), is(CheckList.REPOSITORY_NAME));
+ assertThat(repository.language(), is(JavaScriptLanguage.KEY));
+ assertThat(repository.rules().size(), is(CheckList.getChecks().size()));
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowIllegalArgumentExceptionWhenNoRuleAnnotationIsFound() {
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository newRepository = context.createRepository(CheckList.REPOSITORY_KEY, CheckList.REPOSITORY_NAME);
+ CustomRulesDefinition rulesDefinition = new CustomRulesDefinition();
+
+ rulesDefinition.newRule(CheckWithNoAnnotation.class, newRepository);
+ }
+
+ @Test(expected=IllegalArgumentException.class)
+ public void shouldThrowIllegalArgumentExceptionWhenNoKeyIsFoundInRuleAnnotation() {
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository newRepository = context.createRepository(CheckList.REPOSITORY_KEY, CheckList.REPOSITORY_NAME);
+ CustomRulesDefinition rulesDefinition = new CustomRulesDefinition();
+
+ rulesDefinition.newRule(EmptyRuleKey.class, newRepository);
+ }
+
+ @Test(expected=IllegalStateException.class)
+ public void shouldThrowIllegalStateExceptionWhenNoKeyIsFoundInRuleAnnotation() {
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ RulesDefinition.NewRepository newRepository = context.createRepository(CheckList.REPOSITORY_KEY, CheckList.REPOSITORY_NAME);
+ newRepository.createRule("myCardinality");
+ newRepository.createRule("correctRule");
+ CustomRulesDefinition rulesDefinition = new CustomRulesDefinition();
+
+ rulesDefinition.newRule(UnregisteredRule.class, newRepository);
+ }
+
+ private class CheckWithNoAnnotation implements JavaScriptCheck {
+
+ @Override
+ public <T extends Issue> T addIssue(T arg0) {
+ return null;
+ }
+
+ @Override
+ public PreciseIssue addIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public LineIssue addLineIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public List<Issue> scanFile(TreeVisitorContext arg0) {
+ return null;
+ }
+ }
+
+ @Rule(key = "")
+ private class EmptyRuleKey implements JavaScriptCheck {
+
+ @Override
+ public <T extends Issue> T addIssue(T arg0) {
+ return null;
+ }
+
+ @Override
+ public PreciseIssue addIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public LineIssue addLineIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public List<Issue> scanFile(TreeVisitorContext arg0) {
+ return null;
+ }
+ }
+
+ @Rule(key = "myKey")
+ private class UnregisteredRule implements JavaScriptCheck {
+
+ @Override
+ public <T extends Issue> T addIssue(T arg0) {
+ return null;
+ }
+
+ @Override
+ public PreciseIssue addIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public LineIssue addLineIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public List<Issue> scanFile(TreeVisitorContext arg0) {
+ return null;
+ }
+ }
+
+ @Rule(key = "correctRule")
+ private class CorrectRule implements JavaScriptCheck {
+
+ @Override
+ public <T extends Issue> T addIssue(T arg0) {
+ return null;
+ }
+
+ @Override
+ public PreciseIssue addIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public LineIssue addLineIssue(Tree arg0, String arg1) {
+ return null;
+ }
+
+ @Override
+ public List<Issue> scanFile(TreeVisitorContext arg0) {
+ return null;
+ }
+ }
+}