CallToDeprecatedMethod issues with generic constructor args

java

(Brian Farrell) #1

I noticed this with version 5.9.2 of the sonar-java plugin.

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UsesDeprecations {

  public static void test() {
    new HasDeprecations(new ArrayList<>());
    new HasDeprecations(new HashMap<>());
  }

  static class HasDeprecations {
    @Deprecated
    public HasDeprecations(final Map<String, String> m) {}

    public HasDeprecations(final List<String> l) {}
  }
}

Both constructor calls are marked with Remove this use of “HasDeprecations”; it is deprecated. despite only one being deprecated. If I switch which constructor has the @Deprecated annotation, then neither call is detected as deprecated.

I actually ran into this while developing a custom rule that is very similar to CallToDeprecatedMethod, so if there are any workarounds that I can implement in a custom rule I’d be interested to hear them.


(Brian Farrell) #2

I noticed if I change the line to
new HasDeprecations(new ArrayList());
or
new HasDeprecations(new ArrayList<String>());
the false-positive HasDeprecations violation goes away. It seems to be specific to the diamond <> operator.

Any ideas?


(Brian Farrell) #3

Looks like this doesn’t just affect constructors, but methods as well. This code shows the same issue:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UsesDeprecations {

  public static void test() {
    HasDeprecations.method(new ArrayList<>());
    HasDeprecations.method(new HashMap<>());
  }

  static class HasDeprecations {
    @Deprecated
    public static void method(final Map<String, String> m) {}

    public static void method(final List<String> l) {}
  }
}

If the first method is @Deprecated, both calls are marked by CallToDeprecatedMethod (one false positive). If the second method is @Deprecated, neither is marked by CallToDeprecatedMethod (one false negative).