如何使用 jqassistant 检测/解析超级方法调用

How to detect / resolve super method invocations with jqassistant

我正在使用 jqassistant 1.8.0 来检测 class 层次结构中的超级方法调用。 似乎 class 层次结构中的一些方法调用丢失了,即使在应用 classpath:Resolve 概念之后也是如此。最小设置包含三个 classes:

public class SuperClass {

  void superMethod() {
  }

}

public class SubClass1 extends SuperClass {

  void subMethod1() {
    super.superMethod();
  }

}

public class SubClass2 extends SuperClass {

  void subMethod2() {
    superMethod();
  }
}

subMethod1 和 subMethod2 都在调用 SuperClass 的相同方法,但只有具有显式 "super." 调用的方法具有 :INVOKES 关系。

MATCH
  (who)-[:INVOKES]->(m)<-[:DECLARES]-(:Type {fqn: 'SuperClass'})
Return who

数据库中存在两个具有签名 "void superMethod()" 的节点,一个由 SuperClass 声明,一个由 SubClass2 声明。似乎缺少一些链接两个相同方法的步骤。

是否有另一个内置概念(除了 classpath:Resolve)解决这个问题,还是 java-plugin 没有涵盖这个问题?谢谢!

super.superMethod()superMethod() 的调用略有不同:

第一个指示JVM使用来自super class的方法,第二个依赖于在运行时解析该方法,SubClass2中可能有一个实现(虚拟调用):

对于这种情况,创建的图包含对 SubClass2 中方法占位符的调用(仅具有签名 属性):

(method)-[:INVOKES]->(:Method{signature:"void superMethod()"})<-[:DECLARES]-(:Type{name:"SubClass2"}) 

有一个概念 java:MethodOverrides 应该创建与超级 class 方法的 OVERRIDES 关系,但遗憾的是它在这种情况下不起作用(直到 jQA 1.8.0)。已经应用了 jQA 1.9.0 附带的修复程序:

            MATCH
              (type:Type)-[:DECLARES]->(method:Method),
              (superType:Type)-[:DECLARES]->(superMethod:Method),
              path=shortestPath((type)-[:EXTENDS|IMPLEMENTS*]->(superType))
            WHERE
              method.signature = superMethod.signature
              and superMethod.visibility <> "private"
            WITH
              type, method, superType, superMethod, length(path) as depth
            ORDER BY
              depth asc
            WITH
              method, head(collect(superMethod)) as overriddenMethod
            MERGE
              (method)-[:OVERRIDES]->(overriddenMethod)
            RETURN
              count(*) as OverriddenMethods

使用这个你应该能够执行以下查询:

MATCH
  (:Type{name:"SuperClass"})-[:DECLARES]->(m:Method{name:"superMethod"}),
  (who)-[:INVOKES]->(:Method)-[:OVERRIDES*0..1]->(m) // catching direct or virtual invocations
RETURN
  who