diff --git a/scalafix-rules/src/main/scala/scalafix/internal/rule/DisableSyntax.scala b/scalafix-rules/src/main/scala/scalafix/internal/rule/DisableSyntax.scala index 0a80ce071..54a948597 100644 --- a/scalafix-rules/src/main/scala/scalafix/internal/rule/DisableSyntax.scala +++ b/scalafix-rules/src/main/scala/scalafix/internal/rule/DisableSyntax.scala @@ -113,11 +113,27 @@ final class DisableSyntax(config: DisableSyntaxConfig) Diagnostic("noXml", "xml literals should be avoided", token.pos) case token: Token.Ident if token.value == "asInstanceOf" && config.noAsInstanceOf => - Diagnostic( - "asInstanceOf", - "asInstanceOf casts are disabled, use pattern matching instead", - token.pos - ) + val isMatchableCast = + doc.tokenList + .trailing(token) + .takeWhile(!_.is[Token.RightBracket]) + .collectFirst { case Token.Ident("Matchable") => } + .isDefined + + if (isMatchableCast) { + Diagnostic( + "asInstanceOfMatchable", + "asInstanceOf[Matchable] is used here to enable pattern matching on Any. " + + "Consider using the .asMatchable extension method instead for better readability.", + token.pos + ) + } else { + Diagnostic( + "asInstanceOf", + "asInstanceOf casts are disabled, use pattern matching instead", + token.pos + ) + } case token: Token.Ident if token.value == "isInstanceOf" && config.noIsInstanceOf => Diagnostic( diff --git a/scalafix-tests/input/src/main/scala-3/test/disableSyntax/MatchableDisableSyntax.scala b/scalafix-tests/input/src/main/scala-3/test/disableSyntax/MatchableDisableSyntax.scala new file mode 100644 index 000000000..16458a53a --- /dev/null +++ b/scalafix-tests/input/src/main/scala-3/test/disableSyntax/MatchableDisableSyntax.scala @@ -0,0 +1,35 @@ +/* +rules = DisableSyntax +DisableSyntax.noAsInstanceOf = true +*/ +package test.disableSyntax + +object MatchableDisableSyntax { + class Example { + override def equals(obj: Any): Boolean = + obj.asInstanceOf[Matchable] match { /* assert: DisableSyntax.asInstanceOfMatchable + ^^^^^^^^^^^^ + asInstanceOf[Matchable] is used here to enable pattern matching on Any. Consider using the .asMatchable extension method instead for better readability. + */ + case that: Example => true + case _ => false + } + } + + def regularCast(x: Any): String = + x.asInstanceOf[String] /* assert: DisableSyntax.asInstanceOf + ^^^^^^^^^^^^ + asInstanceOf casts are disabled, use pattern matching instead + */ + + // whitespace between tokens + class WhitespaceExample { + override def equals(obj: Any): Boolean = + obj.asInstanceOf [ Matchable ] match { /* assert: DisableSyntax.asInstanceOfMatchable + ^^^^^^^^^^^^ + asInstanceOf[Matchable] is used here to enable pattern matching on Any. Consider using the .asMatchable extension method instead for better readability. + */ + case _ => true + } + } +}