@Override
    public Void visitMemberSelect(MemberSelectTree tree, AnnotatedTypeMirror type) {
      if (TreeUtils.isFieldAccess(tree) && isUnderlyingTypeAValue(type)) {
        VariableElement elem = (VariableElement) InternalUtils.symbol(tree);
        Object value = elem.getConstantValue();
        if (value != null) {
          // compile time constant
          type.replaceAnnotation(
              resultAnnotationHandler(
                  type.getUnderlyingType(), Collections.singletonList(value), tree));
          return null;
        }
        if (ElementUtils.isStatic(elem) && ElementUtils.isFinal(elem)) {
          Element e = InternalUtils.symbol(tree.getExpression());
          if (e != null) {
            String classname = ElementUtils.getQualifiedClassName(e).toString();
            String fieldName = tree.getIdentifier().toString();
            value = evalutator.evaluateStaticFieldAccess(classname, fieldName, tree);
            if (value != null)
              type.replaceAnnotation(
                  resultAnnotationHandler(
                      type.getUnderlyingType(), Collections.singletonList(value), tree));
            return null;
          }
        }

        if (tree.getIdentifier().toString().equals("length")) {
          AnnotatedTypeMirror receiverType = getAnnotatedType(tree.getExpression());
          if (receiverType.getKind() == TypeKind.ARRAY) {
            AnnotationMirror arrayAnno = receiverType.getAnnotation(ArrayLen.class);
            if (arrayAnno != null) {
              // array.length, where array : @ArrayLen(x)
              List<Integer> lengths = ValueAnnotatedTypeFactory.getArrayLength(arrayAnno);
              type.replaceAnnotation(createNumberAnnotationMirror(new ArrayList<Number>(lengths)));
              return null;
            }
          }
        }
      }
      return null;
    }
  @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;
  }