TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.18k stars 288 forks source link

Can I obtain the return type or field type in JavaAccess? #1164

Closed heyuxiang1996 closed 1 year ago

heyuxiang1996 commented 1 year ago

I am making a rule to check if the application calls Google HideApi, This seems to require obtaining more detailed information from JavaAccess Can I obtain the return type or field type in JavaAccess? Examples similar to the following:

public class Temp {
    public void aMethod() {
        String s = TripartiteLibrary.a();
        int b = TripartiteLibrary.b;
    }

    @Test
    public void test() {
        JavaMethod javaMethod = new ClassFileImporter().importClass(Temp.class).getMethod("aMethod");
        javaMethod.getAccessesFromSelf().stream().forEach(javaAccess -> {
            System.out.println(javaAccess.getDescription());
            // Can I obtain the return type or field type in JavaAccess?
        });
    }

}
hankem commented 1 year ago

The field or method are the target of the corresponding JavaAccess. You need to look at specific subclasses of this generic class in order to make full sense it:

JavaAccess<TARGET>
├─ JavaFieldAccess extends JavaAccess<FieldAccessTarget>
└─ JavaCodeUnitAccess<T extends CodeUnitAccessTarget> extends JavaAccess<T>
   ├─ JavaCall<T extends CodeUnitCallTarget> extends JavaCodeUnitAccess<T>
   │  ├─ JavaMethodCall extends JavaCall<AccessTarget.MethodCallTarget>
   │  └─ JavaConstructorCall extends JavaCall<AccessTarget.ConstructorCallTarget>
   └─ JavaCodeUnitReference<T extends CodeUnitReferenceTarget> extends JavaCodeUnitAccess<T>
      ├─ JavaMethodReference extends JavaCodeUnitReference<MethodReferenceTarget>
      └─ JavaConstructorReference extends JavaCodeUnitReference<ConstructorReferenceTarget>

So if you're only interested in method return types or field types:

System.out.println(javaAccess.getDescription());
// Can I obtain the return type or field type in JavaAccess?
// => YES, we can!
if (javaAccess instanceof JavaMethodCall) {
    System.out.println("Method return type: " + ((JavaMethodCall) javaAccess).getTarget().getReturnType());
}
if (javaAccess instanceof JavaFieldAccess) {
    System.out.println("Field type: " + ((JavaFieldAccess) javaAccess).getTarget().getType());
}
heyuxiang1996 commented 1 year ago

very detailed response I forgot about the inheritance relationship of JavaAccess, Thank you very much!!!