From 4d6c8a7d8ff91153a662c79ee500959fe8b146c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Mass=C3=A9?= Date: Tue, 12 Dec 2017 18:28:31 +0100 Subject: [PATCH] Add id for CustomMessage (fix #495) --- .../scala/scalafix/config/CustomMessage.scala | 44 +++++++++++++++++++ .../internal/config/CustomMessage.scala | 42 ++++++++++++------ .../internal/config/DisableConfig.scala | 9 ++-- .../scalafix/internal/rule/Disable.scala | 13 ++++-- .../internal/rule/DisableSyntax.scala | 2 +- .../input/src/main/scala/test/Disable.scala | 3 +- .../src/main/scala/test/DisableSyntax.scala | 3 +- 7 files changed, 92 insertions(+), 24 deletions(-) create mode 100644 scalafix-core/shared/src/main/scala/scalafix/config/CustomMessage.scala 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 0000000000..d00c0d1a90 --- /dev/null +++ b/scalafix-core/shared/src/main/scala/scalafix/config/CustomMessage.scala @@ -0,0 +1,44 @@ +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](value: T, message: Option[String], id: Option[String]) + +object CustomMessage { + def getOption[T](obj: Conf.Obj, path: String)( + implicit ev: ConfDecoder[T]): Configured[Option[T]] = + Metaconfig + .getKey(obj, Seq(path)) + .map( + value => ev.read(value).map(Some(_)) + ) + .getOrElse(Configured.Ok(None)) + + def decoder[T](field: String)( + implicit ev: ConfDecoder[T]): ConfDecoder[CustomMessage[T]] = + ConfDecoder.instance[CustomMessage[T]] { + case obj: Conf.Obj => { + (obj.get[T](field) |@| + getOption[String](obj, "message") |@| + getOption[String](obj, "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 index d7b539022b..3892f0c0ea 100644 --- a/scalafix-core/shared/src/main/scala/scalafix/internal/config/CustomMessage.scala +++ b/scalafix-core/shared/src/main/scala/scalafix/internal/config/CustomMessage.scala @@ -1,31 +1,47 @@ package scalafix package internal.config -import metaconfig.{Conf, ConfError, ConfDecoder, Configured} +import metaconfig.{Conf, ConfError, ConfDecoder, Configured, Metaconfig} import org.langmeta._ import MetaconfigPendingUpstream.XtensionConfScalafix import scala.language.implicitConversions -case class CustomMessage[T](value: T, message: Option[String]) +case class CustomMessage[T]( + value: T, + message: Option[String], + id: Option[String]) object CustomMessage { + def getOption[T](obj: Conf.Obj, path: String)( + implicit ev: ConfDecoder[T]): Configured[Option[T]] = + Metaconfig + .getKey(obj, Seq(path)) + .map( + value => ev.read(value).map(Some(_)) + ) + .getOrElse(Configured.Ok(None)) + 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) => { + case obj: Conf.Obj => { + (obj.get[T](field) |@| + getOption[String](obj, "message") |@| + getOption[String](obj, "id")).map { + case ((value, message0), id) => val message = - if (message0.isMultiline) { - "\n" + message0.stripMargin - } else { - message0 - } - CustomMessage(value, Some(message)) - } + message0.map(msg => + if (msg.isMultiline) { + "\n" + msg.stripMargin + } else { + msg + }) + + CustomMessage(value, message, id) } + } case els => - ev.read(els).map(value => CustomMessage(value, None)) + ev.read(els).map(value => CustomMessage(value, None, 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 e967143f52..89bebcd7f5 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 @@ -8,14 +8,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/rule/Disable.scala b/scalafix-core/shared/src/main/scala/scalafix/internal/rule/Disable.scala index 2d4ff8c304..2f0b015243 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 3893dea698..1714787c99 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-tests/input/src/main/scala/test/Disable.scala b/scalafix-tests/input/src/main/scala/test/Disable.scala index 3adbe6c020..ea6d560cd5 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 ac7976098e..729c237758 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" }