0

我在 A 类中有一个方法 m1,它有一个 B 类类型的变量 b,m1 通过调用 b.m2(...) 调用 B 类中的方法 m2。现在,方法 m2 不是在类 B 中实现,而是在派生出 B 的类 C 中实现。如果您在这种情况下运行 jQAssistant,如果所有三个类都属于同一个工件,我会得到以下关系: (A)-[:DECLARES]->(m1)-[:INVOKES]->(m2)<-[:DECLARES ]-(B)<-[:EXTENDS]-(C) 和 (C)-[:DECLARES]->(m2')。请注意, (B)-[:DECLARES]->(m2) 是一种综合声明,因为 m2 并不是真正由 B 声明的,而是被继承的。

但是假设 A 类与 B 类和 C 类属于不同的工件。那么解析机制不会在解析的 B 类中生成综合声明。更准确地说,扫描 A 的工件会生成: (A)-[:DECLARES ]->(m1)-[:INVOKES]->(m2'')<-[:DECLARES]-(B')。并通过概念 classPath:Resolve 解析将创建: (B')-[:RESOLVES_TO]->(B) 但不会有 (B)-[:DECLARES]->(m2) ,因此 m2'' 不能解决为m2。因此, :INVOKES 关系也无法解决。

4

1 回答 1

0

对我来说,以下概念有效:

<concept id="missingResolves:AddInheritedMethodsToResolvedTypes">
    <requiresConcept refId="classpath:ResolveMember"/>
    <description>Sometimes the method needed to resolve a method m1 declared in a type t1 is not directly declared in the resolved type t2, but just inherited by t2, then we add this method to t2 (as synthetic-declare).</description>
    <cypher><![CDATA[
    MATCH (t1:Type)-[:RESOLVES_TO]->(t2:Type), (t1)-[:DECLARES]->(m1:Method)
    WHERE  NOT (m1)-[:RESOLVES_TO]->()
    WITH DISTINCT t2, m1.signature AS methodSignature
    MERGE (t2)-[:DECLARES {synthetic: true}]->(m2:Method {signature: methodSignature})
    RETURN t2.name as type, methodSignature ORDER BY t2.name, methodSignature
    ]]></cypher>
</concept>

<concept id="missingResolves:ResolveMethodsUsingInheritedMethodsInResolvedTypes">
    <requiresConcept refId="missingResolves:AddInheritedMethodsToResolvedTypes"/>
    <description>Uses the synthetic methods added by the "AddInheritedMethodsToResolvedTypes" concept to add missing method resolves.</description>
    <cypher><![CDATA[
    MATCH (t1:Type)-[:RESOLVES_TO]->(t2:Type), (t1)-[:DECLARES]->(m1:Method)
    WHERE  NOT (m1)-[:RESOLVES_TO]->()
    WITH t1, t2, m1 MATCH (t2)-[:DECLARES {synthetic: true}]->(m2:Method)
    WHERE  m1.signature = m2.signature
    MERGE (m1)-[:RESOLVES_TO {resolved:true}]->(m2)
    RETURN count(m1) as ResolvedMethods
    ]]></cypher>
</concept>

<concept id="missingResolves:ResolveInvokesAgain">
    <requiresConcept refId="classpath:ResolveInvokes"/>
    <requiresConcept refId="missingResolves:ResolveMethodsUsingInheritedMethodsInResolvedTypes"/>
    <description>Resolve method invocations again (same as in original jQAssistant).</description>
    <cypher><![CDATA[
    MATCH (m:Method)-[i:INVOKES]->(m1:Method)-[:RESOLVES_TO]->(m2:Method)
    WHERE NOT (m)-[:INVOKES{lineNumber:i.lineNumber,resolved:true}]->(m2)
    MERGE (m)-[:INVOKES{lineNumber:i.lineNumber,resolved:true}]->(m2)
    RETURN count(i) as ResolvedInvocations      
    ]]></cypher>
</concept>

<concept id="missingResolves:Correct">
    <requiresConcept refId="classpath:Resolve"/>
    <requiresConcept refId="missingResolves:ResolveInvokesAgain"/>
    <description>Performs a complete corrected resolve.</description>
    <cypher><![CDATA[
    MATCH ()-[r:RESOLVES_TO]->() RETURN count(r) as ResolvedElements
    ]]></cypher>
</concept>
于 2016-07-21T08:24:02.587 回答