Exemple #1
0
  public final boolean canBeSeenBy(
      TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
    if (isPublic()) return true;

    SourceTypeBinding invocationType = scope.enclosingSourceType();
    if (invocationType == this.declaringClass && invocationType == receiverType) return true;

    if (invocationType == null) // static import call
    return !isPrivate() && scope.getCurrentPackage() == this.declaringClass.fPackage;

    if (isProtected()) {
      // answer true if the invocationType is the declaringClass or they are in the same package
      // OR the invocationType is a subclass of the declaringClass
      //    AND the receiverType is the invocationType or its subclass
      //    OR the method is a static method accessed directly through a type
      //    OR previous assertions are true for one of the enclosing type
      if (invocationType == this.declaringClass) return true;
      if (invocationType.fPackage == this.declaringClass.fPackage) return true;

      ReferenceBinding currentType = invocationType;
      int depth = 0;
      ReferenceBinding receiverErasure = (ReferenceBinding) receiverType.erasure();
      ReferenceBinding declaringErasure = (ReferenceBinding) this.declaringClass.erasure();
      do {
        if (currentType.findSuperTypeOriginatingFrom(declaringErasure) != null) {
          if (invocationSite.isSuperAccess()) return true;
          // receiverType can be an array binding in one case... see if you can change it
          if (receiverType instanceof ArrayBinding) return false;
          if (isStatic()) {
            if (depth > 0) invocationSite.setDepth(depth);
            return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
          }
          if (currentType == receiverErasure
              || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
            if (depth > 0) invocationSite.setDepth(depth);
            return true;
          }
        }
        depth++;
        currentType = currentType.enclosingType();
      } while (currentType != null);
      return false;
    }

    if (isPrivate()) {
      // answer true if the receiverType is the declaringClass
      // AND the invocationType and the declaringClass have a common enclosingType
      receiverCheck:
      {
        if (receiverType != this.declaringClass) {
          // special tolerance for type variable direct bounds
          if (receiverType.isTypeVariable()
              && ((TypeVariableBinding) receiverType)
                  .isErasureBoundTo(this.declaringClass.erasure())) break receiverCheck;
          return false;
        }
      }

      if (invocationType != this.declaringClass) {
        ReferenceBinding outerInvocationType = invocationType;
        ReferenceBinding temp = outerInvocationType.enclosingType();
        while (temp != null) {
          outerInvocationType = temp;
          temp = temp.enclosingType();
        }

        ReferenceBinding outerDeclaringClass = (ReferenceBinding) this.declaringClass.erasure();
        temp = outerDeclaringClass.enclosingType();
        while (temp != null) {
          outerDeclaringClass = temp;
          temp = temp.enclosingType();
        }
        if (outerInvocationType != outerDeclaringClass) return false;
      }
      return true;
    }

    // isDefault()
    PackageBinding declaringPackage = this.declaringClass.fPackage;
    if (invocationType.fPackage != declaringPackage) return false;

    // receiverType can be an array binding in one case... see if you can change it
    if (receiverType instanceof ArrayBinding) return false;
    TypeBinding originalDeclaringClass = this.declaringClass.original();
    ReferenceBinding currentType = (ReferenceBinding) receiverType;
    do {
      if (originalDeclaringClass == currentType.original()) return true;
      PackageBinding currentPackage = currentType.fPackage;
      // package could be null for wildcards/intersection types, ignore and recurse in superclass
      if (currentPackage != null && currentPackage != declaringPackage) return false;
    } while ((currentType = currentType.superclass()) != null);
    return false;
  }