コード例 #1
0
 // additional parameter strict: if true we do not tolerate incompatibly missing annotations on
 // type parameters (for overriding analysis)
 public static NullAnnotationMatching analyse(
     TypeBinding requiredType, TypeBinding providedType, int nullStatus, boolean strict) {
   int severity = 0;
   TypeBinding superTypeHint = null;
   if (requiredType instanceof ArrayBinding) {
     long[] requiredDimsTagBits = ((ArrayBinding) requiredType).nullTagBitsPerDimension;
     if (requiredDimsTagBits != null) {
       int dims = requiredType.dimensions();
       if (requiredType.dimensions() == providedType.dimensions()) {
         long[] providedDimsTagBits = ((ArrayBinding) providedType).nullTagBitsPerDimension;
         if (providedDimsTagBits == null) {
           severity = 1; // required is annotated, provided not, need unchecked conversion
         } else {
           for (int i = 0; i <= dims; i++) {
             long requiredBits = validNullTagBits(requiredDimsTagBits[i]);
             long providedBits = validNullTagBits(providedDimsTagBits[i]);
             if (i > 0) nullStatus = -1; // don't use beyond the outermost dimension
             severity =
                 Math.max(
                     severity,
                     computeNullProblemSeverity(requiredBits, providedBits, nullStatus, strict));
             if (severity == 2) return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH;
           }
         }
       } else if (providedType.id == TypeIds.T_null) {
         if (dims > 0 && requiredDimsTagBits[0] == TagBits.AnnotationNonNull)
           return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH;
       }
     }
   } else if (requiredType.hasNullTypeAnnotations() || providedType.hasNullTypeAnnotations()) {
     long requiredBits = requiredNullTagBits(requiredType);
     if (requiredBits != TagBits.AnnotationNullable // nullable lhs accepts everything, ...
         || nullStatus == -1) // only at detail/recursion even nullable must be matched exactly
     {
       long providedBits = providedNullTagBits(providedType);
       severity =
           computeNullProblemSeverity(
               requiredBits, providedBits, nullStatus, strict && nullStatus == -1);
     }
     if (severity < 2) {
       TypeBinding providedSuper = providedType.findSuperTypeOriginatingFrom(requiredType);
       if (providedSuper != providedType) // $IDENTITY-COMPARISON$
       superTypeHint = providedSuper;
       if (requiredType.isParameterizedType()
           && providedSuper
               instanceof ParameterizedTypeBinding) { // TODO(stephan): handle providedType.isRaw()
         TypeBinding[] requiredArguments = ((ParameterizedTypeBinding) requiredType).arguments;
         TypeBinding[] providedArguments = ((ParameterizedTypeBinding) providedSuper).arguments;
         if (requiredArguments != null
             && providedArguments != null
             && requiredArguments.length == providedArguments.length) {
           for (int i = 0; i < requiredArguments.length; i++) {
             NullAnnotationMatching status =
                 analyse(requiredArguments[i], providedArguments[i], -1, strict);
             severity = Math.max(severity, status.severity);
             if (severity == 2) return new NullAnnotationMatching(severity, superTypeHint);
           }
         }
       }
       TypeBinding requiredEnclosing = requiredType.enclosingType();
       TypeBinding providedEnclosing = providedType.enclosingType();
       if (requiredEnclosing != null && providedEnclosing != null) {
         NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, -1, strict);
         severity = Math.max(severity, status.severity);
       }
     }
   }
   if (severity == 0) return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
   return new NullAnnotationMatching(severity, superTypeHint);
 }
コード例 #2
0
 public boolean checkUnsafeCast(
     Scope scope,
     TypeBinding castType,
     TypeBinding expressionType,
     TypeBinding match,
     boolean isNarrowing) {
   if (TypeBinding.equalsEquals(match, castType)) {
     if (!isNarrowing
         && TypeBinding.equalsEquals(
             match,
             this.resolvedType
                 .leafComponentType()) // do not tag as unnecessary when recursing through upper
                                       // bounds
         && !(expressionType.isParameterizedType()
             && expressionType.isProvablyDistinct(castType))) {
       tagAsUnnecessaryCast(scope, castType);
     }
     return true;
   }
   if (match != null) {
     if (isNarrowing
         ? match.isProvablyDistinct(expressionType)
         : castType.isProvablyDistinct(match)) {
       return false;
     }
   }
   switch (castType.kind()) {
     case Binding.PARAMETERIZED_TYPE:
       if (!castType.isReifiable()) {
         if (match == null) { // unrelated types
           this.bits |= ASTNode.UnsafeCast;
           return true;
         }
         switch (match.kind()) {
           case Binding.PARAMETERIZED_TYPE:
             if (isNarrowing) {
               // [JLS 5.5] T <: S
               if (expressionType.isRawType() || !expressionType.isEquivalentTo(match)) {
                 this.bits |= ASTNode.UnsafeCast;
                 return true;
               }
               // [JLS 5.5] S has no subtype X != T, such that |X| == |T|
               // if I2<T,U> extends I1<T>, then cast from I1<T> to I2<T,U> is unchecked
               ParameterizedTypeBinding paramCastType = (ParameterizedTypeBinding) castType;
               ParameterizedTypeBinding paramMatch = (ParameterizedTypeBinding) match;
               // easy case if less parameters on match
               TypeBinding[] castArguments = paramCastType.arguments;
               int length = castArguments == null ? 0 : castArguments.length;
               if (paramMatch.arguments == null || length > paramMatch.arguments.length) {
                 this.bits |= ASTNode.UnsafeCast;
               } else if ((paramCastType.tagBits
                       & (TagBits.HasDirectWildcard | TagBits.HasTypeVariable))
                   != 0) {
                 // verify alternate cast type, substituting different type arguments
                 nextAlternateArgument:
                 for (int i = 0; i < length; i++) {
                   switch (castArguments[i].kind()) {
                     case Binding.WILDCARD_TYPE:
                     case Binding.TYPE_PARAMETER:
                       break; // check substituting with other
                     default:
                       continue nextAlternateArgument; // no alternative possible
                   }
                   TypeBinding[] alternateArguments;
                   // need to clone for each iteration to avoid env paramtype cache interference
                   System.arraycopy(
                       paramCastType.arguments,
                       0,
                       alternateArguments = new TypeBinding[length],
                       0,
                       length);
                   alternateArguments[i] = scope.getJavaLangObject();
                   LookupEnvironment environment = scope.environment();
                   ParameterizedTypeBinding alternateCastType =
                       environment.createParameterizedType(
                           (ReferenceBinding) castType.erasure(),
                           alternateArguments,
                           castType.enclosingType());
                   if (TypeBinding.equalsEquals(
                       alternateCastType.findSuperTypeOriginatingFrom(expressionType), match)) {
                     this.bits |= ASTNode.UnsafeCast;
                     break;
                   }
                 }
               }
               return true;
             } else {
               // [JLS 5.5] T >: S
               if (!match.isEquivalentTo(castType)) {
                 this.bits |= ASTNode.UnsafeCast;
                 return true;
               }
             }
             break;
           case Binding.RAW_TYPE:
             this.bits |=
                 ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
             return true;
           default:
             if (isNarrowing) {
               // match is not parameterized or raw, then any other subtype of match will erase  to
               // |T|
               this.bits |= ASTNode.UnsafeCast;
               return true;
             }
             break;
         }
       }
       break;
     case Binding.ARRAY_TYPE:
       TypeBinding leafType = castType.leafComponentType();
       if (isNarrowing && (!leafType.isReifiable() || leafType.isTypeVariable())) {
         this.bits |= ASTNode.UnsafeCast;
         return true;
       }
       break;
     case Binding.TYPE_PARAMETER:
       this.bits |= ASTNode.UnsafeCast;
       return true;
       //		(disabled) https://bugs.eclipse.org/bugs/show_bug.cgi?id=240807
       //		case Binding.TYPE :
       //			if (isNarrowing && match == null && expressionType.isParameterizedType()) {
       //				this.bits |= ASTNode.UnsafeCast;
       //				return true;
       //			}
       //			break;
   }
   if (!isNarrowing
       && TypeBinding.equalsEquals(
           match,
           this.resolvedType
               .leafComponentType())) { // do not tag as unnecessary when recursing through upper
                                        // bounds
     tagAsUnnecessaryCast(scope, castType);
   }
   return true;
 }
