如何防止在 scala 代码中使用特定的隐式代码?
例如,我最近被 https://github.com/scala/scala/blob/68bad81726d15d03a843dc476d52cbbaf52fb168/src/library/scala/io/Codec.scala#L76 提供的默认Codec
咬了。 有没有办法确保任何需要implicit codec: Codec
的代码永远不会使用fallbackSystemCodec
提供的代码? 或者,是否可以阻止所有隐式编解码器?
这是使用scalafix应该可以做到的吗?
Scalafix 可以使用SemanticTree
检查隐式参数。下面是通过定义自定义 scalafix 规则的示例解决方案。
鉴于
import scala.io.Codec
object Hello {
def foo(implicit codec: Codec) = 3
foo
}
我们可以定义一个自定义规则
class ExcludedImplicitsRule(config: ExcludedImplicitsRuleConfig)
extends SemanticRule("ExcludedImplicitsRule") {
...
override def fix(implicit doc: SemanticDocument): Patch = {
doc.tree.collect {
case term: Term if term.synthetic.isDefined => // TODO: Use ApplyTree(func, args)
val struct = term.synthetic.structure
val isImplicit = struct.contains("implicit")
val excludedImplicit = config.blacklist.find(struct.contains)
if (isImplicit && excludedImplicit.isDefined)
Patch.lint(ExcludedImplicitsDiagnostic(term, excludedImplicit.getOrElse(config.blacklist.mkString(","))))
else
Patch.empty
}.asPatch
}
}
和相应的.scalafix.conf
rule = ExcludedImplicitsRule
ExcludedImplicitsRuleConfig.blacklist = [
fallbackSystemCodec
]
应使sbt scalafix
提高诊断
[error] /Users/mario/IdeaProjects/scalafix-exclude-implicits/example-project/scalafix-exclude-implicits-example/src/main/scala/example/Hello.scala:7:3: error: [ExcludedImplicitsRule] Attempting to pass excluded implicit fallbackSystemCodec to foo'
[error] foo
[error] ^^^
[error] (Compile / scalafix) scalafix.sbt.ScalafixFailed: LinterError
请注意println(term.synthetic.structure)
的输出
Some(ApplyTree(
OriginalTree(Term.Name("foo")),
List(
IdTree(SymbolInformation(scala/io/LowPriorityCodecImplicits#fallbackSystemCodec. => implicit lazy val method fallbackSystemCodec: Codec))
)
))
显然,上述解决方案效率不高,因为它搜索字符串,但它应该给出一些方向。也许匹配ApplyTree(func, args)
会更好。
scalafix-exclude-implicits-example 演示如何配置项目以使用ExcludedImplicitsRule
。
您可以通过完全使用新类型来执行此操作; 这样,没有人能够在您的依赖项中覆盖它。这本质上是我发布的答案,用于创建一个模棱两可的低优先级隐式
但是,例如,如果您无法更改类型,则可能不实用。