public boolean isInterchangeableWith(TypeVariableBinding var1, Substitution var2) {
   if (this == var1) {
     return true;
   } else {
     int var3 = this.superInterfaces.length;
     if (var3 != var1.superInterfaces.length) {
       return false;
     } else if (this.superclass != Scope.substitute(var2, var1.superclass)) {
       return false;
     } else {
       int var4 = 0;
       label35:
       while (var4 < var3) {
         TypeBinding var5 = Scope.substitute(var2, var1.superInterfaces[var4]);
         for (int var6 = 0; var6 < var3; ++var6) {
           if (var5 == this.superInterfaces[var6]) {
             ++var4;
             continue label35;
           }
         }
         return false;
       }
       return true;
     }
   }
 }
  /**
   * After a method has substituted type parameters, check if this resulted in any contradictory
   * null annotations. Problems are either reported directly (if scope != null) or by returning a
   * ProblemMethodBinding.
   */
  public static MethodBinding checkForContraditions(
      final MethodBinding method, final InvocationSite invocationSite, final Scope scope) {

    class SearchContradictions extends TypeBindingVisitor {
      ReferenceBinding typeWithContradiction;

      @Override
      public boolean visit(ReferenceBinding referenceBinding) {
        if ((referenceBinding.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
          this.typeWithContradiction = referenceBinding;
          return false;
        }
        return true;
      }

      @Override
      public boolean visit(TypeVariableBinding typeVariable) {
        return visit((ReferenceBinding) typeVariable);
      }

      @Override
      public boolean visit(RawTypeBinding rawType) {
        return visit((ReferenceBinding) rawType);
      }
    }

    SearchContradictions searchContradiction = new SearchContradictions();
    TypeBindingVisitor.visit(searchContradiction, method.returnType);
    if (searchContradiction.typeWithContradiction != null) {
      if (scope == null)
        return new ProblemMethodBinding(
            method,
            method.selector,
            method.parameters,
            ProblemReasons.ContradictoryNullAnnotations);
      scope.problemReporter().contradictoryNullAnnotationsInferred(method, invocationSite);
      // note: if needed, we might want to update the method by removing the contradictory
      // annotations??
      return method;
    }

    Expression[] arguments = null;
    if (invocationSite instanceof Invocation) arguments = ((Invocation) invocationSite).arguments();
    for (int i = 0; i < method.parameters.length; i++) {
      TypeBindingVisitor.visit(searchContradiction, method.parameters[i]);
      if (searchContradiction.typeWithContradiction != null) {
        if (scope == null)
          return new ProblemMethodBinding(
              method,
              method.selector,
              method.parameters,
              ProblemReasons.ContradictoryNullAnnotations);
        if (arguments != null && i < arguments.length)
          scope.problemReporter().contradictoryNullAnnotationsInferred(method, arguments[i]);
        else scope.problemReporter().contradictoryNullAnnotationsInferred(method, invocationSite);
        return method;
      }
    }
    return method;
  }
示例#3
0
 public TypeBinding checkResolvedType(
     TypeBinding type, Scope scope, int location, boolean hasError) {
   // SH}
   if (type.isArrayType() && ((ArrayBinding) type).leafComponentType == TypeBinding.VOID) {
     scope.problemReporter().cannotAllocateVoidArray(this);
     return null;
   }
   if (!(this
           instanceof
           QualifiedTypeReference) // QualifiedTypeReference#getTypeBinding called above will have
                                   // already checked deprecation
       && isTypeUseDeprecated(type, scope)) {
     reportDeprecatedType(type, scope);
   }
   type =
       scope
           .environment()
           .convertToRawType(type, false /*do not force conversion of enclosing types*/);
   if (type.leafComponentType().isRawType()
       && (this.bits & ASTNode.IgnoreRawTypeCheck) == 0
       && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
           != ProblemSeverities.Ignore) {
     scope.problemReporter().rawTypeReference(this, type);
   }
   if (hasError) {
     resolveAnnotations(scope, 0); // don't apply null defaults to buggy type
     return type;
   } else {
     // store the computed type only if no error, otherwise keep the problem type instead
     this.resolvedType = type;
     resolveAnnotations(scope, location);
     return this
         .resolvedType; // pick up value that may have been changed in resolveAnnotations(..)
   }
 }
 private TypeBinding createArrayType(Scope scope, TypeBinding type) {
   if (this.dimensions > 0) {
     if (this.dimensions > 255) scope.problemReporter().tooManyDimensions(this);
     return scope.createArrayType(type, this.dimensions);
   }
   return type;
 }
示例#5
0
 protected void reportDeprecatedType(TypeBinding type, Scope scope) {
   // {ObjectTeams:
   if (this.deprecationProblemId == 0) return;
   if (this.deprecationProblemId == IProblem.DeprecatedBaseclass)
     scope.problemReporter().deprecatedBaseclass(this, type);
   else
     // SH}
     scope.problemReporter().deprecatedType(type, this, Integer.MAX_VALUE);
 }
示例#6
0
 void checkDecapsulation(ReferenceBinding baseClass, Scope scope) {
   if (!this.resolvedMethod.canBeSeenBy(baseClass, this, scope)) {
     WeavingScheme weavingScheme = scope.compilerOptions().weavingScheme;
     this.implementationStrategy =
         weavingScheme == WeavingScheme.OTDRE
             ? ImplementationStrategy.DYN_ACCESS
             : ImplementationStrategy.DECAPS_WRAPPER;
     this.accessId = createAccessAttribute(scope.enclosingSourceType().roleModel);
     scope.problemReporter().decapsulation(this, baseClass, scope);
   } else {
     this.implementationStrategy = ImplementationStrategy.DIRECT;
   }
 }
 /* (non-Javadoc)
  * @see ITypeBinding#isAssignmentCompatible(ITypeBinding)
  */
 public boolean isAssignmentCompatible(ITypeBinding type) {
   try {
     if (this == type) return true;
     if (!(type instanceof TypeBinding)) return false;
     TypeBinding other = (TypeBinding) type;
     Scope scope = this.resolver.scope();
     if (scope == null) return false;
     return this.binding.isCompatibleWith(other.binding)
         || scope.isBoxingCompatibleWith(this.binding, other.binding);
   } catch (AbortCompilation e) {
     // don't surface internal exception to clients
     // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
     return false;
   }
 }
 public void collectSubstitutes(Scope var1, TypeBinding var2, InferenceContext var3, int var4) {
   if (this.declaringElement == var3.genericMethod) {
     switch (var2.kind()) {
       case 132:
         if (var2 == TypeBinding.field_187) {
           return;
         } else {
           TypeBinding var5 = var1.environment().method_486(var2);
           if (var5 == var2) {
             return;
           } else {
             var2 = var5;
           }
         }
       case 516:
         return;
       default:
         byte var6;
         switch (var4) {
           case 0:
             var6 = 0;
             break;
           case 1:
             var6 = 2;
             break;
           default:
             var6 = 1;
         }
         var3.recordSubstitute(this, var2, var6);
     }
   }
 }
 /**
  * @see
  *     org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope,
  *     org.eclipse.jdt.internal.compiler.lookup.TypeBinding,
  *     org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
  */
 public void computeConversion(
     Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
   if (runtimeTimeType == null || compileTimeType == null) return;
   // set the generic cast after the fact, once the type expectation is fully known (no need for
   // strict cast)
   if (this.binding != null && this.binding.isValidBinding()) {
     FieldBinding originalBinding = this.binding.original();
     TypeBinding originalType = originalBinding.type;
     // extra cast needed if field type is type variable
     if (originalType.leafComponentType().isTypeVariable()) {
       TypeBinding targetType =
           (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
               ? compileTimeType // unboxing: checkcast before conversion
               : runtimeTimeType;
       this.genericCast = originalBinding.type.genericCast(targetType);
       if (this.genericCast instanceof ReferenceBinding) {
         ReferenceBinding referenceCast = (ReferenceBinding) this.genericCast;
         if (!referenceCast.canBeSeenBy(scope)) {
           scope
               .problemReporter()
               .invalidType(
                   this,
                   new ProblemReferenceBinding(
                       CharOperation.splitOn('.', referenceCast.shortReadableName()),
                       referenceCast,
                       ProblemReasons.NotVisible));
         }
       }
     }
   }
   super.computeConversion(scope, runtimeTimeType, compileTimeType);
 }
示例#10
0
 /** During deferred checking re-visit a previously recording unboxing situation. */
 protected void checkUnboxing(Scope scope, Expression expression, FlowInfo flowInfo) {
   int status = expression.nullStatus(flowInfo, this);
   if ((status & FlowInfo.NULL) != 0) {
     scope.problemReporter().nullUnboxing(expression, expression.resolvedType);
     return;
   } else if ((status & FlowInfo.POTENTIALLY_NULL) != 0) {
     scope.problemReporter().potentialNullUnboxing(expression, expression.resolvedType);
     return;
   } else if ((status & FlowInfo.NON_NULL) != 0) {
     return;
   }
   // not handled, perhaps our parent will eventually have something to say?
   if (this.parent != null) {
     this.parent.recordUnboxing(scope, expression, FlowInfo.UNKNOWN, flowInfo);
   }
 }
示例#11
0
  protected boolean isBoxingCompatible(
      TypeBinding expressionType, TypeBinding targetType, Expression expression, Scope scope) {
    if (scope.isBoxingCompatibleWith(expressionType, targetType)) return true;

    return expressionType
            .isBaseType() // narrowing then boxing ? Only allowed for some target types see 362279
        && !targetType.isBaseType()
        && !targetType.isTypeVariable()
        && scope.compilerOptions().sourceLevel
            >= org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5 // autoboxing
        && (targetType.id == TypeIds.T_JavaLangByte
            || targetType.id == TypeIds.T_JavaLangShort
            || targetType.id == TypeIds.T_JavaLangCharacter)
        && expression.isConstantValueOfTypeAssignableToType(
            expressionType, scope.environment().computeBoxingType(targetType));
  }
 public boolean canUseDiamond(String[] parameterTypes, char[] fullyQualifiedTypeName) {
   TypeBinding guessedType = null;
   char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName);
   Scope scope = this.assistScope;
   if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return false;
   // If no LHS or return type expected, then we can safely use diamond
   char[][] expectedTypekeys = this.completionContext.getExpectedTypesKeys();
   if (expectedTypekeys == null || expectedTypekeys.length == 0) return true;
   // Next, find out whether any of the constructor parameters are the same as one of the
   // class type variables. If yes, diamond cannot be used.
   TypeReference ref;
   if (cn.length == 1) {
     ref = new SingleTypeReference(cn[0], 0);
   } else {
     ref = new QualifiedTypeReference(cn, new long[cn.length]);
   }
   // {ObjectTeams: protect call into the compiler
   try (Config config =
       Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
     // orig:
     switch (scope.kind) {
       case Scope.METHOD_SCOPE:
       case Scope.BLOCK_SCOPE:
         guessedType = ref.resolveType((BlockScope) scope);
         break;
       case Scope.CLASS_SCOPE:
         guessedType = ref.resolveType((ClassScope) scope);
         break;
     }
     // :giro
   }
   // SH}
   if (guessedType != null && guessedType.isValidBinding()) {
     // the erasure must be used because guessedType can be a RawTypeBinding
     guessedType = guessedType.erasure();
     TypeVariableBinding[] typeVars = guessedType.typeVariables();
     for (int i = 0; i < parameterTypes.length; i++) {
       for (int j = 0; j < typeVars.length; j++) {
         if (CharOperation.equals(parameterTypes[i].toCharArray(), typeVars[j].sourceName))
           return false;
       }
     }
     return true;
   }
   return false;
 }
示例#13
0
 protected void checkIllegalNullAnnotation(Scope scope) {
   if (this.resolvedType.leafComponentType().isBaseType()
       && hasNullTypeAnnotation(AnnotationPosition.LEAF_TYPE))
     scope
         .problemReporter()
         .illegalAnnotationForBaseType(
             this, this.annotations[0], this.resolvedType.tagBits & TagBits.AnnotationNullMASK);
 }
示例#14
0
 /** Check all typeArguments for illegal null annotations on base types. */
 protected void checkIllegalNullAnnotations(Scope scope, TypeReference[] typeArguments) {
   if (scope.environment().usesNullTypeAnnotations() && typeArguments != null) {
     for (int i = 0; i < typeArguments.length; i++) {
       TypeReference arg = typeArguments[i];
       if (arg.resolvedType != null) arg.checkIllegalNullAnnotation(scope);
     }
   }
 }
  private TypeBinding getTypeFromSignature(String typeSignature, Scope scope) {
    TypeBinding assignableTypeBinding = null;

    TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
    ReferenceContext referenceContext = scope.referenceContext();
    if (referenceContext instanceof AbstractMethodDeclaration) {
      AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
      TypeParameter[] typeParameters = methodDeclaration.typeParameters();
      if (typeParameters != null && typeParameters.length > 0) {
        int length = typeParameters.length;
        int count = 0;
        typeVariables = new TypeVariableBinding[length];
        for (int i = 0; i < length; i++) {
          if (typeParameters[i].binding != null) {
            typeVariables[count++] = typeParameters[i].binding;
          }
        }

        if (count != length) {
          System.arraycopy(
              typeVariables, 0, typeVariables = new TypeVariableBinding[count], 0, count);
        }
      }
    }

    CompilationUnitDeclaration previousUnitBeingCompleted =
        this.lookupEnvironment.unitBeingCompleted;
    this.lookupEnvironment.unitBeingCompleted = this.compilationUnitDeclaration;
    // {ObjectTeams: protect call into the compiler
    /* orig:
    try {
    :giro */
    try (Config config =
        Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
      // orig:

      SignatureWrapper wrapper =
          new SignatureWrapper(replacePackagesDot(typeSignature.toCharArray()));
      // FIXME(stephan): do we interpret type annotations here?
      assignableTypeBinding =
          this.lookupEnvironment.getTypeFromTypeSignature(
              wrapper,
              typeVariables,
              this.assistScope.enclosingClassScope().referenceContext.binding,
              null,
              ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
      assignableTypeBinding =
          BinaryTypeBinding.resolveType(assignableTypeBinding, this.lookupEnvironment, true);
    } catch (AbortCompilation e) {
      assignableTypeBinding = null;
    } finally {
      this.lookupEnvironment.unitBeingCompleted = previousUnitBeingCompleted;
    }
    return assignableTypeBinding;
  }
示例#16
0
 protected void reportInvalidType(Scope scope) {
   // {ObjectTeams: suppress this in role feature bridge (the same will be reported against the
   // original, too):
   if (scope.isFakeMethod(FakeKind.ROLE_FEATURE_BRIDGE)) {
     scope.referenceContext().tagAsHavingErrors();
     return;
   }
   // did we misread an OT keyword as a type reference (during syntax recovery)?
   if (!scope.environment().globalOptions.isPureJava) {
     char[] token = getLastToken();
     for (int j = 0; j < IOTConstants.OT_KEYWORDS.length; j++) {
       if (CharOperation.equals(token, IOTConstants.OT_KEYWORDS[j])) {
         if (scope.referenceContext().compilationResult().hasErrors())
           return; // assume this is a secondary error
       }
     }
   }
   // SH}
   scope.problemReporter().invalidType(this, this.resolvedType);
 }
示例#17
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);
     }
   }
 }
示例#18
0
 /**
  * Check whether this type reference conforms to the null constraints defined for the
  * corresponding type variable.
  */
 protected void checkNullConstraints(
     Scope scope, Substitution substitution, TypeBinding[] variables, int rank) {
   if (variables != null && variables.length > rank) {
     TypeBinding variable = variables[rank];
     if (variable.hasNullTypeAnnotations()) {
       if (NullAnnotationMatching.analyse(
               variable, this.resolvedType, null, substitution, -1, null, CheckMode.BOUND_CHECK)
           .isAnyMismatch())
         scope.problemReporter().nullityMismatchTypeArgument(variable, this.resolvedType, this);
     }
   }
   checkIllegalNullAnnotation(scope);
 }
示例#19
0
 /**
  * @see
  *     org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope,
  *     org.eclipse.jdt.internal.compiler.lookup.TypeBinding,
  *     org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
  */
 public void computeConversion(
     Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
   if (runtimeTimeType == null || compileTimeType == null) return;
   // set the generic cast after the fact, once the type expectation is fully known (no need for
   // strict cast)
   if (this.binding != null && this.binding.isValidBinding()) {
     MethodBinding originalBinding = this.binding.original();
     TypeBinding originalType = originalBinding.returnType;
     // extra cast needed if method return type is type variable
     if (originalType.leafComponentType().isTypeVariable()) {
       TypeBinding targetType =
           (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType())
               ? compileTimeType // unboxing: checkcast before conversion
               : runtimeTimeType;
       this.valueCast = originalType.genericCast(targetType);
     } else if (this.binding == scope.environment().arrayClone
         && runtimeTimeType.id != TypeIds.T_JavaLangObject
         && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
       // from 1.5 source level on, array#clone() resolves to array type, but codegen to
       // #clone()Object - thus require extra inserted cast
       this.valueCast = runtimeTimeType;
     }
     if (this.valueCast instanceof ReferenceBinding) {
       ReferenceBinding referenceCast = (ReferenceBinding) this.valueCast;
       if (!referenceCast.canBeSeenBy(scope)) {
         scope
             .problemReporter()
             .invalidType(
                 this,
                 new ProblemReferenceBinding(
                     CharOperation.splitOn('.', referenceCast.shortReadableName()),
                     referenceCast,
                     ProblemReasons.NotVisible));
       }
     }
   }
   super.computeConversion(scope, runtimeTimeType, compileTimeType);
 }
示例#20
0
 /* check for use of protected role (for parameterized/qualified type references). */
 protected boolean isIllegalQualifiedUseOfProtectedRole(Scope scope) {
   // implies ReferenceBinding
   if (((ReferenceBinding) this.resolvedType).isProtected() // here we only check protected roles
       && !this.getBaseclassDecapsulation().isAllowed()) {
     scope.problemReporter().qualifiedProtectedRole(this, (ReferenceBinding) this.resolvedType);
     // keep a problem binding,  clients may be interested in this information, see
     // CodeSelectionTests.testRoleCreation3
     this.resolvedType =
         new ProblemReferenceBinding(
             ((ReferenceBinding) this.resolvedType).compoundName,
             (ReferenceBinding) this.resolvedType,
             ProblemReasons.NotVisible);
     return true;
   }
   return false;
 }
示例#21
0
  /* Answer true if the method use is considered deprecated.
   * An access in the same compilation unit is allowed.
   */
  public final boolean isMethodUseDeprecated(
      MethodBinding method, Scope scope, boolean isExplicitUse) {
    // ignore references insing Javadoc comments
    if ((this.bits & ASTNode.InsideJavadoc) == 0
        && method.isOrEnclosedByPrivateType()
        && !scope.isDefinedInMethod(method)) {
      // ignore cases where method is used from inside itself (e.g. direct recursions)
      method.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
    }

    // TODO (maxime) consider separating concerns between deprecation and access restriction.
    // 				 Caveat: this was not the case when access restriction funtion was added.
    if (isExplicitUse && (method.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0) {
      // note: explicit constructors calls warnings are kept despite the 'new C1()' case (two
      //       warnings, one on type, the other on constructor), because of the 'super()' case.
      AccessRestriction restriction =
          scope.environment().getAccessRestriction(method.declaringClass.erasure());
      if (restriction != null) {
        scope
            .problemReporter()
            .forbiddenReference(
                method,
                this,
                restriction.classpathEntryType,
                restriction.classpathEntryName,
                restriction.getProblemId());
      }
    }

    if (!method.isViewedAsDeprecated()) return false;

    // inside same unit - no report
    if (scope.isDefinedInSameUnit(method.declaringClass)) return false;

    // non explicit use and non explicitly deprecated - no report
    if (!isExplicitUse && (method.modifiers & ClassFileConstants.AccDeprecated) == 0) {
      return false;
    }

    // if context is deprecated, may avoid reporting
    if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode
        && scope.isInsideDeprecatedCode()) return false;
    return true;
  }
 /** @see org.eclipse.jdt.internal.compiler.ast.Expression#postConversionType(Scope) */
 public TypeBinding postConversionType(Scope scope) {
   TypeBinding convertedType = this.resolvedType;
   if (this.genericCast != null) convertedType = this.genericCast;
   int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4;
   switch (runtimeType) {
     case T_boolean:
       convertedType = TypeBinding.BOOLEAN;
       break;
     case T_byte:
       convertedType = TypeBinding.BYTE;
       break;
     case T_short:
       convertedType = TypeBinding.SHORT;
       break;
     case T_char:
       convertedType = TypeBinding.CHAR;
       break;
     case T_int:
       convertedType = TypeBinding.INT;
       break;
     case T_float:
       convertedType = TypeBinding.FLOAT;
       break;
     case T_long:
       convertedType = TypeBinding.LONG;
       break;
     case T_double:
       convertedType = TypeBinding.DOUBLE;
       break;
     default:
   }
   if ((this.implicitConversion & TypeIds.BOXING) != 0) {
     convertedType = scope.environment().computeBoxingType(convertedType);
   }
   return convertedType;
 }
示例#23
0
  /* Answer true if the type use is considered deprecated.
   * An access in the same compilation unit is allowed.
   */
  public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) {

    if (type.isArrayType()) {
      type = ((ArrayBinding) type).leafComponentType;
    }
    if (type.isBaseType()) return false;

    ReferenceBinding refType = (ReferenceBinding) type;
    // ignore references insing Javadoc comments
    if ((this.bits & ASTNode.InsideJavadoc) == 0
        && refType.isOrEnclosedByPrivateType()
        && !scope.isDefinedInType(refType)) {
      // ignore cases where type is used from inside itself
      ((ReferenceBinding) refType.erasure()).modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
    }

    if (refType.hasRestrictedAccess()) {
      AccessRestriction restriction = scope.environment().getAccessRestriction(type.erasure());
      if (restriction != null) {
        scope
            .problemReporter()
            .forbiddenReference(
                type,
                this,
                restriction.classpathEntryType,
                restriction.classpathEntryName,
                restriction.getProblemId());
      }
    }

    // force annotations resolution before deciding whether the type may be deprecated
    refType.initializeDeprecatedAnnotationTagBits();

    if (!refType.isViewedAsDeprecated()) return false;

    // inside same unit - no report
    if (scope.isDefinedInSameUnit(refType)) return false;

    // if context is deprecated, may avoid reporting
    if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode
        && scope.isInsideDeprecatedCode()) return false;
    return true;
  }
示例#24
0
  public final boolean isFieldUseDeprecated(
      FieldBinding field, Scope scope, boolean isStrictlyAssigned) {
    // ignore references insing Javadoc comments
    if ((this.bits & ASTNode.InsideJavadoc) == 0
        && !isStrictlyAssigned
        && field.isOrEnclosedByPrivateType()
        && !scope.isDefinedInField(field)) {
      // ignore cases where field is used from inside itself
      field.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
    }

    if ((field.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0) {
      AccessRestriction restriction =
          scope.environment().getAccessRestriction(field.declaringClass.erasure());
      if (restriction != null) {
        scope
            .problemReporter()
            .forbiddenReference(
                field,
                this,
                restriction.classpathEntryType,
                restriction.classpathEntryName,
                restriction.getProblemId());
      }
    }

    if (!field.isViewedAsDeprecated()) return false;

    // inside same unit - no report
    if (scope.isDefinedInSameUnit(field.declaringClass)) return false;

    // if context is deprecated, may avoid reporting
    if (!scope.compilerOptions().reportDeprecationInsideDeprecatedCode
        && scope.isInsideDeprecatedCode()) return false;
    return true;
  }
示例#25
0
 public boolean checkUnsafeCast(
     Scope scope,
     TypeBinding castType,
     TypeBinding expressionType,
     TypeBinding match,
     boolean isNarrowing) {
   if (match == castType) {
     if (!isNarrowing
         && match
             == this.resolvedType
                 .leafComponentType()) { // do not tag as unnecessary when recursing through upper
       // bounds
       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.isBoundParameterizedType()) {
         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.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 (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.isBoundParameterizedType() || leafType.isTypeVariable())) {
         this.bits |= ASTNode.UnsafeCast;
         return true;
       }
       break;
     case Binding.TYPE_PARAMETER:
       this.bits |= ASTNode.UnsafeCast;
       return true;
   }
   if (!isNarrowing
       && match
           == this.resolvedType
               .leafComponentType()) { // do not tag as unnecessary when recursing through upper
     // bounds
     tagAsUnnecessaryCast(scope, castType);
   }
   return true;
 }
 /**
  * @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
  */
 public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
   // null is not instanceof Type, recognize direct scenario
   if (this.expression.resolvedType != TypeBinding.NULL)
     scope.problemReporter().unnecessaryInstanceof(this, castType);
 }
