S1874 should consider @Deprecated annotations on package-info.java

java:S1874 ensures that code marked as "@Deprecated” should not be used.

However, (at least in SonarQube 9.9 LTA, which we are still using) it currently does not seem to consider package-level deprecations.

In Java, it is possible to apply an annotation to a package-info.java file to make it apply to all classes in that package. At least the Eclipse compiler would put a warning for these classes and calls as deprecated (albeit not strike-through, as it does with explicit deprecations), but SonarLint and IntelliJ don’t seem to do the same.

Still, it may be worth considering to treat classes from deprecated packages the same as if they were deprecated themselves.

Example:

src/main/java/com/acme/deprecationtest/package-info.java

/**
 * @deprecated We no longer use the classes from this package.
 */
@Deprecated
package com.acme.deprecationtest;

src/main/java/com/acme/deprecationtest/MyOldFoo.java

package com.acme.deprecationtest;

public class MyOldFoo {
  // empty
}

src/main/java/com/acme/SomeOtherService

package com.acme;

import com.acme.deprecationtest.MyOldFoo;

public class SomeOtherService {
  public void baz() {
    MyOldFoo foo = new MyOldFoo();  // FALSE-NEGATIVE: Should be marked as deprecated.
  }
}

Bonus points if the rule message points out that the package is deprecated and not the class, so the developer is not wondering why they cannot find the annotation on the class.

Also, it may be a good idea to make java:S1123 (Deprecated elements should have both the annotation and the Javadoc tag) also check the package-info.java as well?

Hmm, looking at these JDK bug reports, using the @Deprecated annotation on a package does not actually seem to be intended according to the JLS and is only still possible for backwards compatibility reasons. So it seems the Eclipse compiler is actually in the wrong here for interpreting it that way.

JDK-8245664
JDK-8160601
JDK-8141099

So I guess this topic is moot.

1 Like