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; }
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; }
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); }
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); }
/** 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 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; }
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 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; }
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); }
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); } } }
/** * 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); }
/** * @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); }
/* 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; }
/** @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; }
/* 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; }
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; }
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); }
/** * 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); } }
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); } } }
/** * @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; }