【发布时间】:2012-02-02 16:18:15
【问题描述】:
我想建立一些关于在某些 Scala 源代码中使用了哪些 Java 标准库类(java.*/javax.*)和方法的统计数据(以及使用频率)。
最直接的方法是什么?是否有机会也涵盖传递依赖关系,例如。 G。当某些 Lift 类依赖于 Scala 标准库方法,而后者又依赖于 Java 标准库方法?
【问题讨论】:
标签: java scala statistics dependencies
我想建立一些关于在某些 Scala 源代码中使用了哪些 Java 标准库类(java.*/javax.*)和方法的统计数据(以及使用频率)。
最直接的方法是什么?是否有机会也涵盖传递依赖关系,例如。 G。当某些 Lift 类依赖于 Scala 标准库方法,而后者又依赖于 Java 标准库方法?
【问题讨论】:
标签: java scala statistics dependencies
我写了一个 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
【讨论】:
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 类的。
它也有传递依赖。
【讨论】:
您可以使用Structure101 执行此操作。从 Scala/Java 字节码加载 S101 项目,转到 Collaboration 透视图(Structure 选项卡)并在左侧树形视图中选择 Scala 代码的根包,并在 rhs 中选择 Java 包。这将显示您的 Scala 项目使用了哪些 Java 项(到 package.class.method/field 的详细级别),以及哪些 Scala 项使用了 Java 库中的任何内容,您可以深入查看特定的依赖关系。
您还可以使用标记来获得传递依赖。选择项目,右键单击,标记/使用/间接。这将用一个蓝点标记项目,该蓝点在每个透视图中滚动。您可以隐藏除了传递闭包之外的所有内容(反转标签,然后隐藏标签)。通过转到 Slice 透视图,选择“外部类”切片、主集群并使用按父项分组选项,可能会获得一个有用的视图。这将在单个图表上显示所有类,按其父包分组。如果您有一个非常大的项目,您可以切换到 DSM 视图,它比有向图更具可扩展性。
【讨论】:
您可能想看看this question 的答案,它可能适合解决您的问题?
【讨论】:
JDepend 看起来可以这样做:http://clarkware.com/software/JDepend.html
【讨论】: