Skip to content

Add generic method parameter types#640

Merged
codecholeric merged 3 commits intomainfrom
add-generic-method-parameter-types
Aug 20, 2021
Merged

Add generic method parameter types#640
codecholeric merged 3 commits intomainfrom
add-generic-method-parameter-types

Conversation

@codecholeric
Copy link
Copy Markdown
Collaborator

@codecholeric codecholeric commented Jul 16, 2021

As last step to fully support Generics within ArchUnit this adds support for generic method/constructor parameter types. In particular

  • JavaMethod.getParameterTypes() now returns a List of JavaParameterizedType for parameterized generic method/constructor parameter types and the raw types otherwise
  • all type arguments of generic method parameter types are added to JavaClass.directDependencies{From/To}Self

Example: ArchUnit would now detect String and File as Dependency of a method declaration like

class SomeClass {
    void someMethod(Set<List<? super String>> first, Map<?, ? extends File> second) {
    }
}

Note that analogously to the Java Reflection API JavaConstructor.getParameterTypes() and JavaConstructor.getRawParameterTypes() do not behave exactly the same for inner classes. While JavaConstructor.getRawParameterTypes() contains the enclosing class as first parameter type, JavaConstructor.getParameterTypes() does not contain it if the constructor has generic parameters. On the other hand it just returns the same list of raw parameter types if the constructor is non-generic. This might surprise some users, but I decided to stick to the same behavior as the Reflection API, because this has always been the strategy and the solution can never truly satisfy all assumptions a user might have.

Resolves: #115
Resolves: #144
Resolves: #440

@OLibutzki
Copy link
Copy Markdown
Contributor

I'm highly interested in getting this PR to be merged. 🙂

Are there any more obstacles to overcome before this can be merged?

Copy link
Copy Markdown
Member

@hankem hankem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry that it took me so long to review this PR!

@codecholeric
Copy link
Copy Markdown
Collaborator Author

I'm sorry that it took me so long to review this PR!

No worries, I know that it's not in all phases of life super easy to spend a lot of time on OSS 😉 You're always giving great support to ArchUnit, so thanks a lot!

There is actually a violation of the current layer structure, because the method `void setClassResolver(Class<? extends ClassResolver> classResolver)` has a generic parameter type dependency on `ClassResolver` from the `import` layer. I thought about fixing it, but

* it is public API
* it would make the API harder to use (either no guard, or split up into separate places)
* I don't consider this dependency especially harmful for now (the dependency could be removed without breaking any clients at any point)

Thus I have decided to add a conscious exception for this case for now.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
Note that raw and generic parameter types do not behave the same way in all cases. Specifically for constructors of inner classes that obtain a reference to their enclosing class. In this case the Reflection API returns the enclosing class as first raw parameter of the constructor, while the generic parameters (in case there are any) do not contain the enclosing class. Thus I decided to keep both raw and generic parameters in `JavaCodeUnit` separately, while `getParameters()` will return the raw parameters (and thus one extra parameter for inner classes) in non-generic cases. This does not feel great, but the alternatives seem even worse. At least this way it is consistent to the Reflection API. If we choose a different path there will most likely be even more confusion.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
Covers dependencies from and to a `JavaClass` by some generic type argument of a method or constructor.

Signed-off-by: Peter Gafert <peter.gafert@tngtech.com>
@codecholeric codecholeric force-pushed the add-generic-method-parameter-types branch from 79ddd53 to e646c89 Compare August 20, 2021 17:46
@codecholeric codecholeric merged commit 2439767 into main Aug 20, 2021
@codecholeric codecholeric deleted the add-generic-method-parameter-types branch August 20, 2021 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants