示例#1
0
 protected void resolveAnnotations(Scope scope, int location) {
   Annotation[][] annotationsOnDimensions = getAnnotationsOnDimensions();
   if (this.annotations != null || annotationsOnDimensions != null) {
     BlockScope resolutionScope = Scope.typeAnnotationsResolutionScope(scope);
     if (resolutionScope != null) {
       int dimensions = this.dimensions();
       if (this.annotations != null) {
         TypeBinding leafComponentType = this.resolvedType.leafComponentType();
         leafComponentType =
             resolveAnnotations(resolutionScope, this.annotations, leafComponentType);
         this.resolvedType =
             dimensions > 0
                 ? scope.environment().createArrayType(leafComponentType, dimensions)
                 : leafComponentType;
         // contradictory null annotations on the type are already detected in
         // Annotation.resolveType() (SE7 treatment)
       }
       if (annotationsOnDimensions != null) {
         this.resolvedType =
             resolveAnnotations(resolutionScope, annotationsOnDimensions, this.resolvedType);
         if (this.resolvedType instanceof ArrayBinding) {
           long[] nullTagBitsPerDimension =
               ((ArrayBinding) this.resolvedType).nullTagBitsPerDimension;
           if (nullTagBitsPerDimension != null) {
             for (int i = 0;
                 i < dimensions;
                 i++) { // skip last annotations at [dimensions] (concerns the leaf type)
               if ((nullTagBitsPerDimension[i] & TagBits.AnnotationNullMASK)
                   == TagBits.AnnotationNullMASK) {
                 scope.problemReporter().contradictoryNullAnnotations(annotationsOnDimensions[i]);
                 nullTagBitsPerDimension[i] = 0;
               }
             }
           }
         }
       }
     }
   }
   if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled
       && this.resolvedType != null
       && (this.resolvedType.tagBits & TagBits.AnnotationNullMASK) == 0
       && !this.resolvedType.isTypeVariable()
       && !this.resolvedType.isWildcard()
       && location != 0
       && scope.hasDefaultNullnessFor(location)) {
     if (location == Binding.DefaultLocationTypeBound
         && this.resolvedType.id == TypeIds.T_JavaLangObject) {
       scope.problemReporter().implicitObjectBoundNoNullDefault(this);
     } else {
       LookupEnvironment environment = scope.environment();
       AnnotationBinding[] annots = new AnnotationBinding[] {environment.getNonNullAnnotation()};
       this.resolvedType = environment.createAnnotatedType(this.resolvedType, annots);
     }
   }
 }
 void recordArgNonNullness18(
     MethodBinding method,
     int paramIdx,
     Argument currentArgument,
     Boolean nonNullNess,
     LookupEnvironment env) {
   AnnotationBinding annotationBinding =
       nonNullNess.booleanValue() ? env.getNonNullAnnotation() : env.getNullableAnnotation();
   method.parameters[paramIdx] =
       env.createAnnotatedType(
           method.parameters[paramIdx], new AnnotationBinding[] {annotationBinding});
   if (currentArgument != null) {
     currentArgument.binding.type = method.parameters[paramIdx];
   }
 }
  public HierarchyResolver(
      INameEnvironment nameEnvironment,
      Map settings,
      HierarchyBuilder builder,
      IProblemFactory problemFactory) {
    // create a problem handler with the 'exit after all problems' handling policy
    this.options = new CompilerOptions(settings);
    IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.exitAfterAllProblems();
    ProblemReporter problemReporter = new ProblemReporter(policy, this.options, problemFactory);

    LookupEnvironment environment =
        new LookupEnvironment(this, this.options, problemReporter, nameEnvironment);
    environment.mayTolerateMissingType = true;
    setEnvironment(environment, builder);
  }
  public static ReferenceBinding resolveType(LookupEnvironment lookupEnvironment, String typeName) {
    ReferenceBinding type = null;

    int p = typeName.indexOf('$');
    if (p > 0) {
      // resolve an outer type before trying to get the cached inner
      String cupName = typeName.substring(0, p);
      char[][] chars = CharOperation.splitOn('.', cupName.toCharArray());
      ReferenceBinding outerType = lookupEnvironment.getType(chars);
      if (outerType != null) {
        // outer class was found
        resolveRecursive(outerType);
        chars = CharOperation.splitOn('.', typeName.toCharArray());
        type = lookupEnvironment.getCachedType(chars);
        if (type == null) {
          // no inner type; this is a pure failure
          return null;
        }
      }
    } else {
      // just resolve the type straight out
      char[][] chars = CharOperation.splitOn('.', typeName.toCharArray());
      type = lookupEnvironment.getType(chars);
    }

    if (type != null) {
      if (type instanceof UnresolvedReferenceBinding) {
        /*
         * Since type is an instance of UnresolvedReferenceBinding, we know that
         * the return value BinaryTypeBinding.resolveType will be of type
         * ReferenceBinding
         */
        type = (ReferenceBinding) BinaryTypeBinding.resolveType(type, lookupEnvironment, true);
      }
      // found it
      return type;
    }

    // Assume that the last '.' should be '$' and try again.
    //
    p = typeName.lastIndexOf('.');
    if (p >= 0) {
      typeName = typeName.substring(0, p) + "$" + typeName.substring(p + 1);
      return resolveType(lookupEnvironment, typeName);
    }

    return null;
  }
 /**
  * Feed null information from argument annotations into the analysis and mark arguments as
  * assigned.
  */
 static void analyseArguments(
     LookupEnvironment environment,
     FlowInfo flowInfo,
     Argument[] methodArguments,
     MethodBinding methodBinding) {
   if (methodArguments != null) {
     boolean usesNullTypeAnnotations = environment.usesNullTypeAnnotations();
     int length = Math.min(methodBinding.parameters.length, methodArguments.length);
     for (int i = 0; i < length; i++) {
       if (usesNullTypeAnnotations) {
         // leverage null type annotations:
         long tagBits = methodBinding.parameters[i].tagBits & TagBits.AnnotationNullMASK;
         if (tagBits == TagBits.AnnotationNonNull)
           flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
         else if (tagBits == TagBits.AnnotationNullable)
           flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
       } else {
         if (methodBinding.parameterNonNullness != null) {
           // leverage null-info from parameter annotations:
           Boolean nonNullNess = methodBinding.parameterNonNullness[i];
           if (nonNullNess != null) {
             if (nonNullNess.booleanValue())
               flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
             else flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
           }
         }
       }
       // tag parameters as being set:
       flowInfo.markAsDefinitelyAssigned(methodArguments[i].binding);
     }
   }
 }
示例#6
0
 public void swapUnresolved(
     UnresolvedReferenceBinding unresolvedType,
     ReferenceBinding resolvedType,
     LookupEnvironment env) {
   if (this.leafComponentType == unresolvedType) {
     this.leafComponentType = env.convertUnresolvedBinaryToRawType(resolvedType);
     this.tagBits |=
         this.leafComponentType.tagBits
             & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType);
   }
 }
 public void swapUnresolved(
     UnresolvedReferenceBinding unresolvedType,
     ReferenceBinding resolvedType,
     LookupEnvironment env) {
   boolean affected = false;
   if (this.genericType == unresolvedType) {
     this.genericType = resolvedType; // no raw conversion
     affected = true;
   }
   if (this.bound == unresolvedType) {
     this.bound = env.convertUnresolvedBinaryToRawType(resolvedType);
     affected = true;
   }
   if (this.otherBounds != null) {
     for (int i = 0, length = this.otherBounds.length; i < length; i++) {
       if (this.otherBounds[i] == unresolvedType) {
         this.otherBounds[i] = env.convertUnresolvedBinaryToRawType(resolvedType);
         affected = true;
       }
     }
   }
   if (affected) initialize(this.genericType, this.bound, this.otherBounds);
 }
 /**
  * Create raw generic method for raw type (double substitution from type vars with raw type
  * arguments, and erasure of method variables) Only invoked for non-static generic methods of raw
  * type
  */
 public ParameterizedGenericMethodBinding(
     MethodBinding originalMethod, RawTypeBinding rawType, LookupEnvironment environment) {
   TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
   int length = originalVariables.length;
   TypeBinding[] rawArguments = new TypeBinding[length];
   for (int i = 0; i < length; i++) {
     rawArguments[i] =
         environment.convertToRawType(
             originalVariables[i].erasure(), false /*do not force conversion of enclosing types*/);
   }
   this.isRaw = true;
   this.tagBits = originalMethod.tagBits;
   this.environment = environment;
   this.modifiers = originalMethod.modifiers;
   this.selector = originalMethod.selector;
   this.declaringClass = rawType == null ? originalMethod.declaringClass : rawType;
   this.typeVariables = Binding.NO_TYPE_VARIABLES;
   this.typeArguments = rawArguments;
   this.originalMethod = originalMethod;
   boolean ignoreRawTypeSubstitution = rawType == null || originalMethod.isStatic();
   this.parameters =
       Scope.substitute(
           this,
           ignoreRawTypeSubstitution
               ? originalMethod.parameters // no substitution if original was static
               : Scope.substitute(rawType, originalMethod.parameters));
   this.thrownExceptions =
       Scope.substitute(
           this,
           ignoreRawTypeSubstitution
               ? originalMethod.thrownExceptions // no substitution if original was static
               : Scope.substitute(rawType, originalMethod.thrownExceptions));
   // error case where exception type variable would have been substituted by a non-reference type
   // (207573)
   if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS;
   this.returnType =
       Scope.substitute(
           this,
           ignoreRawTypeSubstitution
               ? originalMethod.returnType // no substitution if original was static
               : Scope.substitute(rawType, originalMethod.returnType));
   this.wasInferred = false; // not resulting from method invocation inferrence
   this.parameterNonNullness = originalMethod.parameterNonNullness;
 }
  /**
   * Check and fill in implicit annotations from overridden methods and from default. Precondition:
   * caller has checked whether annotation-based null analysis is enabled.
   */
  public void checkImplicitNullAnnotations(
      MethodBinding currentMethod,
      AbstractMethodDeclaration srcMethod,
      boolean complain,
      Scope scope) {
    // check inherited nullness from superclass and superInterfaces
    try {
      ReferenceBinding currentType = currentMethod.declaringClass;
      if (currentType.id == TypeIds.T_JavaLangObject) {
        return;
      }
      boolean usesTypeAnnotations = scope.environment().usesNullTypeAnnotations();
      boolean needToApplyReturnNonNullDefault =
          currentMethod.hasNonNullDefaultFor(
              Binding.DefaultLocationReturnType, usesTypeAnnotations);
      boolean needToApplyParameterNonNullDefault =
          currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter, usesTypeAnnotations);
      boolean needToApplyNonNullDefault =
          needToApplyReturnNonNullDefault | needToApplyParameterNonNullDefault;
      // compatibility & inheritance do not consider constructors / static methods:
      boolean isInstanceMethod = !currentMethod.isConstructor() && !currentMethod.isStatic();
      complain &= isInstanceMethod;
      if (!needToApplyNonNullDefault
          && !complain
          && !(this.inheritNullAnnotations && isInstanceMethod)) {
        return; // short cut, no work to be done
      }

      if (isInstanceMethod) {
        List superMethodList = new ArrayList();

        // need super types connected:
        if (currentType instanceof SourceTypeBinding
            && !currentType.isHierarchyConnected()
            && !currentType.isAnonymousType()) {
          ((SourceTypeBinding) currentType).scope.connectTypeHierarchy();
        }

        int paramLen = currentMethod.parameters.length;
        findAllOverriddenMethods(
            currentMethod.original(),
            currentMethod.selector,
            paramLen,
            currentType,
            new HashSet(),
            superMethodList);

        // prepare interim storage for nullness info so we don't pollute currentMethod before we
        // know its conflict-free:
        InheritedNonNullnessInfo[] inheritedNonNullnessInfos =
            new InheritedNonNullnessInfo[paramLen + 1]; // index 0 is for the return type
        for (int i = 0; i < paramLen + 1; i++)
          inheritedNonNullnessInfos[i] = new InheritedNonNullnessInfo();

        int length = superMethodList.size();
        for (int i = length; --i >= 0; ) {
          MethodBinding currentSuper = (MethodBinding) superMethodList.get(i);
          if ((currentSuper.tagBits & TagBits.IsNullnessKnown) == 0) {
            // recurse to prepare currentSuper
            checkImplicitNullAnnotations(
                currentSuper,
                null,
                false,
                scope); // TODO (stephan) complain=true if currentSuper is source method??
          }
          checkNullSpecInheritance(
              currentMethod,
              srcMethod,
              needToApplyReturnNonNullDefault,
              needToApplyParameterNonNullDefault,
              complain,
              currentSuper,
              null,
              scope,
              inheritedNonNullnessInfos);
          needToApplyNonNullDefault = false;
        }

        // transfer collected information into currentMethod:
        InheritedNonNullnessInfo info = inheritedNonNullnessInfos[0];
        if (!info.complained) {
          long tagBits = 0;
          if (info.inheritedNonNullness == Boolean.TRUE) {
            tagBits = TagBits.AnnotationNonNull;
          } else if (info.inheritedNonNullness == Boolean.FALSE) {
            tagBits = TagBits.AnnotationNullable;
          }
          if (tagBits != 0) {
            if (!usesTypeAnnotations) {
              currentMethod.tagBits |= tagBits;
            } else {
              if (!currentMethod.returnType.isBaseType()) {
                LookupEnvironment env = scope.environment();
                currentMethod.returnType =
                    env.createAnnotatedType(
                        currentMethod.returnType, env.nullAnnotationsFromTagBits(tagBits));
              }
            }
          }
        }
        for (int i = 0; i < paramLen; i++) {
          info = inheritedNonNullnessInfos[i + 1];
          if (!info.complained && info.inheritedNonNullness != null) {
            Argument currentArg = srcMethod == null ? null : srcMethod.arguments[i];
            if (!usesTypeAnnotations)
              recordArgNonNullness(
                  currentMethod, paramLen, i, currentArg, info.inheritedNonNullness);
            else
              recordArgNonNullness18(
                  currentMethod, i, currentArg, info.inheritedNonNullness, scope.environment());
          }
        }
      }
      if (needToApplyNonNullDefault) {
        if (!usesTypeAnnotations) currentMethod.fillInDefaultNonNullness(srcMethod);
        else currentMethod.fillInDefaultNonNullness18(srcMethod, scope.environment());
      }
    } finally {
      currentMethod.tagBits |= TagBits.IsNullnessKnown;
    }
  }
示例#10
0
  public TypeBinding resolveType(BlockScope scope) {

    this.constant = Constant.NotAConstant;
    if ((this.targetType = this.type.resolveType(scope, true /* check bounds*/)) == null)
      return null;

    /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=320463
      https://bugs.eclipse.org/bugs/show_bug.cgi?id=312076
      JLS3 15.8.2 forbids the type named in the class literal expression from being a parameterized type.
      And the grammar in 18.1 disallows (where X and Y are some concrete types) constructs of the form
      Outer<X>.class, Outer<X>.Inner.class, Outer.Inner<X>.class, Outer<X>.Inner<Y>.class etc.
      Corollary wise, we should resolve the type of the class literal expression to be a raw type as
      class literals exist only for the raw underlying type.
    */
    LookupEnvironment environment = scope.environment();
    this.targetType =
        environment.convertToRawType(
            this.targetType, true /* force conversion of enclosing types*/);

    if (this.targetType.isArrayType()) {
      ArrayBinding arrayBinding = (ArrayBinding) this.targetType;
      TypeBinding leafComponentType = arrayBinding.leafComponentType;
      if (leafComponentType == TypeBinding.VOID) {
        scope.problemReporter().cannotAllocateVoidArray(this);
        return null;
      } else if (leafComponentType.isTypeVariable()) {
        scope
            .problemReporter()
            .illegalClassLiteralForTypeVariable((TypeVariableBinding) leafComponentType, this);
      }
    } else if (this.targetType.isTypeVariable()) {
      scope
          .problemReporter()
          .illegalClassLiteralForTypeVariable((TypeVariableBinding) this.targetType, this);
    }
    // {ObjectTeams: do we need a RoleClassLiteralAccess?
    if (this.targetType instanceof ReferenceBinding) {
      ReferenceBinding targetRef = (ReferenceBinding) this.targetType;
      if (targetRef.isRole()) {
        if (this.verbatim) {
          this.targetType =
              RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, this.targetType, this);
        } else {
          SourceTypeBinding site = scope.enclosingSourceType();
          if (scope.methodScope().isStatic // role class literal needs team instance
              && !site.isRole() // static role method are OK.
              && !RoleTypeBinding.isRoleWithExplicitAnchor(this.targetType)) // t.R.class?
          {
            scope.problemReporter().roleClassLiteralLacksTeamInstance(this, targetRef);
            return null;
          }
          ReferenceBinding teamBinding;
          if (RoleTypeBinding.isRoleWithExplicitAnchor(targetRef))
            teamBinding = targetRef.enclosingType();
          else teamBinding = TeamModel.findEnclosingTeamContainingRole(site, targetRef);
          if (teamBinding == null)
            scope.problemReporter().externalizedRoleClassLiteral(this, targetRef);
          else {
            TypeBinding methodType =
                RoleClassLiteralAccess.ensureGetClassMethod(
                    teamBinding.getTeamModel(),
                    targetRef.roleModel); // not affected by visibility check (for resilience)
            this.roleClassLiteralAccess = new RoleClassLiteralAccess(this, methodType);
            this.resolvedType = this.roleClassLiteralAccess.resolveType(scope);
          }
          return this.resolvedType;
        }
      }
    }
    // SH}
    ReferenceBinding classType = scope.getJavaLangClass();
    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=328689
    if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
      // Integer.class --> Class<Integer>, perform boxing of base types (int.class -->
      // Class<Integer>)
      TypeBinding boxedType = null;
      if (this.targetType.id == T_void) {
        boxedType = environment.getResolvedType(JAVA_LANG_VOID, scope);
      } else {
        boxedType = scope.boxing(this.targetType);
      }
      if (environment.usesNullTypeAnnotations())
        boxedType =
            environment.createAnnotatedType(
                boxedType, new AnnotationBinding[] {environment.getNonNullAnnotation()});
      this.resolvedType =
          environment.createParameterizedType(
              classType, new TypeBinding[] {boxedType}, null /*not a member*/);
    } else {
      this.resolvedType = classType;
    }
    return this.resolvedType;
  }