示例#27
0
 /**
  * Record a null reference for use by deferred checks. Only looping or finally contexts really
  * record that information. The context may emit an error immediately depending on the status of
  * local against flowInfo and its nature (only looping of finally contexts defer part of the
  * checks; nonetheless, contexts that are nested into a looping or a finally context get affected
  * and delegate some checks to their enclosing context).
  *
  * @param scope the scope into which the check is performed
  * @param local the local variable involved in the check
  * @param location the location triggering the analysis, for normal null dereference this is an
  *     expression resolving to 'local', for resource leaks it is an early exit statement.
  * @param checkType the status against which the check must be performed; one of {@link
  *     #CAN_ONLY_NULL CAN_ONLY_NULL}, {@link #CAN_ONLY_NULL_NON_NULL CAN_ONLY_NULL_NON_NULL},
  *     {@link #MAY_NULL MAY_NULL}, potentially combined with a context indicator (one of {@link
  *     #IN_COMPARISON_NULL}, {@link #IN_COMPARISON_NON_NULL}, {@link #IN_ASSIGNMENT} or {@link
  *     #IN_INSTANCEOF}) and a bit to indicate whether the reference is being recorded inside an
  *     assert, {@link #HIDE_NULL_COMPARISON_WARNING}
  * @param flowInfo the flow info at the check point; deferring contexts will perform supplementary
  *     checks against flow info instances that cannot be known at the time of calling this method
  *     (they are influenced by code that follows the current point)
  */
 public void recordUsingNullReference(
     Scope scope, LocalVariableBinding local, ASTNode location, int checkType, FlowInfo flowInfo) {
   if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0 || flowInfo.isDefinitelyUnknown(local)) {
     return;
   }
   // if reference is being recorded inside an assert, we will not raise redundant null check
   // warnings
   checkType |= (this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING);
   int checkTypeWithoutHideNullWarning =
       checkType & ~FlowContext.HIDE_NULL_COMPARISON_WARNING_MASK;
   switch (checkTypeWithoutHideNullWarning) {
     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NULL:
     case CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL:
       if (flowInfo.isDefinitelyNonNull(local)) {
         if (checkTypeWithoutHideNullWarning
             == (CAN_ONLY_NULL_NON_NULL | IN_COMPARISON_NON_NULL)) {
           if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) {
             scope.problemReporter().localVariableRedundantCheckOnNonNull(local, location);
           }
           flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
         } else {
           scope.problemReporter().localVariableNonNullComparedToNull(local, location);
           flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
         }
         return;
       } else if (flowInfo.cannotBeDefinitelyNullOrNonNull(local)) {
         return;
       }
       // $FALL-THROUGH$
     case CAN_ONLY_NULL | IN_COMPARISON_NULL:
     case CAN_ONLY_NULL | IN_COMPARISON_NON_NULL:
     case CAN_ONLY_NULL | IN_ASSIGNMENT:
     case CAN_ONLY_NULL | IN_INSTANCEOF:
       Expression reference = (Expression) location;
       if (flowInfo.isDefinitelyNull(local)) {
         switch (checkTypeWithoutHideNullWarning & CONTEXT_MASK) {
           case FlowContext.IN_COMPARISON_NULL:
             if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL)
                 && (reference.implicitConversion & TypeIds.UNBOXING)
                     != 0) { // check for auto-unboxing first and report appropriate warning
               scope.problemReporter().localVariableNullReference(local, reference);
               return;
             }
             if ((checkType & HIDE_NULL_COMPARISON_WARNING) == 0) {
               scope.problemReporter().localVariableRedundantCheckOnNull(local, reference);
             }
             flowInfo.initsWhenFalse().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
             return;
           case FlowContext.IN_COMPARISON_NON_NULL:
             if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL)
                 && (reference.implicitConversion & TypeIds.UNBOXING)
                     != 0) { // check for auto-unboxing first and report appropriate warning
               scope.problemReporter().localVariableNullReference(local, reference);
               return;
             }
             scope.problemReporter().localVariableNullComparedToNonNull(local, reference);
             flowInfo.initsWhenTrue().setReachMode(FlowInfo.UNREACHABLE_BY_NULLANALYSIS);
             return;
           case FlowContext.IN_ASSIGNMENT:
             scope.problemReporter().localVariableRedundantNullAssignment(local, reference);
             return;
           case FlowContext.IN_INSTANCEOF:
             scope.problemReporter().localVariableNullInstanceof(local, reference);
             return;
         }
       } else if (flowInfo.isPotentiallyNull(local)) {
         switch (checkTypeWithoutHideNullWarning & CONTEXT_MASK) {
           case FlowContext.IN_COMPARISON_NULL:
             if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL)
                 && (reference.implicitConversion & TypeIds.UNBOXING)
                     != 0) { // check for auto-unboxing first and report appropriate warning
               scope.problemReporter().localVariablePotentialNullReference(local, reference);
               return;
             }
             break;
           case FlowContext.IN_COMPARISON_NON_NULL:
             if (((checkTypeWithoutHideNullWarning & CHECK_MASK) == CAN_ONLY_NULL)
                 && (reference.implicitConversion & TypeIds.UNBOXING)
                     != 0) { // check for auto-unboxing first and report appropriate warning
               scope.problemReporter().localVariablePotentialNullReference(local, reference);
               return;
             }
             break;
         }
       } else if (flowInfo.cannotBeDefinitelyNullOrNonNull(local)) {
         return;
       }
       break;
     case MAY_NULL:
       if (flowInfo.isDefinitelyNull(local)) {
         scope.problemReporter().localVariableNullReference(local, location);
         return;
       }
       if (flowInfo.isPotentiallyNull(local)) {
         scope.problemReporter().localVariablePotentialNullReference(local, location);
         return;
       }
       break;
     default:
       // never happens
   }
   if (this.parent != null) {
     this.parent.recordUsingNullReference(scope, local, location, checkType, flowInfo);
   }
 }
示例#28
0
  public void checkExceptionHandlers(
      TypeBinding[] raisedExceptions, ASTNode location, FlowInfo flowInfo, BlockScope scope) {
    // check that all the argument exception types are handled
    // JDK Compatible implementation - when an exception type is thrown,
    // all related catch blocks are marked as reachable... instead of those only
    // until the point where it is safely handled (Smarter - see comment at the end)
    int remainingCount; // counting the number of remaining unhandled exceptions
    int raisedCount; // total number of exceptions raised
    if ((raisedExceptions == null) || ((raisedCount = raisedExceptions.length) == 0)) return;
    remainingCount = raisedCount;

    // duplicate the array of raised exceptions since it will be updated
    // (null replaces any handled exception)
    System.arraycopy(
        raisedExceptions, 0, (raisedExceptions = new TypeBinding[raisedCount]), 0, raisedCount);
    FlowContext traversedContext = this;

    ArrayList abruptlyExitedLoops = null;
    while (traversedContext != null) {
      SubRoutineStatement sub;
      if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) {
        // traversing a non-returning subroutine means that all unhandled
        // exceptions will actually never get sent...
        return;
      }
      // filter exceptions that are locally caught from the innermost enclosing
      // try statement to the outermost ones.
      if (traversedContext instanceof ExceptionHandlingFlowContext) {
        ExceptionHandlingFlowContext exceptionContext =
            (ExceptionHandlingFlowContext) traversedContext;
        ReferenceBinding[] caughtExceptions;
        if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) {
          int caughtCount = caughtExceptions.length;
          boolean[] locallyCaught = new boolean[raisedCount]; // at most

          for (int caughtIndex = 0; caughtIndex < caughtCount; caughtIndex++) {
            ReferenceBinding caughtException = caughtExceptions[caughtIndex];
            for (int raisedIndex = 0; raisedIndex < raisedCount; raisedIndex++) {
              TypeBinding raisedException;
              if ((raisedException = raisedExceptions[raisedIndex]) != null) {
                FlowInfo exceptionFlow = flowInfo;
                int state =
                    caughtException == null
                        ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */
                        : Scope.compareTypes(raisedException, caughtException);
                if (abruptlyExitedLoops != null
                    && caughtException != null
                    && state != Scope.NOT_RELATED) {
                  for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size();
                      i < abruptlyExitedLoopsCount;
                      i++) {
                    LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i);
                    loop.recordCatchContextOfEscapingException(
                        exceptionContext, caughtException, flowInfo);
                  }
                  exceptionFlow =
                      FlowInfo.DEAD_END; // don't use flow info on first round, flow info will be
                  // evaluated during loopback simulation
                }
                switch (state) {
                  case Scope.EQUAL_OR_MORE_SPECIFIC:
                    exceptionContext.recordHandlingException(
                        caughtException,
                        exceptionFlow.unconditionalInits(),
                        raisedException,
                        raisedException, // precise exception that will be caught
                        location,
                        locallyCaught[raisedIndex]);
                    // was already definitely caught ?
                    if (!locallyCaught[raisedIndex]) {
                      locallyCaught[raisedIndex] = true;
                      // remember that this exception has been definitely caught
                      remainingCount--;
                    }
                    break;
                  case Scope.MORE_GENERIC:
                    exceptionContext.recordHandlingException(
                        caughtException,
                        exceptionFlow.unconditionalInits(),
                        raisedException,
                        caughtException,
                        location,
                        false);
                    // was not caught already per construction
                }
              }
            }
          }
          // remove locally caught exceptions from the remaining ones
          for (int i = 0; i < raisedCount; i++) {
            if (locallyCaught[i]) {
              raisedExceptions[i] = null; // removed from the remaining ones.
            }
          }
        }
        // method treatment for unchecked exceptions
        if (exceptionContext.isMethodContext) {
          for (int i = 0; i < raisedCount; i++) {
            TypeBinding raisedException;
            if ((raisedException = raisedExceptions[i]) != null) {
              if (raisedException.isUncheckedException(false)) {
                remainingCount--;
                raisedExceptions[i] = null;
              }
            }
          }
          boolean shouldMergeUnhandledException =
              exceptionContext instanceof ExceptionInferenceFlowContext;
          // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
          // clause will be fixed up later as per JLS 8.6).
          if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) {
            AbstractMethodDeclaration method =
                (AbstractMethodDeclaration) exceptionContext.associatedNode;
            if (method.isConstructor() && method.binding.declaringClass.isAnonymousType())
              shouldMergeUnhandledException = true;
          }
          if (shouldMergeUnhandledException) {
            for (int i = 0; i < raisedCount; i++) {
              TypeBinding raisedException;
              if ((raisedException = raisedExceptions[i]) != null) {
                exceptionContext.mergeUnhandledException(raisedException);
              }
            }
            return; // no need to complain, will fix up constructor/lambda exceptions
          }
          break; // not handled anywhere, thus jump to error handling
        }
      } else if (traversedContext instanceof LoopingFlowContext) {
        if (abruptlyExitedLoops == null) {
          abruptlyExitedLoops = new ArrayList(5);
        }
        abruptlyExitedLoops.add(traversedContext);
      }
      if (remainingCount == 0) return;

      traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

      if (traversedContext instanceof InsideSubRoutineFlowContext) {
        ASTNode node = traversedContext.associatedNode;
        if (node instanceof TryStatement) {
          TryStatement tryStatement = (TryStatement) node;
          flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
        }
      }
      traversedContext = traversedContext.getLocalParent();
    }
    // if reaches this point, then there are some remaining unhandled exception types.
    nextReport:
    for (int i = 0; i < raisedCount; i++) {
      TypeBinding exception;
      if ((exception = raisedExceptions[i]) != null) {
        // only one complaint if same exception declared to be thrown more than once
        for (int j = 0; j < i; j++) {
          if (TypeBinding.equalsEquals(raisedExceptions[j], exception))
            continue nextReport; // already reported
        }
        scope.problemReporter().unhandledException(exception, location);
      }
    }
  }
