Skip to content

Commit

Permalink
changed rule keys but got into trouble with uniqueness
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelZinsmaier committed Oct 11, 2015
1 parent a9f6565 commit f75370b
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import org.sonar.api.rules.{RuleFinder, ActiveRule}
import org.sonar.api.utils.ValidationMessages
import org.scalastyle.ScalastyleError
import scala.xml.XML
import org.sonar.api.rules.RuleQuery


/**
Expand All @@ -37,10 +38,11 @@ class ScalastyleQualityProfile(ruleFinder: RuleFinder) extends ProfileDefinition
override def createProfile(validation: ValidationMessages): RulesProfile = {
val profile = RulesProfile.create(Constants.ProfileName, Constants.ScalaKey)
val enabledRules = defaultConfigRules filter (x => (x \ "@enabled").text.equals("true"))
val defaultKeys = enabledRules map (x => (x \ "@class").text)
val defaultRuleClasses = enabledRules map (x => (x \ "@class").text)

for {ruleKey <- defaultKeys} {
val ruleOption = Option(ruleFinder.findByKey(Constants.RepositoryKey, ruleKey))
for {clazz <- defaultRuleClasses} {
val ruleKey = ScalastyleRepository.getStandardKey(clazz)
val ruleOption = Option(ruleFinder.findByKey(Constants.RepositoryKey, ruleKey))

ruleOption match {
case None => validation.addWarningText(s"Rule $ruleKey not found in ${Constants.RepositoryKey} repository! Rule won't be activated.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,18 @@ package com.ncredinburgh.sonar.scalastyle
import org.sonar.api.rule.Severity
import org.sonar.api.server.rule.RulesDefinition
import org.sonar.api.server.rule.RuleParamType
import org.slf4j.LoggerFactory
import org.sonar.api.server.rule.RulesDefinition.NewRepository
import com.ncredinburgh.sonar.scalastyle.ScalastyleRepository.getStandardKey
import scala.annotation.tailrec

object ScalastyleRepository {

def getStandardKey(clazz: String) = {
val simpleClazz = clazz.reverse.takeWhile(_ != '.').reverse
s"scalastyle_${simpleClazz}"
}
}

/**
* Scalastyle rules repository - creates a rule for each checker shipped with Scalastyle based
Expand All @@ -33,42 +44,63 @@ class ScalastyleRepository extends RulesDefinition {
val repository = context
.createRepository(Constants.RepositoryKey, Constants.ScalaKey)
.setName(Constants.RepositoryName)

ScalastyleResources.allDefinedRules foreach {
resRule => {

// set
val rule = repository.createRule(resRule.clazz)
rule.setName(ScalastyleResources.label(resRule.id))
rule.setHtmlDescription(resRule.description)

// currently all rules comes with "warning" default level so we can treat with major severity
rule.setSeverity(Severity.MAJOR)

// add normal parameters
resRule.params foreach {
param => {
rule
.createParam(param.name)
.setDefaultValue(param.defaultVal)
.setType(param.`type`)
.setDescription(param.desc)
repoRule =>
{
val ruleKey = determineFreeRuleKey(repoRule.clazz, repository)

// define the rule
val rule = repository.createRule(ruleKey)
rule.setName(ScalastyleResources.label(repoRule.id))
rule.setHtmlDescription(repoRule.description)

// currently all rules comes with "warning" default level so we can treat with major severity
rule.setSeverity(Severity.MAJOR)

// add parameters
repoRule.params foreach {
param =>
{
rule
.createParam(param.name)
.setDefaultValue(param.defaultVal)
.setType(param.`type`)
.setDescription(param.desc)
}
}
}

// add synthetic parameter as reference to the class
rule.createParam("scalastyle-checker")
.setDefaultValue(resRule.clazz)

// add synthetic parameter as reference to the class
rule.createParam(Constants.ClazzParam)
.setDefaultValue(repoRule.clazz)
.setType(RuleParamType.STRING)
.setDescription("Scalastyle checker that validates the rule.")

// if a rule has at least one real parameter make it a template
rule.setTemplate(resRule.params.size > 0)
}

// if a rule has at least one real parameter make it a template
rule.setTemplate(repoRule.params.size > 0)

}
}

repository.done()
}

/**
* determines a free rule key in the repo, in case the key scalastyle-<simple class name> is already
* in use the name scalastyle-<simple class name>-<i> is tried i = 1, 2, ....
*/
private def determineFreeRuleKey(clazz: String, repo: NewRepository): String = {
@tailrec
def getFreeRuleKey(key: String, count: Int, repo: NewRepository): String = {
val testee = if (count == 0) key else "$key_$count"
if (repo.rule(testee) == null) {
testee
} else {
getFreeRuleKey(key, (count + 1), repo)
}
}

getFreeRuleKey(getStandardKey(clazz), 0, repo)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ScalastyleRepositorySpec extends FlatSpec with Matchers with Inspectors wi
val ctx = new RulesDefinition.Context()

def rules = ctx.repository(Constants.RepositoryKey).rules()

override def beforeAll() {
testee.define(ctx)
}
Expand Down Expand Up @@ -67,12 +67,12 @@ class ScalastyleRepositorySpec extends FlatSpec with Matchers with Inspectors wi
}