コード例 #3
0
  static boolean isEqual(
      org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding,
      org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding2,
      HashSet visitedTypes) {
    if (typeBinding == typeBinding2) return true;
    if (typeBinding == null || typeBinding2 == null) return false;

    switch (typeBinding.kind()) {
      case Binding.BASE_TYPE:
        if (!typeBinding2.isBaseType()) {
          return false;
        }
        return typeBinding.id == typeBinding2.id;

      case Binding.ARRAY_TYPE:
        if (!typeBinding2.isArrayType()) {
          return false;
        }
        return typeBinding.dimensions() == typeBinding2.dimensions()
            && isEqual(
                typeBinding.leafComponentType(), typeBinding2.leafComponentType(), visitedTypes);

      case Binding.PARAMETERIZED_TYPE:
        if (!typeBinding2.isParameterizedType()) {
          return false;
        }
        ParameterizedTypeBinding parameterizedTypeBinding = (ParameterizedTypeBinding) typeBinding;
        ParameterizedTypeBinding parameterizedTypeBinding2 =
            (ParameterizedTypeBinding) typeBinding2;
        return CharOperation.equals(
                parameterizedTypeBinding.compoundName, parameterizedTypeBinding2.compoundName)
            && (parameterizedTypeBinding.modifiers
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
                == (parameterizedTypeBinding2.modifiers
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
            && isEqual(
                parameterizedTypeBinding.arguments,
                parameterizedTypeBinding2.arguments,
                visitedTypes)
            && isEqual(
                parameterizedTypeBinding.enclosingType(),
                parameterizedTypeBinding2.enclosingType(),
                visitedTypes);

      case Binding.WILDCARD_TYPE:
        if (typeBinding2.kind() != Binding.WILDCARD_TYPE) {
          return false;
        }
        WildcardBinding wildcardBinding = (WildcardBinding) typeBinding;
        WildcardBinding wildcardBinding2 = (WildcardBinding) typeBinding2;
        return isEqual(wildcardBinding.bound, wildcardBinding2.bound, visitedTypes)
            && wildcardBinding.boundKind == wildcardBinding2.boundKind;

      case Binding.INTERSECTION_TYPE:
        if (typeBinding2.kind() != Binding.INTERSECTION_TYPE) {
          return false;
        }
        WildcardBinding intersectionBinding = (WildcardBinding) typeBinding;
        WildcardBinding intersectionBinding2 = (WildcardBinding) typeBinding2;
        return isEqual(intersectionBinding.bound, intersectionBinding2.bound, visitedTypes)
            && isEqual(
                intersectionBinding.otherBounds, intersectionBinding2.otherBounds, visitedTypes);

      case Binding.TYPE_PARAMETER:
        if (!(typeBinding2.isTypeVariable())) {
          return false;
        }
        if (typeBinding.isCapture()) {
          if (!(typeBinding2.isCapture())) {
            return false;
          }
          CaptureBinding captureBinding = (CaptureBinding) typeBinding;
          CaptureBinding captureBinding2 = (CaptureBinding) typeBinding2;
          if (captureBinding.position == captureBinding2.position) {
            if (visitedTypes.contains(typeBinding)) return true;
            visitedTypes.add(typeBinding);

            return isEqual(captureBinding.wildcard, captureBinding2.wildcard, visitedTypes)
                && isEqual(captureBinding.sourceType, captureBinding2.sourceType, visitedTypes);
          }
          return false;
        }
        TypeVariableBinding typeVariableBinding = (TypeVariableBinding) typeBinding;
        TypeVariableBinding typeVariableBinding2 = (TypeVariableBinding) typeBinding2;
        if (CharOperation.equals(typeVariableBinding.sourceName, typeVariableBinding2.sourceName)) {
          if (visitedTypes.contains(typeBinding)) return true;
          visitedTypes.add(typeBinding);

          return isEqual(
                  typeVariableBinding.declaringElement,
                  typeVariableBinding2.declaringElement,
                  visitedTypes)
              && isEqual(
                  typeVariableBinding.superclass(), typeVariableBinding2.superclass(), visitedTypes)
              && isEqual(
                  typeVariableBinding.superInterfaces(),
                  typeVariableBinding2.superInterfaces(),
                  visitedTypes);
        }
        return false;
      case Binding.GENERIC_TYPE:
        if (!typeBinding2.isGenericType()) {
          return false;
        }
        ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
        ReferenceBinding referenceBinding2 = (ReferenceBinding) typeBinding2;
        return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
            && (referenceBinding.modifiers
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
                == (referenceBinding2.modifiers
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
            && isEqual(
                referenceBinding.typeVariables(), referenceBinding2.typeVariables(), visitedTypes)
            && isEqual(
                referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);

      case Binding.RAW_TYPE:
      default:
        if (!(typeBinding2 instanceof ReferenceBinding)) {
          return false;
        }
        referenceBinding = (ReferenceBinding) typeBinding;
        referenceBinding2 = (ReferenceBinding) typeBinding2;
        char[] constantPoolName = referenceBinding.constantPoolName();
        char[] constantPoolName2 = referenceBinding2.constantPoolName();
        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=116833
        if (constantPoolName == null) {
          if (constantPoolName2 != null) {
            return false;
          }
          if (!CharOperation.equals(
              referenceBinding.computeUniqueKey(), referenceBinding2.computeUniqueKey())) {
            return false;
          }
        } else {
          if (constantPoolName2 == null) {
            return false;
          }
          if (!CharOperation.equals(constantPoolName, constantPoolName2)) {
            return false;
          }
        }
        return CharOperation.equals(referenceBinding.compoundName, referenceBinding2.compoundName)
            && (!referenceBinding2.isGenericType())
            && (referenceBinding.isRawType() == referenceBinding2.isRawType())
            && ((referenceBinding.modifiers & ~ClassFileConstants.AccSuper)
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
                == ((referenceBinding2.modifiers & ~ClassFileConstants.AccSuper)
                    & (ExtraCompilerModifiers.AccJustFlag
                        | ClassFileConstants.AccInterface
                        | ClassFileConstants.AccEnum
                        | ClassFileConstants.AccAnnotation))
            && isEqual(
                referenceBinding.enclosingType(), referenceBinding2.enclosingType(), visitedTypes);
    }
  }