diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/Reference.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/Reference.java index 362b37d0cde..483f888e649 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/Reference.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/Reference.java @@ -9,10 +9,12 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import lombok.ToString; import net.bytebuddy.jar.asm.Opcodes; import net.bytebuddy.jar.asm.Type; /** An immutable reference to a jvm class. */ +@ToString public class Reference { private final Set sources; private final String className; @@ -129,11 +131,6 @@ private static Set mergeFlags(final Set flags1, final Set flag return merged; } - @Override - public String toString() { - return "Reference<" + className + ">"; - } - public static class Source { private final String name; private final int line; diff --git a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceCreator.java b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceCreator.java index d5455ef3088..230d7bdf0ca 100644 --- a/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceCreator.java +++ b/dd-java-agent/agent-tooling/src/main/java/datadog/trace/agent/tooling/muzzle/ReferenceCreator.java @@ -180,9 +180,16 @@ public void visit( refSourceClassName = Utils.getClassName(name); refSourceType = Type.getType("L" + name + ";"); refSourceTypeInternalName = refSourceType.getInternalName(); - // Additional references we could check - // - supertype of class and visible from this package - // - interfaces of class and visible from this package + + // Add references to each of the interfaces. + for (String iface : interfaces) { + addReference( + new Reference.Builder(iface) + .withSource(refSourceClassName, 0) // We don't have a specific line number to use. + .withFlag(Reference.Flag.PUBLIC) + .build()); + } + // the super type is handled by the method visitor to the constructor. super.visit(version, access, name, signature, superName, interfaces); } diff --git a/dd-java-agent/testing/src/test/groovy/muzzle/ReferenceCreatorTest.groovy b/dd-java-agent/testing/src/test/groovy/muzzle/ReferenceCreatorTest.groovy index 7af6299d2bf..a471ff47d3b 100644 --- a/dd-java-agent/testing/src/test/groovy/muzzle/ReferenceCreatorTest.groovy +++ b/dd-java-agent/testing/src/test/groovy/muzzle/ReferenceCreatorTest.groovy @@ -49,6 +49,19 @@ class ReferenceCreatorTest extends AgentTestRunner { aFieldRefs.size() == 2 } + def "ref test"() { + setup: + Map references = ReferenceCreator.createReferencesFrom(MethodBodyAdvice.A.getName(), this.getClass().getClassLoader()) + def a = references.get('muzzle.TestClasses$MethodBodyAdvice$A') + def b = references.get('muzzle.TestClasses$MethodBodyAdvice$B') + + expect: + references.keySet() == ['muzzle.TestClasses$MethodBodyAdvice$A', 'muzzle.TestClasses$MethodBodyAdvice$B'].toSet() + + and: "doesn't need to reference self" + !(a.getSources().any { it.name == 'muzzle.TestClasses$MethodBodyAdvice$A' }) + } + def "protected ref test"() { setup: Map references = ReferenceCreator.createReferencesFrom(MethodBodyAdvice.B2.getName(), this.getClass().getClassLoader()) @@ -67,6 +80,24 @@ class ReferenceCreatorTest extends AgentTestRunner { references.get('muzzle.TestClasses$MethodBodyAdvice$A') != null } + def "interface impl creates references"() { + setup: + Map references = ReferenceCreator.createReferencesFrom(MethodBodyAdvice.SomeImplementation.getName(), this.getClass().getClassLoader()) + + expect: + references.get('muzzle.TestClasses$MethodBodyAdvice$SomeInterface') != null + references.size() == 1 + } + + def "child class creates references"() { + setup: + Map references = ReferenceCreator.createReferencesFrom(MethodBodyAdvice.A2.getName(), this.getClass().getClassLoader()) + + expect: + references.get('muzzle.TestClasses$MethodBodyAdvice$A') != null + references.size() == 1 + } + def "instanceof creates references"() { setup: Map references = ReferenceCreator.createReferencesFrom(InstanceofAdvice.getName(), this.getClass().getClassLoader()) @@ -82,7 +113,7 @@ class ReferenceCreatorTest extends AgentTestRunner { Map references = ReferenceCreator.createReferencesFrom(TestClasses.InDyAdvice.getName(), this.getClass().getClassLoader()) expect: - references.get('muzzle.TestClasses$MethodBodyAdvice$SomeImplementation') != null + references.get('muzzle.TestClasses$MethodBodyAdvice$HasMethod') != null references.get('muzzle.TestClasses$MethodBodyAdvice$B') != null } diff --git a/dd-java-agent/testing/src/test/java/muzzle/TestClasses.java b/dd-java-agent/testing/src/test/java/muzzle/TestClasses.java index 931d8b098dd..7ee27cc599b 100644 --- a/dd-java-agent/testing/src/test/java/muzzle/TestClasses.java +++ b/dd-java-agent/testing/src/test/java/muzzle/TestClasses.java @@ -95,10 +95,9 @@ public static boolean instanceofMethod(final Object a) { // Can't test this until java 7 is dropped. public static class InDyAdvice { - // public static MethodBodyAdvice.SomeInterface indyMethod( - // final MethodBodyAdvice.SomeImplementation a) { + // public static MethodBodyAdvice.HasMethod indyMethod(final MethodBodyAdvice.HasMethod a) { // Runnable aStaticMethod = MethodBodyAdvice.B::aStaticMethod; - // return a::someMethod; + // return a::requiredMethod; // } } }