|
3 | 3 | import checkers.inference.model.ConstraintManager; |
4 | 4 | import checkers.inference.model.SourceVariableSlot; |
5 | 5 | import checkers.inference.model.Slot; |
| 6 | + |
6 | 7 | import org.checkerframework.framework.type.AnnotatedTypeFactory; |
7 | 8 | import org.checkerframework.framework.type.AnnotatedTypeFactory.ParameterizedExecutableType; |
8 | 9 | import org.checkerframework.framework.type.AnnotatedTypeMirror; |
|
23 | 24 | import javax.lang.model.type.TypeKind; |
24 | 25 |
|
25 | 26 | import com.sun.source.tree.AnnotatedTypeTree; |
| 27 | +import com.sun.source.tree.AnnotationTree; |
26 | 28 | import com.sun.source.tree.AssignmentTree; |
27 | 29 | import com.sun.source.tree.BinaryTree; |
28 | 30 | import com.sun.source.tree.ClassTree; |
@@ -182,16 +184,28 @@ public Void visitIdentifier(IdentifierTree node, AnnotatedTypeMirror identifierT |
182 | 184 |
|
183 | 185 | } else if (parentNode.getKind() == Kind.NEW_CLASS |
184 | 186 | && ((NewClassTree) parentNode).getIdentifier() == node) { |
185 | | - // This can happen at two locations in a NewClassTree: |
186 | | - // (1) The type identifier of the NewClassTree, as `A` of `new A() {}`, |
187 | | - // (2) The type identifier on the anonymous class's extends/implements clause. |
188 | | - // Note that the identifiers trees described in the two cases above are identical |
189 | | - // for one NewClassTree, i.e. they share the same slot |
190 | | - // TODO: A NewClassTree should be handled in visitNewClass method exclusively |
| 187 | + // This can happen in two cases related to NewClassTrees: |
| 188 | + // (1) The type identifier of non-anonymous class instantiations, without explict |
| 189 | + // annotations, such as `A` of `new A()`; |
| 190 | + // (2) The type identifier of anonymous class instantiations, with or without |
| 191 | + // explicit annotations. |
| 192 | + // TODO: A NewClassTree should be handled in visitNewClass method exclusively |
191 | 193 | // without messing around with the IdentifierTree or ClassTree, see issue: |
192 | 194 | // https://github.com/opprop/checker-framework-inference/issues/332 |
193 | | - variableAnnotator.visit(identifierType, node); |
194 | 195 |
|
| 196 | + NewClassTree newClassTree = (NewClassTree) parentNode; |
| 197 | + if (newClassTree.getClassBody() != null) { |
| 198 | + // For case 2, get the explicit annotation if any exists so that no variable slot |
| 199 | + // is created. Note the annotation cannot be retrieved from the identifier, but |
| 200 | + // from the modifier of the anonymous class body. e.g. for the following case |
| 201 | + // new @HERE Class() {} |
| 202 | + // @HERE is on the modifier of the anonymous class body, instead of on the type identifier. |
| 203 | + List<? extends AnnotationTree> annos = |
| 204 | + newClassTree.getClassBody().getModifiers().getAnnotations(); |
| 205 | + identifierType.addAnnotations(TreeUtils.annotationsFromTypeAnnotationTrees(annos)); |
| 206 | + ((InferenceAnnotatedTypeFactory) atypeFactory).getConstantToVariableAnnotator().visit(identifierType); |
| 207 | + } |
| 208 | + variableAnnotator.visit(identifierType, node); |
195 | 209 | } |
196 | 210 | } |
197 | 211 | } |
|
0 commit comments