1 package com.uber.nullaway.dataflow; 2 3 import com.google.common.base.Preconditions; 4 import com.google.errorprone.util.ASTHelpers; 5 import com.sun.source.tree.ClassTree; 6 import com.sun.source.tree.LambdaExpressionTree; 7 import com.sun.source.tree.Tree; 8 import com.sun.tools.javac.util.Context; 9 import java.util.LinkedHashMap; 10 import java.util.Map; 11 import javax.annotation.Nullable; 12 import javax.lang.model.element.NestingKind; 13 14 /** 15 * Stores info on nullness of local variables in enclosing environments, used when performing 16 * dataflow analysis on lambdas or methods in anonymous classes that may access these locals 17 */ 18 public class EnclosingEnvironmentNullness { 19 20 public static final Context.Key<EnclosingEnvironmentNullness> 21 ENCLOSING_ENVIRONMENT_NULLNESS_ANALYSIS_KEY = new Context.Key<>(); 22 23 private final Map<Tree, NullnessStore> environmentNullness = new LinkedHashMap<>(); 24 instance(Context context)25 public static EnclosingEnvironmentNullness instance(Context context) { 26 EnclosingEnvironmentNullness instance = 27 context.get(ENCLOSING_ENVIRONMENT_NULLNESS_ANALYSIS_KEY); 28 if (instance == null) { 29 instance = new EnclosingEnvironmentNullness(); 30 context.put(ENCLOSING_ENVIRONMENT_NULLNESS_ANALYSIS_KEY, instance); 31 } 32 return instance; 33 } 34 addEnvironmentMapping(Tree t, NullnessStore s)35 public void addEnvironmentMapping(Tree t, NullnessStore s) { 36 Preconditions.checkArgument(isValidTreeType(t), "cannot store environment for node " + t); 37 environmentNullness.put(t, s); 38 } 39 40 @Nullable getEnvironmentMapping(Tree t)41 public NullnessStore getEnvironmentMapping(Tree t) { 42 Preconditions.checkArgument(isValidTreeType(t)); 43 return environmentNullness.get(t); 44 } 45 clear()46 public void clear() { 47 environmentNullness.clear(); 48 } 49 50 /** Is t an anonymous inner class or a lambda? */ isValidTreeType(Tree t)51 private boolean isValidTreeType(Tree t) { 52 if (t instanceof LambdaExpressionTree) { 53 return true; 54 } 55 if (t instanceof ClassTree) { 56 NestingKind nestingKind = ASTHelpers.getSymbol((ClassTree) t).getNestingKind(); 57 return nestingKind.equals(NestingKind.ANONYMOUS) || nestingKind.equals(NestingKind.LOCAL); 58 } 59 return false; 60 } 61 } 62