-
Notifications
You must be signed in to change notification settings - Fork 298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getCallsOfSelf does not return calls made through interface reference #1225
Comments
This is actually expected behavior: ArchUnit does not (and in general cannot) track the type of all objects at runtime, and void callDoSomething() {
MyInterface myInterface = new MyClassA();
myInterface.doSomething();
} is compiled to the following byte code:
– which doesn't know anything about a call to |
That is unfortunate because then it is not reliably possible to determine whether a specific method is directly or transitively invoked by certain other methods. I am not familiar with Java bytecode, and I accept your answer, but I have heard that there are analysis tools such as ASM, Byte Buddy, or BCEL that can extract information about the implementation of interfaces from bytecode. |
The information about implementation of interfaces is available in ArchUnit, but your question is about resolving runtime/dynamic polymorphism. While it may seem obvious that MyInterface myInterface = new MyClassA();
myInterface.doSomething(); calls void callDoSomething() {
doSomething(new MyClassA());
}
void callDoSomething(MyInterface myInterface) {
myInterface.doSomething();
} is recognized? You can see that this can become arbitrarily complicated for a static code analysis tool. To me, this seems impossible (in general), but I'm of course open to suggestions. |
I concur that precisely tracking the diverse paths taken by a program's control flow to conclusively assert that only objects of type T1 - Tn, implementing an interface MyInterface, can emerge at a particular juncture—excluding objects of type Tn+1 - Tn+m, which also implement MyInterface—would be a formidable task. However, should one implement a mode positing that, when leveraging interfaces, any implementation of the interface could potentially manifest wherever the interface is employed, then it would become comparatively straightforward to compute all theoretically feasible transitive chains. Or, could there be an aspect I've inadvertently overlooked? |
Consider the following code base:
Then calling getCallsOfSelf on JavaMethod object for MyClassA.doSomething will find nothing.
But expected would be to find MyClassCaller.callDoSomething.
Changing type of myInterface in callDoSomething from MyInterface to MyClassA leads to getCallsOfSelf finding callDoSomething
I was using the following dependency to archunit:
The text was updated successfully, but these errors were encountered: