ArchUnit
ArchUnit copied to clipboard
Add support for casts
At the moment casts without any further dependencies on the target type are not detected as dependencies. I.e.
SomeClass example(Object rawInput) {
return (SomeClassImpl) rawInput; // should forbid dependencies on SomeClassImpl
}
Since there are no further dependencies on SomeClassImpl this would be missed. It does likely not cause a maintenance problem later, because the cast could at any time be weakened to (SomeClass) without any further compile or runtime issues, but still it would be nice to detect these things. Also to be able to access all casts that a class or method applies could be useful for other scenarios.
We could add this the following way:
- extend
Set<TypeCast> JavaCodeUnit.getCasts()(compareInstanceofCheck) - add the
TypeCasts toJavaClass.directDependencies{From/To}Self
(open for discussion: What is the best name for the domain object? TypeCast, Cast, JavaCast, ClassCast, ...?)
Is this issue open? If yes I would like to try to work on it. I have a few questions about the task. JavaClass.directDependencies{From/To}Self those methods are returning a set of Dependency objects. TypeCasts should be added to the dependency object or a new version of those methods is required like this: "getDirectDependenciesFromSelf(TypeCasts typeCasts)"?
IMO we want both: (1) a specific method to ask domain objects for casts, and (2) register those as dependencies.
Random previous examples:
instanceofchecks- (1)+(2) were added with c89adacbe10e12ece545bfb5e271f39e2e81b63e.
.classreferences- (1) was added with 66737c0b5f0ce72836a7dd6825ee8957c4fa01b1.
- (2) was added with 9123d39c1a17321464d330b76e149bac04a066f6.
@Kaammill and yes, the issue is up for grabs and we're always super happy about contributions :smiley:
Some information about checkcast
The compiler might add some checkcast instructions:
void foobar(java.lang.Object);
Code:
0: aload_1
1: invokestatic #29 // Method com/foobar/SomeClass.of:(Ljava/lang/Object;)Lcom/foobar/SomeClass;
4: ldc #35 // class java/lang/Boolean
6: invokevirtual #37 // Method com/foobar/SomeClass.someMethod:(Ljava/lang/Class;)Ljava/lang/Object;
9: checkcast #35 // class java/lang/Boolean
What I noticed: if the previous instruction is invokevirtual or invokeinterface, the checkcast was generated by the compiler
Also bridge methods will have more compiler checkcast instructions
Detecting casts are also useful when working with polymorphism in hibernate, where instanceof and direct casts should not be used due to hibernate proxies.
Having this feature in archunit would also help in building rules for this case