|
43 | 43 | import com.uber.nullaway.handlers.MethodAnalysisContext;
|
44 | 44 | import com.uber.nullaway.handlers.contract.ContractUtils;
|
45 | 45 | import java.util.Collections;
|
| 46 | +import java.util.HashSet; |
46 | 47 | import java.util.Iterator;
|
47 | 48 | import java.util.List;
|
48 | 49 | import java.util.Set;
|
| 50 | +import javax.lang.model.element.Element; |
| 51 | +import javax.lang.model.element.Modifier; |
49 | 52 | import javax.lang.model.element.VariableElement;
|
50 | 53 | import org.checkerframework.nullaway.dataflow.cfg.UnderlyingAST;
|
51 | 54 | import org.checkerframework.nullaway.dataflow.cfg.node.LocalVariableNode;
|
@@ -145,11 +148,35 @@ public void onMatchMethodInvocation(
|
145 | 148 | Symbol.ClassSymbol classSymbol = ASTHelpers.enclosingClass(methodSymbol);
|
146 | 149 | Preconditions.checkNotNull(
|
147 | 150 | classSymbol, "Could not find the enclosing class for method symbol: " + methodSymbol);
|
148 |
| - VariableElement field = getInstanceFieldOfClass(classSymbol, fieldName); |
| 151 | + VariableElement field = getFieldOfClass(classSymbol, fieldName); |
149 | 152 | if (field == null) {
|
150 | 153 | // we will report an error on the method declaration
|
151 | 154 | continue;
|
152 | 155 | }
|
| 156 | + if (field.getModifiers().contains(Modifier.STATIC)) { |
| 157 | + Set<Element> nonnullStaticFields = |
| 158 | + analysis |
| 159 | + .getNullnessAnalysis(state) |
| 160 | + .getNonnullStaticFieldsBefore(state.getPath(), state.context); |
| 161 | + |
| 162 | + if (!nonnullStaticFields.contains(field)) { |
| 163 | + String message = |
| 164 | + "Expected static field " |
| 165 | + + fieldName |
| 166 | + + " to be non-null at call site due to @RequiresNonNull annotation on invoked method"; |
| 167 | + state.reportMatch( |
| 168 | + analysis |
| 169 | + .getErrorBuilder() |
| 170 | + .createErrorDescription( |
| 171 | + new ErrorMessage( |
| 172 | + ErrorMessage.MessageTypes.PRECONDITION_NOT_SATISFIED, message), |
| 173 | + tree, |
| 174 | + analysis.buildDescription(tree), |
| 175 | + state, |
| 176 | + null)); |
| 177 | + } |
| 178 | + continue; |
| 179 | + } |
153 | 180 | ExpressionTree methodSelectTree = tree.getMethodSelect();
|
154 | 181 | Nullness nullness =
|
155 | 182 | analysis
|
@@ -195,14 +222,23 @@ public NullnessStore.Builder onDataflowInitialStore(
|
195 | 222 | if (fieldNames == null) {
|
196 | 223 | return result;
|
197 | 224 | }
|
198 |
| - fieldNames = ContractUtils.trimReceivers(fieldNames); |
| 225 | + Set<String> filteredFieldNames = new HashSet<>(); |
199 | 226 | for (String fieldName : fieldNames) {
|
200 |
| - VariableElement field = getInstanceFieldOfClass(ASTHelpers.getSymbol(classTree), fieldName); |
| 227 | + if (!isThisDotStaticField(ASTHelpers.getSymbol(classTree), fieldName)) { |
| 228 | + filteredFieldNames.add(fieldName); |
| 229 | + } |
| 230 | + } |
| 231 | + filteredFieldNames = ContractUtils.trimReceivers(filteredFieldNames); |
| 232 | + for (String fieldName : filteredFieldNames) { |
| 233 | + VariableElement field = getFieldOfClass(ASTHelpers.getSymbol(classTree), fieldName); |
201 | 234 | if (field == null) {
|
202 | 235 | // Invalid annotation, will result in an error during validation. For now, skip field.
|
203 | 236 | continue;
|
204 | 237 | }
|
205 |
| - AccessPath accessPath = AccessPath.fromFieldElement(field); |
| 238 | + AccessPath accessPath = |
| 239 | + field.getModifiers().contains(Modifier.STATIC) |
| 240 | + ? AccessPath.fromStaticField(field) |
| 241 | + : AccessPath.fromFieldElement(field); |
206 | 242 | result.setInformation(accessPath, Nullness.NONNULL);
|
207 | 243 | }
|
208 | 244 | return result;
|
|
0 commit comments