Как обнаружить / разрешить супер вызовы методов с помощью jqassistant - PullRequest
0 голосов
/ 25 марта 2020

Я использую 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, но только тот, который явно " супер." вызов имеет отношение: INVOKES.

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

В базе данных существует два узла с подписью "void superMethod ()", один объявлен суперклассом, а другой - субклассом2. Кажется, что отсутствует какой-то шаг, который связывает два идентичных метода.

Существует ли другая встроенная концепция (кроме classpath: Resolve), разрешающая это, или она не охватывается java -плагином? Спасибо!

1 Ответ

0 голосов
/ 30 марта 2020

Существует небольшая разница между вызовами 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
...