如何检测Scala源中Java类的依赖关系?

时间:2012-01-04 18:59:10

标签: java scala statistics dependencies

我想构建一些关于哪些Java标准库类(java.* / javax.*中的那些)和方法在一些Scala源代码中使用的常规统计信息(以及频率)。

最直接的方法是什么?是否有机会涵盖传递依赖关系,例如: G。当一些Lift类依赖于Scala标准库方法时,该方法依赖于Java标准库方法?

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您可能想看看this question的答案,该答案可能会适用于解决您的问题?

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

IntelliJ IDEA有一个名为Analyze Dependencies的功能,它可以做你想要的。

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

<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类。

它也具有传递依赖性。

答案 4 :(得分:0)

我写了一个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