提取scala项目的完整调用图(艰难的一个)
我想从一个给定的Scala项目中提取所有方法的调用图,这些是项目自己的源代码的一部分。
据了解,演示文稿编译器不能启用,而且它需要一直下降到实际编译器(或编译器插件?)。 你能建议完整的代码,这将安全地适用于大多数scala项目,但那些使用最古老的动态语言功能?对于调用图,我的意思是包括类/特征方法顶点的有向(可能是循环的)图,其中边 – B表示A可以调用B. 来自图书馆的图书馆的呼叫应避免或被标记为不在项目本身的来源之外。 谢谢! 编辑: 看到我的宏天堂衍生原型解决方案,基于@ dk14的领先,作为下面的答案。主持在github在http://goo.gl/oeshdx。 解决方法
这是工作原型,它将必要的基础数据打印到控制台,作为概念证明。
http://goo.gl/oeshdx。
如何运作 我从macro paradise开始,将@ dk14的概念从顶层样板中进行了调整。 Macro paradise允许您定义一个注释,该批注将在您的源代码中的任何注释对象上应用您的宏。从那里您可以访问编译器为源生成的AST,而scala反射api可用于探索AST元素的类型信息。 Quasiquotes(词源来自haskell或某物)用于匹配相关要素的AST。 更多关于Quasiquotes 要注意的一个重要的事情是,quasiquotes工作在AST,但它们是一个奇怪的第一眼api,而不是AST(!)的直接表示。 AST通过天堂的宏注释为你挑选,然后quasiquote是探索手头的AST的工具:您使用quasiquotes匹配,切片和骰子抽象语法树。 关于quasiquotes的实际注意事项是,有固定的quasiquote模板,用于匹配每种类型的scala AST – Scala类定义的模板,Scala方法定义的模板等。These tempaltes are all provided here,使其非常简单的匹配和解构手头的AST有趣的成分。虽然模板可能看起来很尴尬,但它们大多只是模仿scala语法的模板,您可以将$ prepended变量名称自由地更改为更适合您的口味的名称。 我还需要进一步磨练我使用的quasiquote比赛,目前还不完美。然而,我的代码似乎在许多情况下产生了期望的结果,并且将匹配珩磨到95%的精度可能是很好的。 样品输出 found class B class B has method doB found object DefaultExpander object DefaultExpander has method foo object DefaultExpander has method apply which calls Console on object scala of type package scala which calls foo on object DefaultExpander.this of type object DefaultExpander which calls <init> on object new A of type class A which calls doA on object a of type class A which calls <init> on object new B of type class B which calls doB on object b of type class B which calls mkString on object tags.map[String,Seq[String]](((tag: logTag) => "[".+(Util.getObjectName(tag)).+("]")))(collection.this.Seq.canBuildFrom[String]) of type trait Seq which calls map on object tags of type trait Seq which calls $plus on object "[".+(Util.getObjectName(tag)) of type class String which calls $plus on object "[" of type class String which calls getObjectName on object Util of type object Util which calls canBuildFrom on object collection.this.Seq of type object Seq which calls Seq on object collection.this of type package collection . . . 很容易看出呼叫者和被调用者可以如何从这些数据进行关联,以及如何过滤或标记项目源之外的呼叫目标。这一切都是为了scala 2.11。使用这个代码,需要在每个源文件中为每个类/对象/ etc添加注释。 剩下的挑战主要是: 剩下的挑战: >完成这项工作后,这会崩溃。 7月4日凌晨 思考的替代方法 acyclic提出了一个完全相反的方法,它仍然依赖于scala编译器的领域 – 它会检查由源程序生成的所有符号,由编译器(就像我从源代码中收集)一样。它的作用是检查循环引用(有关详细定义,请参阅repo)。每个符号据称具有足够的信息,以得出acyclic需要生成的参考图。 如果可行,如果可行,可以找到父“owner” of every symbol的方案,而不是将焦点放在源文件连接图上,因为非循环本身。因此,通过一些努力,它将恢复每个方法的类/对象所有权。不确定这种设计是否不会计算爆炸,也不确定如何确定性地获取包含每个符号的类。 上行空间是在这里不需要宏注释。缺点是,这不能将运行时仪器放置为宏观天堂,而是容易允许,这可能有时是有用的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |