diff --git a/project/Dependencies.scala b/project/Dependencies.scala index bcf41cf31..e3bc95277 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -4,7 +4,7 @@ import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._ object Dependencies { val scalametaV = "2.1.2" - val metaconfigV = "0.5.3" + val metaconfigV = "0.5.4" def semanticdbSbt = "0.4.0" def dotty = "0.1.1-bin-20170530-f8f52cc-NIGHTLY" def scala210 = "2.10.6" diff --git a/scalafix-core/shared/src/main/scala/scalafix/config/CustomMessage.scala b/scalafix-core/shared/src/main/scala/scalafix/config/CustomMessage.scala new file mode 100644 index 000000000..e5429157c --- /dev/null +++ b/scalafix-core/shared/src/main/scala/scalafix/config/CustomMessage.scala @@ -0,0 +1,38 @@ +package scalafix +package config + +import metaconfig.{Conf, ConfError, ConfDecoder, Configured, Metaconfig} +import org.langmeta._ +import scalafix.internal.config.MetaconfigPendingUpstream.XtensionConfScalafix + +import scala.language.implicitConversions + +class CustomMessage[T]( + val value: T, + val message: Option[String], + val id: Option[String]) + +object CustomMessage { + def decoder[T](field: String)( + implicit ev: ConfDecoder[T]): ConfDecoder[CustomMessage[T]] = + ConfDecoder.instance[CustomMessage[T]] { + case obj: Conf.Obj => { + (obj.get[T](field) |@| + obj.getOption[String]("message") |@| + obj.getOption[String]("id")).map { + case ((value, message0), id) => + val message = + message0.map(msg => + if (msg.isMultiline) { + "\n" + msg.stripMargin + } else { + msg + }) + + new CustomMessage(value, message, id) + } + } + case els => + ev.read(els).map(value => new CustomMessage(value, None, None)) + } +} diff --git a/scalafix-core/shared/src/main/scala/scalafix/internal/config/CustomMessage.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/config/CustomMessage.scala deleted file mode 100644 index d7b539022..000000000 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/config/CustomMessage.scala +++ /dev/null @@ -1,31 +0,0 @@ -package scalafix -package internal.config - -import metaconfig.{Conf, ConfError, ConfDecoder, Configured} -import org.langmeta._ -import MetaconfigPendingUpstream.XtensionConfScalafix - -import scala.language.implicitConversions - -case class CustomMessage[T](value: T, message: Option[String]) - -object CustomMessage { - def decoder[T](field: String)( - implicit ev: ConfDecoder[T]): ConfDecoder[CustomMessage[T]] = - ConfDecoder.instance[CustomMessage[T]] { - case obj: Conf.Obj => - (obj.get[T](field) |@| obj.get[String]("message")).map { - case (value, message0) => { - val message = - if (message0.isMultiline) { - "\n" + message0.stripMargin - } else { - message0 - } - CustomMessage(value, Some(message)) - } - } - case els => - ev.read(els).map(value => CustomMessage(value, None)) - } -} diff --git a/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableConfig.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableConfig.scala index e967143f5..9491b1b74 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableConfig.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableConfig.scala @@ -1,4 +1,5 @@ -package scalafix.internal.config +package scalafix +package internal.config import metaconfig.ConfDecoder import MetaconfigPendingUpstream.XtensionConfScalafix @@ -8,14 +9,13 @@ import scalafix.internal.util.SymbolOps case class DisableConfig(symbols: List[CustomMessage[Symbol.Global]] = Nil) { def allSymbols = symbols.map(_.value) - private val messageBySymbol: Map[String, String] = + private val messageBySymbol: Map[String, CustomMessage[Symbol.Global]] = symbols - .flatMap(custom => - custom.message.map(message => - (SymbolOps.normalize(custom.value).syntax, message))) + .map(custom => (SymbolOps.normalize(custom.value).syntax, custom)) .toMap - def customMessage(symbol: Symbol.Global): Option[String] = + def customMessage( + symbol: Symbol.Global): Option[CustomMessage[Symbol.Global]] = messageBySymbol.get(SymbolOps.normalize(symbol).syntax) implicit val customMessageReader: ConfDecoder[CustomMessage[Symbol.Global]] = diff --git a/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableSyntaxConfig.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableSyntaxConfig.scala index c5feb2e28..c33619956 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableSyntaxConfig.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/internal/config/DisableSyntaxConfig.scala @@ -1,4 +1,5 @@ -package scalafix.internal.config +package scalafix +package internal.config import metaconfig.{Conf, ConfError, ConfDecoder, Configured} import org.langmeta._ diff --git a/scalafix-core/shared/src/main/scala/scalafix/internal/rule/Disable.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/rule/Disable.scala index 2d4ff8c30..2f0b01524 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/rule/Disable.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/internal/rule/Disable.scala @@ -51,11 +51,18 @@ final case class Disable(index: SemanticdbIndex, config: DisableConfig) case _ => "" -> pos } - val message = config - .customMessage(symbol) + val custom = config.customMessage(symbol) + + val message = custom + .flatMap(_.message) .getOrElse(s"${signature.name} is disabled$details") + + val id = custom + .flatMap(_.id) + .getOrElse(signature.name) + errorCategory - .copy(id = signature.name) + .copy(id = id) .at(message, caret) } } diff --git a/scalafix-core/shared/src/main/scala/scalafix/internal/rule/DisableSyntax.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/rule/DisableSyntax.scala index 3893dea69..1714787c9 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/rule/DisableSyntax.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/internal/rule/DisableSyntax.scala @@ -35,7 +35,7 @@ final case class DisableSyntax( while (matcher.find()) { regexLintMessages += errorCategory - .copy(id = pattern) + .copy(id = regex.id.getOrElse(pattern)) .at(message, pos(matcher.start)) } } diff --git a/scalafix-core/shared/src/main/scala/scalafix/package.scala b/scalafix-core/shared/src/main/scala/scalafix/package.scala index 10993434e..36244f766 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/package.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/package.scala @@ -34,6 +34,9 @@ package object scalafix { @deprecated("Renamed to Rule", "0.5.0") val Rewrite = rule.Rule + type CustomMessage[T] = scalafix.config.CustomMessage[T] + val CustomMessage = scalafix.config.CustomMessage + type SemanticRule = rule.SemanticRule type Rule = rule.Rule val Rule = rule.Rule diff --git a/scalafix-tests/input/src/main/scala/test/Disable.scala b/scalafix-tests/input/src/main/scala/test/Disable.scala index 3adbe6c02..ea6d560cd 100644 --- a/scalafix-tests/input/src/main/scala/test/Disable.scala +++ b/scalafix-tests/input/src/main/scala/test/Disable.scala @@ -5,6 +5,7 @@ Disable.symbols = [ "test.Disable.D.disabledFunction" { symbol = "scala.Option.get" + id = "Option.get" message = """|Option.get is the root of all evils | @@ -47,7 +48,7 @@ case object Disable { def asInstanceOf: O = "test" } val yy = AA.asInstanceOf // OK, no errors - Option(1).get /* assert: Disable.get + Option(1).get /* assert: Disable.Option.get ^ Option.get is the root of all evils diff --git a/scalafix-tests/input/src/main/scala/test/DisableSyntax.scala b/scalafix-tests/input/src/main/scala/test/DisableSyntax.scala index ac7976098..729c23775 100644 --- a/scalafix-tests/input/src/main/scala/test/DisableSyntax.scala +++ b/scalafix-tests/input/src/main/scala/test/DisableSyntax.scala @@ -11,6 +11,7 @@ DisableSyntax.noSemicolons = true DisableSyntax.noXml = true DisableSyntax.regex = [ { + id = offensive pattern = "[P|p]imp" message = "Please consider a less offensive word such as Extension" } @@ -39,7 +40,7 @@ case object DisableSyntax { xml // assert: DisableSyntax.noXml // assert: DisableSyntax.noTabs - implicit class StringPimp(value: String) { // assert: DisableSyntax.[P|p]imp + implicit class StringPimp(value: String) { // assert: DisableSyntax.offensive def -(other: String): String = s"$value - $other" }