/* * Copyright (c) 2017 Uber Technologies, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.uber.nullaway.testdata; import android.webkit.WebView; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import java.io.File; import java.lang.ref.WeakReference; import java.net.URLClassLoader; import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import javax.annotation.Nullable; import javax.lang.model.element.Element; import javax.lang.model.util.Elements; public class NullAwayNativeModels { public static void referenceStuff() { AtomicReference<Object> ref = new AtomicReference<>(null); Object x = ref.get(); // BUG: Diagnostic contains: dereferenced expression x.toString(); // BUG: Diagnostic contains: dereferenced expression ref.get().toString(); WeakReference<Object> w = new WeakReference<Object>(x); // BUG: Diagnostic contains: dereferenced expression w.get().hashCode(); Exception e = new RuntimeException(); // BUG: Diagnostic contains: dereferenced expression e.getMessage().hashCode(); } // we will add bug annotations when we have full support for maps public static void mapStuff(Map<Object, Object> m) { // BUG: Diagnostic contains: dereferenced expression m.get(new Object()).toString(); Object value = m.get(new Object()); // BUG: Diagnostic contains: dereferenced expression value.toString(); HashMap<Object, Object> h = new HashMap<>(); Object value2 = h.get(new Object()); // BUG: Diagnostic contains: dereferenced expression value2.toString(); } static void mapGetNullCheck() { Object x = new Object(); Map<Object, Object> m = new HashMap<>(); if (m.get(x) != null) { m.get(x).toString(); } HashMap<Object, Object> m2 = (HashMap) m; if (m2.get(x) != null) { m2.get(x).hashCode(); } } static void mapContainsKeyCheck() { Object x = new Object(); Map<Object, Object> m = new HashMap<>(); if (m.containsKey(x)) { m.get(x).toString(); } if (m.containsKey(x)) { Object y = m.get(x); y.toString(); } HashMap<Object, Object> m2 = (HashMap) m; if (m2.containsKey(x)) { m2.get(x).hashCode(); } if (m2.containsKey(x)) { Object y = m2.get(x); y.hashCode(); } Object z = new Object(); if (m2.containsKey(z)) { // BUG: Diagnostic contains: dereferenced expression m2.get(x).hashCode(); } if (m2.containsKey(z)) { Object y = m2.get(x); // BUG: Diagnostic contains: dereferenced expression y.hashCode(); } // test negation if (!m2.containsKey(x)) { return; } Object y = m2.get(x); y.hashCode(); } static class Wrapper { Object wrapped = new Object(); public Object getWrapped() { return wrapped; } } static final String KEY = "key"; static void harderMapContainsKeyCheck() { Map m = new HashMap(); Wrapper w = new Wrapper(); if (m.containsKey(w.getWrapped())) { m.get(w.getWrapped()).toString(); } if (m.containsKey(w.getWrapped())) { Object o = m.get(w.getWrapped()); o.toString(); } if (m.get(w.getWrapped()) != null) { m.get(w.getWrapped()).toString(); } if (m.get(w.getWrapped()) != null) { Object o = m.get(w.getWrapped()); o.toString(); } if (m.containsKey(KEY)) { m.get(KEY).toString(); } if (m.containsKey(KEY)) { Object o = m.get(KEY); o.toString(); } } static void testLinkedHashMap() { LinkedHashMap m = new LinkedHashMap(); Object o = new Object(); if (m.containsKey(o)) { m.get(o).toString(); } } static void mapContainsKeyPut() { Object x = new Object(); Map<Object, Object> m = new HashMap<>(); if (!m.containsKey(x)) { m.put(x, new Object()); } m.get(x).toString(); HashMap<Object, Object> m2 = new HashMap<>(); if (!m2.containsKey(x)) { m2.put(x, x); } m2.get(x).toString(); Object y = new Object(), z = new Object(); if (!m2.containsKey(z)) { m2.put(y, new Object()); } // BUG: Diagnostic contains: dereferenced expression m2.get(z).toString(); LinkedHashMap m3 = new LinkedHashMap(); if (!m3.containsKey(y)) { m3.put(y, new Object()); } m3.get(y).hashCode(); } static void immutableMapStuff() { ImmutableMap m = ImmutableMap.of(); Object res = m.get(new Object()); // BUG: Diagnostic contains: dereferenced expression res.toString(); Object x = new Object(); if (m.containsKey(x)) { m.get(x).toString(); } } static void failIfNull( @Nullable Object o1, @Nullable Object o2, @Nullable Object o3, @Nullable Object o4, @Nullable Object o5) { org.junit.Assert.assertNotNull(o1); o1.toString(); org.junit.Assert.assertNotNull("Null!", o2); o2.toString(); org.junit.jupiter.api.Assertions.assertNotNull(o3); o3.toString(); org.junit.jupiter.api.Assertions.assertNotNull(o4, "Null!"); o4.toString(); org.junit.jupiter.api.Assertions.assertNotNull(o5, () -> "Null!"); o5.toString(); } static void nonNullParameters() { // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required NullAwayNativeModels.class.getResource(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required NullAwayNativeModels.class.isAssignableFrom(null); String s = null; // BUG: Diagnostic contains: passing @Nullable parameter 's' where @NonNull is required File f = new File(s); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required URLClassLoader.newInstance(null, NullAwayNativeModels.class.getClassLoader()); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required Optional<Object> op = Optional.of(null); } static void elementStuff(Element e, Elements elems) { // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required e.getAnnotation(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required elems.getPackageElement(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required elems.getTypeElement(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required elems.getDocComment(null); } static void arrayDequeStuff() { ArrayDeque<Object> d = new ArrayDeque<>(); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.add(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.addFirst(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.addLast(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offerFirst(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offerLast(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offer(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.push(null); Object[] o = null; // BUG: Diagnostic contains: passing @Nullable parameter 'o' where @NonNull is required d.toArray(o); // this should be fine d.toArray(); } static void dequeStuff() { Deque<Object> d = new ArrayDeque<>(); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.add(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.addFirst(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.addLast(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offerFirst(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offerLast(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.offer(null); // BUG: Diagnostic contains: passing @Nullable parameter 'null' where @NonNull is required d.push(null); Object[] o = null; // BUG: Diagnostic contains: passing @Nullable parameter 'o' where @NonNull is required d.toArray(o); } static void guavaStuff() { Collection<String> c = null; Object o = null; // BUG: Diagnostic contains: passing @Nullable parameter 'c' where @NonNull is required ImmutableList.builder().addAll(c).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'o' where @NonNull is required ImmutableList.builder().add(o).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'c' where @NonNull is required ImmutableSet.builder().addAll(c).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'o' where @NonNull is required ImmutableSet.builder().add(o).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'c' where @NonNull is required ImmutableSortedSet.builder().addAll(c).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'o' where @NonNull is required ImmutableSortedSet.builder().add(o).build(); // BUG: Diagnostic contains: passing @Nullable parameter 'c' where @NonNull is required Iterables.getFirst(c, "hi"); } static void androidStuff() { android.webkit.WebView webView = new WebView(); // BUG: Diagnostic contains: dereferenced expression webView.getUrl().toString(); String s = null; if (!android.text.TextUtils.isEmpty(s)) { // no warning due to isEmpty check s.hashCode(); } } static void apacheCommonsStuff() { String s = null; if (!org.apache.commons.lang.StringUtils.isEmpty(s)) { // no warning due to isEmpty check s.hashCode(); } String t = null; if (!org.apache.commons.lang3.StringUtils.isEmpty(t)) { // no warning due to isEmpty check t.hashCode(); } } }