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

Remove accesses to synthetic enum SwitchMap fields when checking classes accessability #1011

Open
marcindabrowski opened this issue Nov 28, 2022 · 3 comments

Comments

@marcindabrowski
Copy link

Hi,
I'm using ArchUnit 1.0.1 with Java 17 and have a similar problem as described in #570 resolved by PR #895

I have this enum:

public enum ExampleEnum {
  FOO,
  BAR
}

and mapper

public class ExampleEnumMapper {
  public static String failingExample1(final ExampleEnum exampleEnum) {
    return switch (exampleEnum) {
      case FOO -> "foo";
      case BAR -> "bar";
    };
  }
}

When I'm executing this test:

    private static final JavaClasses MODULE_CLASSES = new ClassFileImporter().importPath("build/classes/java")

    def "should mappers be public"() {
        given: "a rule"
            ArchRule rule = classes()
                .should()
                .bePublic()

        expect: "rule is not broken"
            rule.check(MODULE_CLASSES)
    }

I'm getting this error:

java.lang.AssertionError: Architecture Violation [Priority: MEDIUM] - Rule 'classes should be public' was violated (1 times):
Class <com.example.ExampleEnumMapper$1> does not have modifier PUBLIC in (ExampleEnumMapper.java:0)
@codecholeric
Copy link
Collaborator

Yes, I tried to be as little invasive as possible, because removing the whole class is a bigger impact. For now you can just adjust the rule to

classes()
  .that().doNotHaveModifier(JavaModifier.SYNTHETIC)
  .should()
  .bePublic();

That should exclude your cases, right?

@marcindabrowski
Copy link
Author

That should exclude your cases, right?

Thanks, it is working.
But should I close this Issue?
For me, it looks like a workaround, not a final solution,.

@codecholeric
Copy link
Collaborator

The problem is that I'm not sure if there is a general rule to deal with synthetic code. And once excluded there will be no way anymore for users to interact with it at all. I'm just thinking about dependency cases, where the source code actually results in a synthetic class (or method) being created where the compiled source code then lives. If the synthetic code is just ignored we suddenly don't have any traces more of the dependencies that were in the original source code.
I once experimented quite a lot to remove all synthetic members in #87 and I couldn't figure out a way to make it work without losing information in some place.
If we talk about dependencies, then it's still better to see Class <a.b.Magic$synthetic$123> calls method <a.b.Foo.bar()>... than not having any trace anymore at all even though it's in the source code 🤔 In particular, if things like the Kotlin compiler are also taken into consideration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants