Exemplo n.º 1
0
 @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);
 }
 @Override
 public Void visitExecutable(AnnotatedExecutableType t, Void p) {
   Void result = super.visitExecutable(t, p);
   Element elem = t.getElement();
   if (elem.getKind() == ElementKind.CONSTRUCTOR) {
     AnnotatedDeclaredType returnType = (AnnotatedDeclaredType) t.getReturnType();
     DeclaredType underlyingType = returnType.getUnderlyingType();
     returnType.replaceAnnotation(getFreeOrRawAnnotationOfSuperType(underlyingType));
   }
   return result;
 }
  /**
   * Checks that the annotations on the type arguments supplied to a type or a method invocation are
   * within the bounds of the type variables as declared, and issues the
   * "type.argument.type.incompatible" error if they are not.
   *
   * <p>This method used to be visitParameterizedType, which incorrectly handles the main annotation
   * on generic types.
   */
  protected Void visitParameterizedType(AnnotatedDeclaredType type, ParameterizedTypeTree tree) {
    // System.out.printf("TypeValidator.visitParameterizedType: type: %s, tree: %s\n",
    // type, tree);

    if (TreeUtils.isDiamondTree(tree)) return null;

    final TypeElement element = (TypeElement) type.getUnderlyingType().asElement();
    if (checker.shouldSkipUses(element)) return null;

    List<AnnotatedTypeVariable> typevars = atypeFactory.typeVariablesFromUse(type, element);

    visitor.checkTypeArguments(tree, typevars, type.getTypeArguments(), tree.getTypeArguments());

    return null;
  }
Exemplo n.º 4
0
  @Override
  public boolean isValidUse(
      AnnotatedDeclaredType declarationType, AnnotatedDeclaredType useType, Tree tree) {
    // At most a single qualifier on a type, ignoring a possible PolyAll
    // annotation.
    boolean foundInit = false;
    boolean foundNonNull = false;
    Set<Class<? extends Annotation>> initQuals = atypeFactory.getInitializationAnnotations();
    Set<Class<? extends Annotation>> nonNullQuals = atypeFactory.getNullnessAnnotations();

    for (AnnotationMirror anno : useType.getAnnotations()) {
      if (QualifierPolymorphism.isPolyAll(anno)) {
        // ok.
      } else if (containsSameIgnoringValues(initQuals, anno)) {
        if (foundInit) {
          return false;
        }
        foundInit = true;
      } else if (containsSameIgnoringValues(nonNullQuals, anno)) {
        if (foundNonNull) {
          return false;
        }
        foundNonNull = true;
      }
    }

    if (tree.getKind() == Tree.Kind.VARIABLE) {
      Element vs = InternalUtils.symbol(tree);
      switch (vs.getKind()) {
        case EXCEPTION_PARAMETER:
          if (useType.hasAnnotation(NULLABLE)) {
            // Exception parameters cannot use Nullable
            // annotations. They default to NonNull.
            return false;
          }
          break;
        default:
          // nothing to do
          break;
      }
    }

    // The super implementation checks that useType is a subtype
    // of declarationType. However, declarationType by default
    // is NonNull, which would then forbid Nullable uses.
    // Therefore, don't perform this check.
    return true;
  }
  protected void setSelfTypeInInitializationCode(
      Tree tree, AnnotatedDeclaredType selfType, TreePath path) {
    ClassTree enclosingClass = TreeUtils.enclosingClass(path);
    Type classType = ((JCTree) enclosingClass).type;
    AnnotationMirror annotation = null;

    // If all fields are committed-only, and they are all initialized,
    // then it is save to switch to @UnderInitialization(CurrentClass).
    if (areAllFieldsCommittedOnly(enclosingClass)) {
      Store store = getStoreBefore(tree);
      if (store != null) {
        List<AnnotationMirror> annos = Collections.emptyList();
        if (getUninitializedInvariantFields(store, path, false, annos).size() == 0) {
          if (useFbc) {
            annotation = createFreeAnnotation(classType);
          } else {
            annotation = createUnclassifiedAnnotation(classType);
          }
        }
      }
    }

    if (annotation == null) {
      annotation = getFreeOrRawAnnotationOfSuperType(classType);
    }
    selfType.replaceAnnotation(annotation);
  }
 @Override
 public R visitDeclared(AnnotatedDeclaredType type, P p) {
   if (visitedNodes.containsKey(type)) {
     return visitedNodes.get(type);
   }
   visitedNodes.put(type, null);
   R r = scan(type.getTypeArguments(), p);
   return r;
 }
  /** Adds extends/implements and class annotations to type. Annotates type parameters. */
  @Override
  public void extractAndApply() {
    // ensures that we check that there only valid target types on this class, there are no
    // "targeted" locations
    super.extractAndApply();

    // Annotate raw types //TODO: ASK WERNER WHAT THIS MIGHT MEAN?  WHAT ACTUALLY GOES HERE?
    type.addAnnotations(typeSymbol.getAnnotationMirrors());

    applyAllElementAnnotations(
        declaredType.getTypeArguments(), typeSymbol.getTypeParameters(), typeFactory);
  }
  @Override
  public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
    if (checker.shouldSkipUses(type.getUnderlyingType().asElement()))
      return super.visitDeclared(type, tree);

    {
      // Ensure that type use is a subtype of the element type
      // isValidUse determines the erasure of the types.
      AnnotatedDeclaredType elemType =
          (AnnotatedDeclaredType)
              atypeFactory.getAnnotatedType(type.getUnderlyingType().asElement());

      if (!visitor.isValidUse(elemType, type, tree)) {
        reportError(type, tree);
      }
    }

    // System.out.println("Type: " + type);
    // System.out.println("Tree: " + tree);
    // System.out.println("Tree kind: " + tree.getKind());

    /*
     * Try to reconstruct the ParameterizedTypeTree from the given tree.
     * TODO: there has to be a nicer way to do this...
     */
    Pair<ParameterizedTypeTree, AnnotatedDeclaredType> p = extractParameterizedTypeTree(tree, type);
    ParameterizedTypeTree typeargtree = p.first;
    type = p.second;

    if (typeargtree != null) {
      // We have a ParameterizedTypeTree -> visit it.

      visitParameterizedType(type, typeargtree);

      /*
       * Instead of calling super with the unchanged "tree", adapt the
       * second argument to be the corresponding type argument tree. This
       * ensures that the first and second parameter to this method always
       * correspond. visitDeclared is the only method that had this
       * problem.
       */
      List<? extends AnnotatedTypeMirror> tatypes = type.getTypeArguments();

      if (tatypes == null) return null;

      // May be zero for a "diamond" (inferred type args in constructor
      // invocation).
      int numTypeArgs = typeargtree.getTypeArguments().size();
      if (numTypeArgs != 0) {
        // TODO: this should be an equality, but in
        // http://buffalo.cs.washington.edu:8080/job/jdk6-daikon-typecheck/2061/console
        // it failed with:
        // daikon/Debug.java; message: size mismatch for type arguments:
        // @NonNull Object and Class<?>
        // but I didn't manage to reduce it to a test case.
        assert tatypes.size() <= numTypeArgs
            : "size mismatch for type arguments: " + type + " and " + typeargtree;

        for (int i = 0; i < tatypes.size(); ++i) {
          scan(tatypes.get(i), typeargtree.getTypeArguments().get(i));
        }
      }

      return null;

      // Don't call the super version, because it creates a mismatch
      // between
      // the first and second parameters.
      // return super.visitDeclared(type, tree);
    }

    return super.visitDeclared(type, tree);
  }