-
Notifications
You must be signed in to change notification settings - Fork 325
Improve error messages for synthetic/anonymous class violations #1552
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
base: main
Are you sure you want to change the base?
Improve error messages for synthetic/anonymous class violations #1552
Conversation
When ArchUnit rules fail on synthetic or anonymous classes generated by the compiler (e.g., from lambdas or enum switches), new users are often confused by error messages pointing to classes they didn't write (MyService$1). This commit enhances naming convention error messages to detect synthetic/ anonymous classes and provide a helpful hint directing users to exclude these classes using .doNotHaveModifier(JavaModifier.SYNTHETIC) or .areNotAnonymousClasses(). The implementation uses a custom ArchCondition that checks the failing object and appends the hint only when the condition fails on a synthetic or anonymous class, ensuring regular violations remain unchanged. Implementation details: - Checks both SYNTHETIC (compiler-generated, e.g., enum switch maps per JLS 13.1.7) and anonymous classes (both can cause unexpected naming violations) - Applies to haveSimpleNameStartingWith, haveSimpleNameContaining, and haveSimpleNameEndingWith methods - Fully compatible with Java 8-21 (all APIs available since Java 1.5) - Includes unit tests for anonymous classes and integration tests for synthetic classes Resolves: TNG#1509 Signed-off-by: chadongmin <[email protected]>
|
@hankem @codecholeric When you have time, I would appreciate your review of this PR. No rush at all—I know maintaining this project takes considerable effort. Thank you for all your work on ArchUnit! 😃 |
|
Thank you so much for your contribution and understanding, and apologies for missing your ping on the other issue! |
The synthetic class hint message was using hardcoded \n line separators, which caused test failures on Windows CI. Windows uses \r\n as line separator, but the test framework splits violation messages using System.lineSeparator(). This mismatch prevented proper message parsing and matching in integration tests. Changed SYNTHETIC_CLASS_HINT_MESSAGE from a static constant with hardcoded \n to a dynamic method getSyntheticClassHintMessage() that uses System.lineSeparator(). This ensures the hint message uses the correct platform-specific line separator, allowing tests to pass on all platforms (macOS, Linux, and Windows). Signed-off-by: chadongmin <[email protected]>
|
@hankem The issue was that the hint message was using hardcoded I fixed this by changing the hint message from a static constant to a method that dynamically uses All tests pass locally and I've run the full test suite with |
|
Hi @hankem , just wanted to let you know that all checks are passing now! Personally, I believe that developers shouldn't need to understand the internal behavior of the Java compiler to use this library. They simply expect ArchUnit to verify naming conventions on their source code, just as the rules imply. However, I value your insight as the maintainer. I'm curious to hear if you agree that this abstraction is meaningful for the project. Looking forward to your review! |
Description
Improves error messages when ArchUnit rules fail on synthetic or anonymous classes generated by the compiler. New users are often confused when rules fail on classes like
MyService$1that they didn't write, with no clear guidance on how to resolve the issue.Problem
As reported in #1509 and #1019, users encounter confusing error messages like:
This happens when the Java compiler generates synthetic classes for:
Users spend significant time debugging these "violations" even though they aren't actual architectural issues in their source code.
Solution
This PR adds helpful hints to error messages when rules fail on synthetic or anonymous classes:
Before:
After:
The hint only appears when relevant—regular class violations remain unchanged.
Implementation Details
Why Check Both SYNTHETIC and Anonymous?
Synthetic classes: Compiler-generated (e.g., enum switch maps defined in JLS 13.1.7)
ACC_SYNTHETICflag in bytecodeMyClass$1from enum switchesAnonymous classes: Explicitly created in source but may violate naming rules
isAnonymousClass()new Runnable() {}SYNTHETICcheck doesn't work butareNotAnonymousClasses()doesChanges Made
Core Implementation (
ArchConditions.java):haveWithHint()method that creates customArchConditionwith hint supportisSyntheticOrAnonymous()helper to detect both synthetic and anonymous classeshaveWithHint():haveSimpleNameStartingWith()haveSimpleNameContaining()haveSimpleNameEndingWith()Unit Tests (
ClassesShouldTest.java):NestedClassWithSomeMoreClasses.getAnonymousClass()for testingIntegration Tests:
ExpectedNaming.javato handle hint messagesExamplesIntegrationTest.javato include expected hint linesUseCaseOneThreeController$1(synthetic class from enum switch)Compatibility
isAnonymousClass()available since Java 1.5JavaModifier.SYNTHETICavailable since Java 1.5./gradlew clean build -PallTests✅ passesTesting
Test Coverage
BUILD SUCCESSFULwith all testsTest Results
Related Issues
Resolves #1509
Relates to #1019
Checklist
./gradlew clean build -PallTests)git commit -s)