TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.13k stars 284 forks source link

DEPRECATED_API_SHOULD_NOT_BE_USED does not consider constants nor final fields #1272

Closed mkjensen closed 3 months ago

mkjensen commented 3 months ago

DEPRECATED_API_SHOULD_NOT_BE_USED does not consider constants.

For example, referring to

@Deprecated
static final int CONSTANT = 42;

is not considered a violation.

I extended GeneralCodingRulesTest to demonstrate the issue: https://github.com/TNG/ArchUnit/compare/main...mkjensen:ArchUnit:constant-final-field-deprecated

It seems like refering to a final field is also not considered a violation. However, the test class used to demonstrate the issue is considered to refer to a deprecated final field when the field is initialized:

"Constructor <com.tngtech.archunit.library.GeneralCodingRulesTest$1ClassWithDeprecatedMembers.<init>(com.tngtech.archunit.library.GeneralCodingRulesTest)> sets field <com.tngtech.archunit.library.GeneralCodingRulesTest$1ClassWithDeprecatedMembers.finalTarget> in (GeneralCodingRulesTest.java:131)"
rweisleder commented 3 months ago

This is a limitation of ArchUnit, because it only depends on the bytecode. Compile-time constants like static final int are inlined during compilation. The compiled bytecode contains the exact value of CONSTANT. There remains no reference to this field in the bytecode. Therefore, ArchUnit cannot see the usage of deprecated API. It's called The Static Final Inline Trap.

I have to say that I haven't tried with non-static fields yet. But from my point of view, they are also compile-time constants. So I wouldn't be surprised if they are also inlined. On the other hand, the rule should work with non-primitive fields.

mkjensen commented 3 months ago

Thank you for the explanation, @rweisleder. That (unfortunately) makes sense.