示例#29
0
  /**
   * @param isExceptionOnAutoClose This is for checking exception handlers for exceptions raised
   *     during the auto close of resources inside a try with resources statement. (Relevant for
   *     source levels 1.7 and above only)
   */
  public void checkExceptionHandlers(
      TypeBinding raisedException,
      ASTNode location,
      FlowInfo flowInfo,
      BlockScope scope,
      boolean isExceptionOnAutoClose) {
    // LIGHT-VERSION OF THE EQUIVALENT WITH AN ARRAY OF EXCEPTIONS
    // check that all the argument exception types are handled
    // JDK Compatible implementation - when an exception type is thrown,
    // all related catch blocks are marked as reachable... instead of those only
    // until the point where it is safely handled (Smarter - see comment at the end)
    FlowContext traversedContext = this;
    ArrayList abruptlyExitedLoops = null;
    if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7
        && location instanceof ThrowStatement) {
      Expression throwExpression = ((ThrowStatement) location).exception;
      LocalVariableBinding throwArgBinding = throwExpression.localVariableBinding();
      if (throwExpression
              instanceof SingleNameReference // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350361
          && throwArgBinding instanceof CatchParameterBinding
          && throwArgBinding.isEffectivelyFinal()) {
        CatchParameterBinding parameter = (CatchParameterBinding) throwArgBinding;
        checkExceptionHandlers(parameter.getPreciseTypes(), location, flowInfo, scope);
        return;
      }
    }
    while (traversedContext != null) {
      SubRoutineStatement sub;
      if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) {
        // traversing a non-returning subroutine means that all unhandled
        // exceptions will actually never get sent...
        return;
      }

      // filter exceptions that are locally caught from the innermost enclosing
      // try statement to the outermost ones.
      if (traversedContext instanceof ExceptionHandlingFlowContext) {
        ExceptionHandlingFlowContext exceptionContext =
            (ExceptionHandlingFlowContext) traversedContext;
        ReferenceBinding[] caughtExceptions;
        if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) {
          boolean definitelyCaught = false;
          for (int caughtIndex = 0, caughtCount = caughtExceptions.length;
              caughtIndex < caughtCount;
              caughtIndex++) {
            ReferenceBinding caughtException = caughtExceptions[caughtIndex];
            FlowInfo exceptionFlow = flowInfo;
            int state =
                caughtException == null
                    ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */
                    : Scope.compareTypes(raisedException, caughtException);
            if (abruptlyExitedLoops != null
                && caughtException != null
                && state != Scope.NOT_RELATED) {
              for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size();
                  i < abruptlyExitedLoopsCount;
                  i++) {
                LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i);
                loop.recordCatchContextOfEscapingException(
                    exceptionContext, caughtException, flowInfo);
              }
              exceptionFlow =
                  FlowInfo
                      .DEAD_END; // don't use flow info on first round, flow info will be evaluated
              // during loopback simulation
            }
            switch (state) {
              case Scope.EQUAL_OR_MORE_SPECIFIC:
                exceptionContext.recordHandlingException(
                    caughtException,
                    exceptionFlow.unconditionalInits(),
                    raisedException,
                    raisedException, // precise exception that will be caught
                    location,
                    definitelyCaught);
                // was it already definitely caught ?
                definitelyCaught = true;
                break;
              case Scope.MORE_GENERIC:
                exceptionContext.recordHandlingException(
                    caughtException,
                    exceptionFlow.unconditionalInits(),
                    raisedException,
                    caughtException,
                    location,
                    false);
                // was not caught already per construction
            }
          }
          if (definitelyCaught) return;
        }
        // method treatment for unchecked exceptions
        if (exceptionContext.isMethodContext) {
          if (raisedException.isUncheckedException(false)) return;
          boolean shouldMergeUnhandledExceptions =
              exceptionContext instanceof ExceptionInferenceFlowContext;

          // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
          // clause will be fixed up later as per JLS 8.6).
          if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) {
            AbstractMethodDeclaration method =
                (AbstractMethodDeclaration) exceptionContext.associatedNode;
            if (method.isConstructor() && method.binding.declaringClass.isAnonymousType())
              shouldMergeUnhandledExceptions = true;
          }
          if (shouldMergeUnhandledExceptions) {
            exceptionContext.mergeUnhandledException(raisedException);
            return; // no need to complain, will fix up constructor/lambda exceptions
          }
          break; // not handled anywhere, thus jump to error handling
        }
      } else if (traversedContext instanceof LoopingFlowContext) {
        if (abruptlyExitedLoops == null) {
          abruptlyExitedLoops = new ArrayList(5);
        }
        abruptlyExitedLoops.add(traversedContext);
      }

      traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

      if (!isExceptionOnAutoClose) {
        if (traversedContext instanceof InsideSubRoutineFlowContext) {
          ASTNode node = traversedContext.associatedNode;
          if (node instanceof TryStatement) {
            TryStatement tryStatement = (TryStatement) node;
            flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
          }
        }
      }
      traversedContext = traversedContext.getLocalParent();
    }
    // if reaches this point, then there are some remaining unhandled exception types.
    if (isExceptionOnAutoClose) {
      scope.problemReporter().unhandledExceptionFromAutoClose(raisedException, location);
    } else {
      scope.problemReporter().unhandledException(raisedException, location);
    }
  }
  private TypeBinding internalResolveLeafType(
      Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
    ReferenceBinding currentType;
    if (enclosingType == null) {
      this.resolvedType = scope.getType(this.token);
      if (this.resolvedType.isValidBinding()) {
        currentType = (ReferenceBinding) this.resolvedType;
      } else {
        reportInvalidType(scope);
        switch (this.resolvedType.problemId()) {
          case ProblemReasons.NotFound:
          case ProblemReasons.NotVisible:
          case ProblemReasons.InheritedNameHidesEnclosingName:
            TypeBinding type = this.resolvedType.closestMatch();
            if (type instanceof ReferenceBinding) {
              currentType = (ReferenceBinding) type;
              break;
            }
            // $FALL-THROUGH$ - unable to complete type binding, but still resolve type arguments
          default:
            boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
            int argLength = this.typeArguments.length;
            for (int i = 0; i < argLength; i++) {
              TypeReference typeArgument = this.typeArguments[i];
              if (isClassScope) {
                typeArgument.resolveType((ClassScope) scope);
              } else {
                typeArgument.resolveType((BlockScope) scope, checkBounds);
              }
            }
            return null;
        }
        // be resilient, still attempt resolving arguments
      }
      enclosingType = currentType.enclosingType(); // if member type
      if (enclosingType != null) {
        enclosingType =
            currentType.isStatic()
                ? (ReferenceBinding)
                    scope
                        .environment()
                        .convertToRawType(
                            enclosingType, false /*do not force conversion of enclosing types*/)
                : scope.environment().convertToParameterizedType(enclosingType);
        currentType =
            scope
                .environment()
                .createParameterizedType(
                    (ReferenceBinding) currentType.erasure(), null /* no arg */, enclosingType);
      }
    } else { // resolving member type (relatively to enclosingType)
      this.resolvedType = currentType = scope.getMemberType(this.token, enclosingType);
      if (!this.resolvedType.isValidBinding()) {
        scope.problemReporter().invalidEnclosingType(this, currentType, enclosingType);
        return null;
      }
      if (isTypeUseDeprecated(currentType, scope))
        scope.problemReporter().deprecatedType(currentType, this);
      ReferenceBinding currentEnclosing = currentType.enclosingType();
      if (currentEnclosing != null && currentEnclosing.erasure() != enclosingType.erasure()) {
        enclosingType =
            currentEnclosing; // inherited member type, leave it associated with its enclosing
                              // rather than subtype
      }
    }

    // check generic and arity
    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
    TypeReference keep = null;
    if (isClassScope) {
      keep = ((ClassScope) scope).superTypeReference;
      ((ClassScope) scope).superTypeReference = null;
    }
    int argLength = this.typeArguments.length;
    TypeBinding[] argTypes = new TypeBinding[argLength];
    boolean argHasError = false;
    ReferenceBinding currentOriginal = (ReferenceBinding) currentType.original();
    for (int i = 0; i < argLength; i++) {
      TypeReference typeArgument = this.typeArguments[i];
      TypeBinding argType =
          isClassScope
              ? typeArgument.resolveTypeArgument((ClassScope) scope, currentOriginal, i)
              : typeArgument.resolveTypeArgument((BlockScope) scope, currentOriginal, i);
      this.bits |= (typeArgument.bits & ASTNode.HasTypeAnnotations);
      if (argType == null) {
        argHasError = true;
      } else {
        if (typeArgument.annotations != null)
          argTypes[i] =
              captureTypeAnnotations(scope, enclosingType, argType, typeArgument.annotations[0]);
        else argTypes[i] = argType;
      }
    }
    if (argHasError) {
      return null;
    }
    if (isClassScope) {
      ((ClassScope) scope).superTypeReference = keep;
      if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null;
    }

    final boolean isDiamond = (this.bits & ASTNode.IsDiamond) != 0;
    TypeVariableBinding[] typeVariables = currentOriginal.typeVariables();
    if (typeVariables == Binding.NO_TYPE_VARIABLES) { // non generic invoked with arguments
      boolean isCompliant15 =
          scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5;
      if ((currentOriginal.tagBits & TagBits.HasMissingType) == 0) {
        if (isCompliant15) { // below 1.5, already reported as syntax error
          this.resolvedType = currentType;
          scope
              .problemReporter()
              .nonGenericTypeCannotBeParameterized(0, this, currentType, argTypes);
          return null;
        }
      }
      // resilience do not rebuild a parameterized type unless compliance is allowing it
      if (!isCompliant15) {
        if (!this.resolvedType.isValidBinding()) return currentType;
        return this.resolvedType = currentType;
      }
      // if missing generic type, and compliance >= 1.5, then will rebuild a parameterized binding
    } else if (argLength != typeVariables.length) {
      if (!isDiamond) { // check arity, IsDiamond never set for 1.6-
        scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
        return null;
      }
    } else if (!currentType.isStatic()) {
      ReferenceBinding actualEnclosing = currentType.enclosingType();
      if (actualEnclosing != null && actualEnclosing.isRawType()) {
        scope
            .problemReporter()
            .rawMemberTypeCannotBeParameterized(
                this,
                scope.environment().createRawType(currentOriginal, actualEnclosing),
                argTypes);
        return null;
      }
    }

    ParameterizedTypeBinding parameterizedType =
        scope.environment().createParameterizedType(currentOriginal, argTypes, enclosingType);
    // check argument type compatibility for non <> cases - <> case needs no bounds check, we will
    // scream foul if needed during inference.
    if (!isDiamond) {
      if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method
                       // resolution
      parameterizedType.boundCheck(scope, this.typeArguments);
      else scope.deferBoundCheck(this);
    }
    if (isTypeUseDeprecated(parameterizedType, scope))
      reportDeprecatedType(parameterizedType, scope);

    if (!this.resolvedType.isValidBinding()) {
      return parameterizedType;
    }
    return this.resolvedType = parameterizedType;
  }