• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.uber.nullaway.handlers;
2 /*
3  * Copyright (c) 2017 Uber Technologies, Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE.
22  */
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.collect.ImmutableSet;
25 import com.google.errorprone.predicates.type.DescendantOf;
26 import com.google.errorprone.suppliers.Suppliers;
27 import com.uber.nullaway.handlers.stream.StreamModelBuilder;
28 import com.uber.nullaway.handlers.stream.StreamTypeRecord;
29 
30 public class StreamNullabilityPropagatorFactory {
getJavaStreamNullabilityPropagator()31   public static StreamNullabilityPropagator getJavaStreamNullabilityPropagator() {
32     ImmutableList<StreamTypeRecord> streamModels =
33         StreamModelBuilder.start()
34             .addStreamType(new DescendantOf(Suppliers.typeFromString("java.util.stream.Stream")))
35             // Names of all the methods of java.util.stream.Stream that behave like .filter(...)
36             // (must take exactly 1 argument)
37             .withFilterMethodFromSignature("filter(java.util.function.Predicate<? super T>)")
38             // Names and relevant arguments of all the methods of java.util.stream.Stream that
39             // behave
40             // like .map(...) for the purposes of this checker (the listed arguments are those that
41             // take the potentially filtered objects from the stream)
42             .withMapMethodFromSignature(
43                 "<R>map(java.util.function.Function<? super T,? extends R>)",
44                 "apply",
45                 ImmutableSet.of(0))
46             .withMapMethodFromSignature(
47                 "mapToInt(java.util.function.ToIntFunction<? super T>)",
48                 "applyAsInt",
49                 ImmutableSet.of(0))
50             .withMapMethodFromSignature(
51                 "mapToLong(java.util.function.ToLongFunction<? super T>)",
52                 "applyAsLong",
53                 ImmutableSet.of(0))
54             .withMapMethodFromSignature(
55                 "mapToDouble(java.util.function.ToDoubleFunction<? super T>)",
56                 "applyAsDouble",
57                 ImmutableSet.of(0))
58             .withMapMethodFromSignature(
59                 "forEach(java.util.function.Consumer<? super T>)", "accept", ImmutableSet.of(0))
60             .withMapMethodFromSignature(
61                 "forEachOrdered(java.util.function.Consumer<? super T>)",
62                 "accept",
63                 ImmutableSet.of(0))
64             .withMapMethodAllFromName("flatMap", "apply", ImmutableSet.of(0))
65             // List of methods of java.util.stream.Stream through which we just propagate the
66             // nullability information of the last call, e.g. m() in
67             // Observable.filter(...).m().map(...) means the
68             // nullability information from filter(...) should still be propagated to map(...),
69             // ignoring the interleaving call to m().
70             .withPassthroughMethodFromSignature("distinct()")
71             // List of methods of java.util.stream.Stream that both use the nullability information
72             // internally (like map does), but also don't change the values flowing through the
73             // stream
74             // and thus propagate
75             // the nullability information of the last call.
76             .end();
77     return new StreamNullabilityPropagator(streamModels);
78   }
79 
getRxStreamNullabilityPropagator()80   public static StreamNullabilityPropagator getRxStreamNullabilityPropagator() {
81     ImmutableList<StreamTypeRecord> rxModels =
82         StreamModelBuilder.start()
83             .addStreamType(new DescendantOf(Suppliers.typeFromString("io.reactivex.Observable")))
84             // Names of all the methods of io.reactivex.Observable that behave like .filter(...)
85             // (must take exactly 1 argument)
86             .withFilterMethodFromSignature("filter(io.reactivex.functions.Predicate<? super T>)")
87             // Names and relevant arguments of all the methods of io.reactivex.Observable that
88             // behave
89             // like .map(...) for the purposes of this checker (the listed arguments are those that
90             // take the potentially filtered objects from the stream)
91             .withMapMethodFromSignature(
92                 "<R>map(io.reactivex.functions.Function<? super T,? extends R>)",
93                 "apply",
94                 ImmutableSet.of(0))
95             .withMapMethodAllFromName("flatMap", "apply", ImmutableSet.of(0))
96             .withMapMethodAllFromName("flatMapSingle", "apply", ImmutableSet.of(0))
97             .withMapMethodFromSignature(
98                 "distinctUntilChanged(io.reactivex.functions.BiPredicate<? super T,? super T>)",
99                 "test",
100                 ImmutableSet.of(0, 1))
101             // List of methods of io.reactivex.Observable through which we just propagate the
102             // nullability information of the last call, e.g. m() in
103             // Observable.filter(...).m().map(...) means the
104             // nullability information from filter(...) should still be propagated to map(...),
105             // ignoring the interleaving call to m().
106             .withPassthroughMethodFromSignature("distinct()")
107             .withPassthroughMethodFromSignature("distinctUntilChanged()")
108             .withPassthroughMethodAllFromName("observeOn")
109             // List of methods of io.reactivex.Observable that both use the nullability information
110             // internally (like map does), but also don't change the values flowing through the
111             // stream
112             // and thus propagate
113             // the nullability information of the last call.
114             .withUseAndPassthroughMethodAllFromName("doOnNext", "accept", ImmutableSet.of(0))
115             .addStreamType(new DescendantOf(Suppliers.typeFromString("io.reactivex.Maybe")))
116             .withFilterMethodFromSignature("filter(io.reactivex.functions.Predicate<? super T>)")
117             .withMapMethodFromSignature(
118                 "<R>map(io.reactivex.functions.Function<? super T,? extends R>)",
119                 "apply",
120                 ImmutableSet.of(0))
121             .withMapMethodAllFromName("flatMap", "apply", ImmutableSet.of(0))
122             .withMapMethodAllFromName("flatMapSingle", "apply", ImmutableSet.of(0))
123             .withPassthroughMethodAllFromName("observeOn")
124             .withUseAndPassthroughMethodAllFromName("doOnNext", "accept", ImmutableSet.of(0))
125             .addStreamType(new DescendantOf(Suppliers.typeFromString("io.reactivex.Single")))
126             .withFilterMethodFromSignature("filter(io.reactivex.functions.Predicate<? super T>)")
127             .withMapMethodFromSignature(
128                 "<R>map(io.reactivex.functions.Function<? super T,? extends R>)",
129                 "apply",
130                 ImmutableSet.of(0))
131             .withMapMethodAllFromName("flatMap", "apply", ImmutableSet.of(0))
132             .withMapMethodAllFromName("flatMapSingle", "apply", ImmutableSet.of(0))
133             .withPassthroughMethodAllFromName("observeOn")
134             .withUseAndPassthroughMethodAllFromName("doOnNext", "accept", ImmutableSet.of(0))
135             .end();
136 
137     return new StreamNullabilityPropagator(rxModels);
138   }
139 }
140