【问题标题】:How to detect dependencies on Java classes in Scala sources?如何检测 Scala 源代码中对 Java 类的依赖关系?
【发布时间】:2012-02-02 16:18:15
【问题描述】:

我想建立一些关于在某些 Scala 源代码中使用了哪些 Java 标准库类(java.*/javax.*)和方法的统计数据(以及使用频率)。

最直接的方法是什么?是否有机会也涵盖传递依赖关系,例如。 G。当某些 Lift 类依赖于 Scala 标准库方法,而后者又依赖于 Java 标准库方法?

【问题讨论】:

    标签: java scala statistics dependencies


    【解决方案1】:

    我写了一个 Scala 编译器插件,它为我解决了这个问题。它并不漂亮,但它确实发挥了作用。

    完成这项工作的主要部分如下所示:

    for (tree <- unit.body) {
      tree match {
        case tree@DefDef(mods, name, tparams, vparamss, tpt, rhs)
          if isJavaAndNotAccessor(mods, rhs.symbol) =>
          printJava(rhs, "DefDef")
    
        case tree@ValDef(mods, name, tpt, rhs) =>
          if (isJavaAndNotAccessor(mods, tpt.symbol))
            printJava(tpt, "ValDef")
          tpt.tpe.typeArgs.foreach(t => findAllJavaTypes(t.baseTypeSeq.toList).foreach(sym => printJavaCustom(sym, posWithFallback(sym.pos, tree.pos), "TpeArg")))
    
        case tree@Template(parents, self, body) =>
          parents.foreach(p => findAllJavaTypes(p.tpe.baseTypeSeq.toList).foreach(sym => printJavaCustom(sym, posWithFallback(p.pos, tree.pos), "TpeDef")))
    
        case tree@Select(qual, name) =>
          if (isJavaAndNotJLObjectInit(tree.symbol) && (tree.symbol.isMethod || tree.symbol.isValue || tree.symbol.isStaticMember))
            printJava(tree, "Select")
    
        case _ =>
      }
    }
    
    private def findAllJavaTypes(types: List[Type]): List[Symbol] = {
      def find0(types: List[Type], result: List[Type]): List[Type] =
        if (types == List())
          result
        else
          find0(types.flatMap(_.typeArgs), types.filter(tpe => isJavaAndNotJLObject(tpe.typeSymbol)) ::: result)
    
      find0(types, List()).distinct.map(_.typeSymbol)
    }
    

    代码托管在这里:https://github.com/soc/scala-compilerplugin-javausagecounter

    【讨论】:

      【解决方案2】:

      IntelliJ IDEA 有一个名为“分析依赖项”的功能,可以满足您的需求。

      您可以将依赖关系分析导出到一个文本文件中,它将包含以下条目:

      <file path="$PROJECT_DIR$/src/main/scala/com/foo/config/Bootstrap.scala">
        <dependency path="$PROJECT_DIR$/src/main/scala/com/foo/ws/auth/Auth.scala" />
        <dependency path="$PROJECT_DIR$/src/main/scala/com/foo/domain/auth/User.scala" />
        <dependency path="$MAVEN_REPOSITORY$/org/scala-lang/scala-library/2.9.1/scala-library-2.9.1.jar!/scala/package.class" />
        <dependency path="/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/../Classes/classes.jar!/java/io/InputStream.class" />
        ....
      

      注意列出的最后一行是如何依赖于 Java InputStream 类的。

      它也有传递依赖。

      【讨论】:

        【解决方案3】:

        您可以使用Structure101 执行此操作。从 Scala/Java 字节码加载 S101 项目,转到 Collaboration 透视图(Structure 选项卡)并在左侧树形视图中选择 Scala 代码的根包,并在 rhs 中选择 Java 包。这将显示您的 Scala 项目使用了哪些 Java 项(到 package.class.method/field 的详细级别),以及哪些 Scala 项使用了 Java 库中的任何内容,您可以深入查看特定的依赖关系。

        您还可以使用标记来获得传递依赖。选择项目,右键单击,标记/使用/间接。这将用一个蓝点标记项目,该蓝点在每个透视图中滚动。您可以隐藏除了传递闭包之外的所有内容(反转标签,然后隐藏标签)。通过转到 Slice 透视图,选择“外部类”切片、主集群并使用按父项分组选项,可能会获得一个有用的视图。这将在单个图表上显示所有类,按其父包分组。如果您有一个非常大的项目,您可以切换到 DSM 视图,它比有向图更具可扩展性。

        【讨论】:

          【解决方案4】:

          您可能想看看this question 的答案,它可能适合解决您的问题?

          【讨论】:

            【解决方案5】:

            JDepend 看起来可以这样做:http://clarkware.com/software/JDepend.html

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-07-04
              • 2011-03-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多