Skip to content
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

More easily detect overridden methods & calls to super #1040

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
380958a
Added Method#isOverridden
java-coding-prodigy Jan 6, 2023
e569b0e
Fixed the method and added a test
java-coding-prodigy Jan 7, 2023
9c68442
Merge branch 'main' into main
java-coding-prodigy Jan 7, 2023
9f58651
Added support for methods in grandparent class and used ArchUnit API …
java-coding-prodigy Jan 8, 2023
1903590
Merge branch 'main' of github.com:TNG/ArchUnit
java-coding-prodigy Jan 8, 2023
3e97e3f
Fixed issue with `isOverridden`
java-coding-prodigy Jan 8, 2023
3ea2f36
Added testing for overriden method in grandparent class
java-coding-prodigy Jan 8, 2023
c901839
Merge branch 'main' of github.com:java-coding-prodigy/ArchUnit
java-coding-prodigy Jan 8, 2023
9e74551
Undo accidental copyright change
java-coding-prodigy Jan 8, 2023
c9e63f6
Check for super methods in interfaces as well
java-coding-prodigy Jan 8, 2023
02eae70
Import fix
java-coding-prodigy Jan 8, 2023
e67cb29
Merge branch 'main' into main
java-coding-prodigy Feb 8, 2023
d7c3481
Got this so far
java-coding-prodigy May 17, 2023
2acc5d6
Got this so far
java-coding-prodigy May 17, 2023
9c8a0a2
Merge branch 'main' into main
java-coding-prodigy May 18, 2023
82c8bfa
Merge branch 'main' into main
java-coding-prodigy Jul 25, 2023
1767d88
Merge branch 'main' into main
java-coding-prodigy Oct 6, 2023
b8b74e6
Merge branch 'TNG:main' into main
java-coding-prodigy Oct 15, 2023
c13a74a
Finally passed the test.
java-coding-prodigy Nov 11, 2023
fa2bebc
Merge branch 'main' into main
java-coding-prodigy Nov 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import com.tngtech.archunit.PublicAPI;
import com.tngtech.archunit.base.ArchUnitException.InconsistentClassPathException;
Expand Down Expand Up @@ -125,6 +126,14 @@ public String getDescription() {
return "Method <" + getFullName() + ">";
}

@PublicAPI(usage = ACCESS)
public boolean isOverridden() {
return Stream.concat(getOwner().getAllRawSuperclasses().stream(), getOwner().getAllRawInterfaces().stream())
Copy link
Member

Choose a reason for hiding this comment

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

Can we pleae add a small test to cover the feature that overriden methods from interfaces are detected?

.map(JavaClass::getAllMethods)
.flatMap(Set<JavaMethod>::stream)
.anyMatch(superMethod -> superMethod.getName().equals(getName()) && superMethod.getParameterTypes().equals(getParameterTypes()));
}

@ResolvesTypesViaReflection
@MayResolveTypesViaReflection(reason = "Just part of a bigger resolution process")
private class ReflectMethodSupplier implements Supplier<Method> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.tngtech.archunit.core.domain;


import com.tngtech.archunit.core.importer.ClassFileImporter;
import org.junit.Test;

import static com.tngtech.archunit.testutil.Assertions.assertThat;

public class JavaMethodTest {
@Test
public void isOverriddenTest() {
class Base {
void method1() {
}

void method1(int x) {
}
}
class Child extends Base {
void method1() {
}

void method2() {
}
}
class GrandChild extends Child {
void method1() {

}

void method1(int x) {

}

void method2() {

}

void method3() {

}

}
ClassFileImporter importer = new ClassFileImporter();
JavaClass baseClass = importer.importClass(Base.class);
JavaClass childClass = importer.importClass(Child.class);
JavaClass grandChildClass = importer.importClass(GrandChild.class);
assertThat(baseClass.getMethod("method1").isOverridden()).isFalse();
assertThat(baseClass.getMethod("method1", int.class).isOverridden()).isFalse();
assertThat(childClass.getMethod("method1").isOverridden()).isTrue();
assertThat(childClass.getMethod("method2").isOverridden()).isFalse();
assertThat(grandChildClass.getMethod("method1").isOverridden()).isTrue();
assertThat(grandChildClass.getMethod("method1", int.class).isOverridden()).isTrue();
assertThat(grandChildClass.getMethod("method2").isOverridden()).isTrue();
assertThat(grandChildClass.getMethod("method3").isOverridden()).isFalse();
//TODO add testing for methods with generic parameters
Copy link
Member

Choose a reason for hiding this comment

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

It seems that we indeed don't recognize all overriden generic methods:

    @Test
    public void overridden_generic_methods_are_supported() {
        class Parent<T extends Number> {
            void method(T t) { }
        }
        class Child extends Parent<Integer> {
            @Override
            void method(Integer t) { }
        }
        JavaClass childClass = new ClassFileImporter().importClass(Child.class);
        JavaMethod method = childClass.getMethod("method", Integer.class);
        assertThat(method.isOverridden()).isTrue();  // Expecting value to be true but was false 
    }

Choose a reason for hiding this comment

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

Hmmm, this might complicate the code now.
I'll see what I can do.

}
}
Copy link
Member

Choose a reason for hiding this comment

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

We should also have a test for the use case of #1047 .

Copy link
Author

Choose a reason for hiding this comment

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

I believe that is already in place, currently we check if the parameters and name of the method are equal, and that implies compatibility of return type.
If that is not the case, then the user code will not compile in the first place

Copy link
Member

Choose a reason for hiding this comment

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

I thought that we should document that this works (which it curently does, but we also want to avoid any future regression):

    @Test
    public void more_specific_return_type_is_supported() {
        class Parent {
            CharSequence method() { return "base"; }
        }
        class Child extends Parent {
            @Override
            String method() { return "overridden"; }
        }
        JavaClass childClass = new ClassFileImporter().importClass(Child.class);
        JavaMethod method = childClass.getMethod("method");
        assertThat(method.isOverridden()).isTrue();
    }