@Override public Void visitNewClass(NewClassTree node, Void p) { AnnotatedDeclaredType type = atypeFactory.getAnnotatedType(node); ExpressionTree identifier = node.getIdentifier(); if (identifier instanceof AnnotatedTypeTree) { AnnotatedTypeTree t = (AnnotatedTypeTree) identifier; for (AnnotationMirror a : atypeFactory.getAnnotatedType(t).getAnnotations()) { // is this an annotation of the nullness checker? boolean nullnessCheckerAnno = containsSameIgnoringValues(atypeFactory.getNullnessAnnotations(), a); if (nullnessCheckerAnno && !AnnotationUtils.areSame(NONNULL, a)) { // The type is not non-null => warning checker.report(Result.warning("new.class.type.invalid", type.getAnnotations()), node); // Note that other consistency checks are made by isValid. } } if (t.toString().contains("@PolyNull")) { // TODO: this is a hack, but PolyNull gets substituted // afterwards checker.report(Result.warning("new.class.type.invalid", type.getAnnotations()), node); } } // TODO: It might be nicer to introduce a framework-level // isValidNewClassType or some such. return super.visitNewClass(node, p); }
private static List<? extends TypeMirror> computeNewClass( Set<ElementKind> types, CompilationInfo info, TreePath parent, Tree error, int offset) { NewClassTree nct = (NewClassTree) parent.getLeaf(); boolean errorInRealArguments = false; for (Tree param : nct.getArguments()) { errorInRealArguments |= param == error; } if (errorInRealArguments) { TypeMirror[] proposedType = new TypeMirror[1]; int[] proposedIndex = new int[1]; ExecutableElement ee = org.netbeans.modules.editor.java.Utilities.fuzzyResolveMethodInvocation( info, parent, proposedType, proposedIndex); if (ee == null) { // cannot be resolved return null; } types.add(ElementKind.PARAMETER); types.add(ElementKind.LOCAL_VARIABLE); types.add(ElementKind.FIELD); return Collections.singletonList(proposedType[0]); } Tree id = nct.getIdentifier(); if (id.getKind() == Kind.PARAMETERIZED_TYPE) { id = ((ParameterizedTypeTree) id).getType(); } if (id == error) { return resolveType( EnumSet.noneOf(ElementKind.class), info, parent.getParentPath(), nct, offset, null, null); } return null; }
@Override public Void visitNewClass(NewClassTree node, AnnotatedTypeMirror p) { super.visitNewClass(node, p); if (useFbc) { boolean allCommitted = true; Type type = ((JCTree) node).type; for (ExpressionTree a : node.getArguments()) { final AnnotatedTypeMirror t = getAnnotatedType(a); allCommitted &= (isCommitted(t) || isFbcBottom(t)); } if (!allCommitted) { p.replaceAnnotation(createFreeAnnotation(type)); } } return null; }
@Override public Void visitNewClass(NewClassTree tree, AnnotatedTypeMirror type) { boolean wrapperClass = TypesUtils.isBoxedPrimitive(type.getUnderlyingType()) || TypesUtils.isDeclaredOfName(type.getUnderlyingType(), "java.lang.String"); if (wrapperClass || (isUnderlyingTypeAValue(type) && methodIsStaticallyExecutable(TreeUtils.elementFromUse(tree)))) { // get arugment values List<? extends ExpressionTree> arguments = tree.getArguments(); ArrayList<List<?>> argValues; if (arguments.size() > 0) { argValues = new ArrayList<List<?>>(); for (ExpressionTree argument : arguments) { AnnotatedTypeMirror argType = getAnnotatedType(argument); List<?> values = getValues(argType, argType.getUnderlyingType()); if (values.isEmpty()) { // values aren't known, so don't try to evaluate the // method return null; } argValues.add(values); } } else { argValues = null; } // Evaluate method List<?> returnValues = evalutator.evaluteConstrutorCall(argValues, tree, type.getUnderlyingType()); AnnotationMirror returnType = resultAnnotationHandler(type.getUnderlyingType(), returnValues, tree); type.replaceAnnotation(returnType); } return null; }
private Pair<ParameterizedTypeTree, AnnotatedDeclaredType> extractParameterizedTypeTree( Tree tree, AnnotatedDeclaredType type) { ParameterizedTypeTree typeargtree = null; switch (tree.getKind()) { case VARIABLE: Tree lt = ((VariableTree) tree).getType(); if (lt instanceof ParameterizedTypeTree) { typeargtree = (ParameterizedTypeTree) lt; } else { // System.out.println("Found a: " + lt); } break; case PARAMETERIZED_TYPE: typeargtree = (ParameterizedTypeTree) tree; break; case NEW_CLASS: NewClassTree nct = (NewClassTree) tree; ExpressionTree nctid = nct.getIdentifier(); if (nctid.getKind() == Tree.Kind.PARAMETERIZED_TYPE) { typeargtree = (ParameterizedTypeTree) nctid; /* * This is quite tricky... for anonymous class instantiations, * the type at this point has no type arguments. By doing the * following, we get the type arguments again. */ type = (AnnotatedDeclaredType) atypeFactory.getAnnotatedType(typeargtree); } break; case ANNOTATED_TYPE: AnnotatedTypeTree tr = (AnnotatedTypeTree) tree; ExpressionTree undtr = tr.getUnderlyingType(); if (undtr instanceof ParameterizedTypeTree) { typeargtree = (ParameterizedTypeTree) undtr; } else if (undtr instanceof IdentifierTree) { // @Something D -> Nothing to do } else { // TODO: add more test cases to ensure that nested types are // handled correctly, // e.g. @Nullable() List<@Nullable Object>[][] Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(undtr, type); typeargtree = p.first; type = p.second; } break; case IDENTIFIER: case ARRAY_TYPE: case NEW_ARRAY: case MEMBER_SELECT: case UNBOUNDED_WILDCARD: case EXTENDS_WILDCARD: case SUPER_WILDCARD: case TYPE_PARAMETER: // Nothing to do. // System.out.println("Found a: " + (tree instanceof // ParameterizedTypeTree)); break; default: // the parameterized type is the result of some expression tree. // No need to do anything further. break; // System.err.printf("TypeValidator.visitDeclared unhandled tree: %s of kind %s\n", // tree, tree.getKind()); } return Pair.of(typeargtree, type); }