it should "name the rule properly" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.MagicNumberChecker")
val rule = rules.find(_.key == "scalastyle_MagicNumberChecker")
rule.get.name shouldEqual "Magic Number"
}

it should "describe the rule properly" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.MagicNumberChecker")
val rule = rules.find(_.key == "scalastyle_MagicNumberChecker")
rule.get.htmlDescription shouldEqual
"<p>Replacing a magic number with a named constant can make code easier to read and understand," +
" and can avoid some subtle bugs.</p>\n" +
Expand All @@ -82,42 +82,42 @@ class ScalastyleRepositorySpec extends FlatSpec with Matchers with Inspectors wi
}

it should "determine the parameter of a rule with a parameter" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.ParameterNumberChecker")
rule.get.params map (_.key) shouldEqual List("maxParameters", "scalastyle-checker")
val rule = rules.find(_.key == "scalastyle_ParameterNumberChecker")
rule.get.params map (_.key) shouldEqual List("maxParameters", Constants.ClazzParam)
}

it should "determine parameters of a rule with multiple parameters" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.MethodNamesChecker")
rule.get.params map (_.key) should contain theSameElementsAs List("regex", "ignoreRegex", "ignoreOverride", "scalastyle-checker")
val rule = rules.find(_.key == "scalastyle_MethodNamesChecker")
rule.get.params map (_.key) should contain theSameElementsAs List("regex", "ignoreRegex", "ignoreOverride", Constants.ClazzParam)
}

it should "determine correct type of integer parameters" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.ParameterNumberChecker")
val rule = rules.find(_.key == "scalastyle_ParameterNumberChecker")
rule.get.param("maxParameters").`type` shouldEqual RuleParamType.INTEGER
}

it should "determine correct type of boolean parameters" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.MethodNamesChecker")
val rule = rules.find(_.key == "scalastyle_MethodNamesChecker")
rule.get.param("ignoreOverride").`type` shouldEqual RuleParamType.BOOLEAN
}

it should "determine correct type of regex parameters" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.ClassTypeParameterChecker")
val rule = rules.find(_.key == "scalastyle_ClassTypeParameterChecker")
rule.get.param("regex").`type` shouldEqual RuleParamType.STRING
}

it should "describe the parameter properly" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.ClassTypeParameterChecker")
val rule = rules.find(_.key == "scalastyle_ClassTypeParameterChecker")
rule.get.param("regex").description shouldEqual "Standard Scala regular expression syntax"
}

it should "provide default parameters to scalastyle preferred defaults for rules with a parameter" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.ParameterNumberChecker")
val rule = rules.find(_.key == "scalastyle_ParameterNumberChecker")
rule.get.param("maxParameters").defaultValue.toInt shouldEqual 8
}

it should "provide default parameters to scalastyle preferred defaults for rules with multiple parameters" in {
val rule = rules.find(_.key == "org.scalastyle.scalariform.MethodNamesChecker")
val rule = rules.find(_.key == "scalastyle_MethodNamesChecker")
rule.get.param("regex").defaultValue shouldEqual "^[a-z][A-Za-z0-9]*(_=)?$"
rule.get.param("ignoreRegex").defaultValue shouldEqual "^$"
rule.get.param("ignoreOverride").defaultValue.toBoolean shouldEqual false
Expand Down

0 comments on commit f75370b

Please sign in to comment.