• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.uber.nullaway.handlers.contract;
2 
3 import static com.uber.nullaway.Nullness.NONNULL;
4 import static com.uber.nullaway.Nullness.NULLABLE;
5 
6 import com.google.errorprone.util.ASTHelpers;
7 import com.sun.source.tree.ClassTree;
8 import com.sun.source.tree.MethodTree;
9 import com.sun.tools.javac.code.Symbol;
10 import com.sun.tools.javac.code.Types;
11 import com.sun.tools.javac.util.Context;
12 import com.uber.nullaway.Config;
13 import com.uber.nullaway.Nullness;
14 import com.uber.nullaway.dataflow.AccessPath;
15 import com.uber.nullaway.dataflow.NullnessStore;
16 import com.uber.nullaway.dataflow.NullnessStoreInitializer;
17 import com.uber.nullaway.handlers.Handler;
18 import java.util.List;
19 import javax.lang.model.element.Element;
20 import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST;
21 import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode;
22 
23 /**
24  * Nullness Store initializer in case of dataflow for contract check. The nullability of parameters
25  * in this case is determined from @Contract annotation.
26  */
27 public class ContractNullnessStoreInitializer extends NullnessStoreInitializer {
28 
29   @Override
getInitialStore( UnderlyingAST underlyingAST, List<LocalVariableNode> parameters, Handler handler, Context context, Types types, Config config)30   public NullnessStore getInitialStore(
31       UnderlyingAST underlyingAST,
32       List<LocalVariableNode> parameters,
33       Handler handler,
34       Context context,
35       Types types,
36       Config config) {
37     assert underlyingAST.getKind() == UnderlyingAST.Kind.METHOD;
38 
39     final MethodTree methodTree = ((UnderlyingAST.CFGMethod) underlyingAST).getMethod();
40     final ClassTree classTree = ((UnderlyingAST.CFGMethod) underlyingAST).getClassTree();
41     final Symbol.MethodSymbol callee = ASTHelpers.getSymbol(methodTree);
42     final String contractString = ContractUtils.getContractString(callee, config);
43 
44     assert contractString != null;
45 
46     String[] clauses = contractString.split(";");
47     String[] parts = clauses[0].split("->");
48     String[] antecedent = parts[0].split(",");
49 
50     NullnessStore envStore = getEnvNullnessStoreForClass(classTree, context);
51     NullnessStore.Builder result = envStore.toBuilder();
52 
53     for (int i = 0; i < antecedent.length; ++i) {
54       String valueConstraint = antecedent[i].trim();
55 
56       final LocalVariableNode param = parameters.get(i);
57       final Element element = param.getElement();
58 
59       Nullness assumed = NULLABLE;
60 
61       // There are 2 cases when we assume that the parameter is NONNULL
62       // 1. if the contract specifies it as (!null)
63       // 2. if there is no @nullable annotation to the parameter in the function signature
64       if (valueConstraint.equals("!null")
65           || !Nullness.hasNullableAnnotation((Symbol) element, config)) {
66         assumed = NONNULL;
67       }
68 
69       result.setInformation(AccessPath.fromLocal(param), assumed);
70     }
71 
72     return result.build();
73   }
74 }
75