0

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

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 声明。似乎缺少一些链接这两种相同方法的步骤。

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

4

1 回答 1

0

super.superMethod()调用和之间存在细微差别superMethod()

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

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

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

有一个概念java:MethodOverrides应该创建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
于 2020-03-30T07:52:44.083 回答