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(..) } }
/** * 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; }
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); }
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); } } }
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; }
/** * @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); }
/** 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); } }
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); }
/** * 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); }
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; } }
/* 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; }
/* 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; }
/* 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; }
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); }
/** * @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); }
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; }
/** * @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); }
/** * 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); } }
protected TypeBinding internalResolveType(Scope scope, int location) { // handle the error here this.constant = Constant.NotAConstant; if (this.resolvedType != null) { // is a shared type reference which was already resolved if (this.resolvedType.isValidBinding()) { return this.resolvedType; } else { switch (this.resolvedType.problemId()) { case ProblemReasons.NotFound: case ProblemReasons.NotVisible: case ProblemReasons.InheritedNameHidesEnclosingName: TypeBinding type = this.resolvedType.closestMatch(); if (type == null) return null; return scope .environment() .convertToRawType(type, false /*do not force conversion of enclosing types*/); default: return null; } } } boolean hasError; // {ObjectTeams: don't let SelectionNodeFound(null) prevent alternate searching strategies: SelectionNodeFound caughtException = null; TypeBinding type = null; try { // base import scope first: CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult(); CompilationResult.CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext()); try { type = checkResolveUsingBaseImportScope( scope, location, false); // apply TOLERATE strategy only as a last resort below // copied from below: if (type != null && type.isValidBinding()) { 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); } return type; } } catch (SelectionNodeFound snf) { if (snf.binding != null) throw snf; // found a valid node. caughtException = snf; } finally { if (caughtException != null || (type == null) || !type.isValidBinding()) compilationResult.rollBack(cp); } // ~orig~: type = this.resolvedType = getTypeBinding(scope); if (type == null) { return null; // detected cycle while resolving hierarchy } // :~giro~ } catch (SelectionNodeFound snf) { if (snf.binding != null) throw snf; // found a valid node. caughtException = snf; } // a third chance trying an anchored type: try { if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) { // anchored type TypeBinding result = resolveAnchoredType(scope); if (result != null) // did we do any better than before? type = this.resolvedType = result; // if non-null but ProblemBinding report below. } } catch (SelectionNodeFound snf2) { caughtException = snf2; // throw the newer exception instead. } // a forth chance trying a TOLERATED base imported type: try { if ((caughtException != null) || (this.resolvedType.problemId() == ProblemReasons.NotFound)) { if (this.baseclassDecapsulation == DecapsulationState.TOLERATED) { TypeBinding result = checkResolveUsingBaseImportScope(scope, -1, true); if (result != null) // did we do any better than before? type = this.resolvedType = result; // if non-null but ProblemBinding report below. } } } catch (SelectionNodeFound snf2) { caughtException = snf2; // throw the newer exception instead. } finally { // the attempt to prevent an exception failed: if (caughtException != null) throw caughtException; } // SH} if ((hasError = !type.isValidBinding()) == true) { reportInvalidType(scope); switch (type.problemId()) { case ProblemReasons.NotFound: case ProblemReasons.NotVisible: case ProblemReasons.InheritedNameHidesEnclosingName: type = type.closestMatch(); if (type == null) return null; break; default: return null; } } // {ObjectTeams: Split method to make tail accessible: return checkResolvedType(type, scope, location, hasError); }
protected void reportDeprecatedType(TypeBinding type, Scope scope, int index) { scope.problemReporter().deprecatedType(type, this, index); }
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; }