What is the Eclipse External Annotation Format for Static Inner Classes?

368 views Asked by At

I am trying to write an Eclipse External Annotation file for the static inner class Map.Entry. How do I do this?

I created a file named Map$Entry.eea in the java/util sub-folder under the folder where all of my External Annotation files are located. Here are the contents of that file.

class java/util/Map$Entry

comparingByKey
 <K::Ljava/lang/Comparable<-TK;>;V:Ljava/lang/Object;>()Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
 <K::Ljava/lang/Comparable<-TK;>;V:Ljava/lang/Object;>()L1java/util/Comparator<L1java/util/Map$Entry<T1K;TV;>;>;

comparingByKey
 <K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Comparator<-TK;>;)Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
 <K:Ljava/lang/Object;V:Ljava/lang/Object;>(L1java/util/Comparator<-TK;>;)L1java/util/Comparator<L1java/util/Map$Entry<TK;TV;>;>;

comparingByValue
 <K:Ljava/lang/Object;V::Ljava/lang/Comparable<-TV;>;>()Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
 <K:Ljava/lang/Object;V::Ljava/lang/Comparable<-TV;>;>()L1java/util/Comparator<L1java/util/Map$Entry<TK;T1V;>;>;

comparingByValue
 <K:Ljava/lang/Object;V:Ljava/lang/Object;>(Ljava/util/Comparator<-TV;>;)Ljava/util/Comparator<Ljava/util/Map$Entry<TK;TV;>;>;
 <K:Ljava/lang/Object;V:Ljava/lang/Object;>(L1java/util/Comparator<-TV;>;)L1java/util/Comparator<L1java/util/Map$Entry<TK;TV;>;>;

equals
 (Ljava/lang/Object;)Z
 (L0java/lang/Object;)Z

getKey
 ()TK;
 ()TK;

getValue
 ()TV;
 ()TV;

setValue
 (TV;)TV;
 (TV;)TV;

Eclipse still flags a warning on entry.getValue() in the following code:

Map.Entry<@Nullable String, @NonNull Object> entry;
@NonNull Object value = entry.getValue();

The warning is:

Unsafe interpretation of method return type as '@NonNull' based on the receiver type
'Map.<@NonNull Entry<@Nullable String, @NonNull Object>>'. Type Map.Entry<K, V> doesn't seem
to be designed with null type annotations in mind.
2

There are 2 answers

0
Nathan On

Upgrading to Eclipse Oxygen (4.7.0) build 20170620-1800 resolved the problem. Map$Entry.eea can be left as is in the question and the compiler warnings happen at the appropriate times. If the Map.Entry V is @NonNull in code, then getValue()'s return type is @NonNull. If the Map.Entry V is @Nullable in code, then getValue()'s return type is @Nullable.

The code in the question no longer causes a compiler warning. The following code does (which is expected and desired).

Map.Entry<@NonNull String, @Nullable Object> entry;
...
entry.getValue().toString();
3
howlger On

The second line after getValue must be ()T1V; instead of ()TV; for @NonNull:

class java/util/Map$Entry
getValue
 ()TV;
 ()T1V;

For @Nullable it would be ()T0V;

But because the value of a map entry can be null ("it's also possible that the map explicitly maps the key to null"), there should only be a warning at @NonNull Object value = entry.getValue(); if the type of entry is Map.Entry<String, @Nullable Object> but not if the type is Map.Entry<String, @NonNull Object>. To tell Eclipse that Map.Entry is designed with null type annotations in mind the java/util/Map$Entry.eea file must be almost empty:

class java/util/Map$Entry

But be careful, if you do the same for Map then there would be no warning for @NonNull Object o = map.get("foo");. You have to annotate all @Nullable type parameters explicitly:

class java/util/Map
get
 (Ljava/lang/Object;)TV;
 (Ljava/lang/Object;)T0V;

See also: Eclipse 4.6 New and Noteworthy - Improved null analysis with generics