有没有办法防止使用依赖项提供的特定功能?

Posted

技术标签:

【中文标题】有没有办法防止使用依赖项提供的特定功能?【英文标题】:Is there a way to prevent usage of a specific function provided by a dependency? 【发布时间】:2020-09-14 17:58:51 【问题描述】:

我的应用程序对库 A 有编译依赖项。我知道这个库中有一个特定的函数会导致性能问题。但它并没有被弃用,如果你没有这些先验信息,你会认为使用它是安全的。我正在寻找一种方法来以某种方式弃用此函数或阻止它被直接调用。

是否有可能通过静态分析工具或内置编译器标志来实现?

【问题讨论】:

fork依赖并取出函数? @joelb 这不是一个选项。 【参考方案1】:

您可以为 Scalafix 编写规则

https://scalacenter.github.io/scalafix/docs/developers/setup.html

例如让我们弃用scala.Predef.println

class DeprecateFunction extends SemanticRule("DeprecateFunction") 

  case class Deprecation(position: Position) extends Diagnostic 
    override def message = "Use loggers instead of println"
    override def severity = LintSeverity.Warning
  

  val deprecatedFunction = SymbolMatcher.normalized("scala.Predef.println")

  override def fix(implicit doc: SemanticDocument): Patch = 
    doc.tree.collect 
      case deprecatedFunction(t: Name) =>
        Patch.lint(Deprecation(t.pos))
    .asPatch
  

例子:

object Scalafixdemo 
  println(1)

输出:

[IJ]sbt:scalafix> scalafix --rules=file:rules/src/main/scala/fix/DeprecateFunction.scala
[info] Running scalafix on 1 Scala sources
[warn] .../scalafix/input/src/main/scala/fix/Scalafixdemo.scala:8:3: warning: [DeprecateFunction] Use loggers instead of println
[warn]   println(1)
[warn]   ^^^^^^^
[success] Total time: 2 s, completed 27.05.2020 21:12:13

【讨论】:

【参考方案2】:

我已经检查了 scalafix,但设置这种 linting 太复杂了。我最终使用了 wartremover 并添加了一个自定义疣。

自定义疣位于子项目中,如 example 所示。

lazy val myWarts = project.in(file("my-warts")).settings(
  commonSettings,
  libraryDependencies ++= Seq(
  "org.wartremover" % "wartremover" % wartremover.Wart.PluginVersion cross CrossVersion.full
  )
)

lazy val main = project.in(file("main")).settings(
  commonSettings,
  wartremoverWarnings += Wart.custom("mywarts.ExtractOrElse"),
  wartremoverClasspaths ++= 
    (fullClasspath in (myWarts, Compile)).value.map(_.data.toURI.toString)
  
)

我通过简单地修改内置 EitherProjectionPartial wart 创建了一个自定义 wart。

object ExtractOrElse extends WartTraverser 
  def apply(u: WartUniverse): u.Traverser = 
    import u.universe._

    val extractableJsonAstNode = rootMirror.staticClass("org.json4s.ExtractableJsonAstNode")
    new u.Traverser 
      override def traverse(tree: Tree): Unit = 
        tree match 
          // Ignore trees marked by SuppressWarnings
          case t if hasWartAnnotation(u)(t) =>
          case Select(left, TermName("extractOrElse")) if left.tpe.baseType(extractableJsonAstNode) != NoType =>
            error(u)(tree.pos, "extractOrElse is deprecated - use toOption.map or extract[Option[A]] instead")
            super.traverse(tree)
          case _ => super.traverse(tree)
        
      
    
  

【讨论】:

以上是关于有没有办法防止使用依赖项提供的特定功能?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法防止 MASM 更改指令?

防止 Chrome 缓存特定字段

是否可以防止 C 共享库中的函数覆盖?

有啥办法可以防止 React Native IOS 0.63 版中的截图?

ASP程序防止SQL注入的最好办法?

过滤以防止三星 Galaxy 相机从 Play 商店访问应用程序