File: KeyFors.java

package info (click to toggle)
checker-framework-java 3.2.0%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,104 kB
  • sloc: java: 145,916; xml: 839; sh: 518; makefile: 404; perl: 26
file content (129 lines) | stat: -rw-r--r-- 4,212 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.*;

public class KeyFors {

    public void withoutKeyFor() {
        Map<String, String> map = new HashMap<>();
        String key = "key";

        // :: error: (assignment.type.incompatible)
        @NonNull String value = map.get(key);
    }

    public void withKeyFor() {
        Map<String, String> map = new HashMap<>();
        @SuppressWarnings("assignment.type.incompatible")
        @KeyFor("map") String key = "key";

        @NonNull String value = map.get(key);
    }

    public void withCollection() {
        Map<String, String> map = new HashMap<>();
        List<@KeyFor("map") String> keys = new ArrayList<>();

        @KeyFor("map") String key = keys.get(0);
        @NonNull String value = map.get(key);
        value = map.get(keys.get(0));
    }

    public void withIndirectReference() {
        class Container {
            Map<String, String> map = new HashMap<>();
        }

        Container container = new Container();
        @SuppressWarnings("assignment.type.incompatible")
        @KeyFor("container.map") String key = "m";

        @NonNull String value = container.map.get(key);
    }

    /** Returns a sorted version of m.keySet(). */
    public static <K extends Comparable<? super K>, V> Collection<@KeyFor("#1") K> sortedKeySet(
            Map<K, V> m) {
        throw new RuntimeException();
    }

    static HashMap<Integer, Object> call_hashmap = new HashMap<>();

    public void testForLoop(HashMap<String, String> lastMap) {
        Collection<@KeyFor("lastMap") String> sorted = sortedKeySet(lastMap);
        for (@KeyFor("lastMap") String key : sorted) {
            @NonNull String al = lastMap.get(key);
        }
        for (@KeyFor("call_hashmap") Integer i : sortedKeySet(call_hashmap)) {}
    }

    static class Otherclass {
        static Map<String, String> map = new HashMap<>();
    }

    public void testStaticKeyFor(@KeyFor("Otherclass.map") String s1, String s2) {
        Otherclass.map.get(s1).toString();
        // :: error: (dereference.of.nullable)
        Otherclass.map.get(s2).toString();

        Otherclass o = new Otherclass();
        o.map.get(s1).toString();
        // TODO:: error: (dereference.of.nullable)
        o.map.get(s2).toString();
    }

    public class Graph<T> {

        HashMap<T, List<@KeyFor("childMap") T>> childMap;

        public Graph(HashMap<T, List<@KeyFor("childMap") T>> childMap) {
            this.childMap = childMap;
        }

        public void addNode(T n) {
            // body omitted, not relevant to test case
        }

        public void addEdge2(T parent, T child) {
            addNode(parent);
            @SuppressWarnings("cast.unsafe")
            @KeyFor("childMap") T parent2 = (@KeyFor("childMap") T) parent;
            @NonNull List<@KeyFor("childMap") T> l = childMap.get(parent2);
        }

        // TODO: This is a feature request to have KeyFor inferred
        //    public void addEdge3( T parent, T child ) {
        //      addNode(parent);
        //      parent = (@KeyFor("childMap") T) parent;
        //      @NonNull List<T> l = childMap.get(parent);
        //    }

    }

    /* TODO: add logic that after a call to "put" the first argument is
    annotated with @KeyFor. A "@KeyForAfter" annotation to
    support this in a general way might be overkill.
    Similarly, for calls to "remove" we need to invalidate all (?)
    KeyFor annotations.*/

    void keyForFlow() {
        Map<String, String> leaders = new LinkedHashMap<>();
        Set<@KeyFor("leaders") String> varsUsedPreviously =
                new LinkedHashSet<@KeyFor("leaders") String>();
        String varName = "hello";
        leaders.put(varName, "goodbye");
        @KeyFor("leaders") String kf = varName;
    }

    public static void mapPut(String start) {
        Map<String, Integer> n2e = new HashMap<>();
        n2e.put(start, Integer.valueOf(0));
        @KeyFor("n2e") String start2 = start;
    }
}