// expression.implicitConversion holds the cast for baseType casting public CastExpression(Expression expression, Expression type) { this.expression = expression; this.type = type; type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage }
public TypeBinding resolveType(BlockScope scope) { // Propagate the type checking to the arguments, and check if the constructor is defined. this.constant = Constant.NotAConstant; if (this.type == null) { // initialization of an enum constant this.resolvedType = scope.enclosingReceiverType(); } else { this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); checkParameterizedAllocation: { if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>() ReferenceBinding currentType = (ReferenceBinding) this.resolvedType; if (currentType == null) return currentType; do { // isStatic() is answering true for toplevel types if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; if (currentType.isRawType()) break checkParameterizedAllocation; } while ((currentType = currentType.enclosingType()) != null); ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { if (qRef.typeArguments[i] != null) { scope .problemReporter() .illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType); break; } } } } } // will check for null after args are resolved final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0; // resolve type arguments (for generic constructor call) if (this.typeArguments != null) { int length = this.typeArguments.length; boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (isDiamond) { scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments); return null; } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // buffering the arguments' types boolean argsContainCast = false; TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { boolean argHasError = false; int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null) { argHasError = true; } } if (argHasError) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case. No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do not return the partially resolved type. */ if (isDiamond) { return null; // not the partially cooked this.resolvedType } if (this.resolvedType instanceof ReferenceBinding) { // record a best guess, for clients who need hint about possible constructor match TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0; ) { pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type } this.binding = scope.findMethod( (ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method // match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw // method (175409) closestMatch = scope .environment() .createParameterizedGenericMethod( closestMatch.original(), (RawTypeBinding) null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct // recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } return this.resolvedType; } } if (this.resolvedType == null || !this.resolvedType.isValidBinding()) { return null; } // null type denotes fake allocation for enum constant inits if (this.type != null && !this.resolvedType.canBeInstantiated()) { scope.problemReporter().cannotInstantiate(this.type, this.resolvedType); return this.resolvedType; } if (isDiamond) { TypeBinding[] inferredTypes = inferElidedTypes( ((ParameterizedTypeBinding) this.resolvedType).genericType(), null, argumentTypes, scope); if (inferredTypes == null) { scope.problemReporter().cannotInferElidedTypes(this); return this.resolvedType = null; } this.resolvedType = this.type.resolvedType = scope .environment() .createParameterizedType( ((ParameterizedTypeBinding) this.resolvedType).genericType(), inferredTypes, ((ParameterizedTypeBinding) this.resolvedType).enclosingType()); } ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType; if (!(this.binding = scope.getConstructor(allocationType, argumentTypes, this)) .isValidBinding()) { if (this.binding.declaringClass == null) { this.binding.declaringClass = allocationType; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { return null; } scope.problemReporter().invalidConstructor(this, this.binding); return this.resolvedType; } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); if (checkInvocationArguments( scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope .problemReporter() .unnecessaryTypeArgumentsForMethodInvocation( this.binding, this.genericTypeArguments, this.typeArguments); } if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) { checkTypeArgumentRedundancy( (ParameterizedTypeBinding) this.resolvedType, null, argumentTypes, scope); } final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { new ImplicitNullAnnotationVerifier( scope.environment(), compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null /*srcMethod*/, false, scope); } return allocationType; }
public TypeBinding resolveType(BlockScope scope) { // added for code assist...cannot occur with 'normal' code if (this.anonymousType == null && this.enclosingInstance == null) { return super.resolveType(scope); } // Propagate the type checking to the arguments, and checks if the constructor is defined. // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' // ClassBodyopt // ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' // ClassBodyopt this.constant = Constant.NotAConstant; TypeBinding enclosingInstanceType = null; ReferenceBinding enclosingInstanceReference = null; TypeBinding receiverType = null; boolean hasError = false; boolean enclosingInstanceContainsCast = false; boolean argsContainCast = false; if (this.enclosingInstance != null) { if (this.enclosingInstance instanceof CastExpression) { this.enclosingInstance.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on enclosingInstanceContainsCast = true; } if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null) { hasError = true; } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) { scope .problemReporter() .illegalPrimitiveOrArrayTypeForEnclosingInstance( enclosingInstanceType, this.enclosingInstance); hasError = true; } else if (this.type instanceof QualifiedTypeReference) { scope .problemReporter() .illegalUsageOfQualifiedTypeReference((QualifiedTypeReference) this.type); hasError = true; } else if (!(enclosingInstanceReference = (ReferenceBinding) enclosingInstanceType) .canBeSeenBy(scope)) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317212 enclosingInstanceType = new ProblemReferenceBinding( enclosingInstanceReference.compoundName, enclosingInstanceReference, ProblemReasons.NotVisible); scope.problemReporter().invalidType(this.enclosingInstance, enclosingInstanceType); hasError = true; } else { receiverType = ((SingleTypeReference) this.type) .resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType); if (receiverType != null && enclosingInstanceContainsCast) { CastExpression.checkNeedForEnclosingInstanceCast( scope, this.enclosingInstance, enclosingInstanceType, receiverType); } } } else { if (this.type == null) { // initialization of an enum constant receiverType = scope.enclosingSourceType(); } else { receiverType = this.type.resolveType(scope, true /* check bounds*/); checkParameterizedAllocation: { if (receiverType == null || !receiverType.isValidBinding()) break checkParameterizedAllocation; if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>() ReferenceBinding currentType = (ReferenceBinding) receiverType; do { // isStatic() is answering true for toplevel types if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0) break checkParameterizedAllocation; if (currentType.isRawType()) break checkParameterizedAllocation; } while ((currentType = currentType.enclosingType()) != null); ParameterizedQualifiedTypeReference qRef = (ParameterizedQualifiedTypeReference) this.type; for (int i = qRef.typeArguments.length - 2; i >= 0; i--) { if (qRef.typeArguments[i] != null) { scope .problemReporter() .illegalQualifiedParameterizedTypeAllocation(this.type, receiverType); break; } } } } } } if (receiverType == null || !receiverType.isValidBinding()) { hasError = true; } // resolve type arguments (for generic constructor call) final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0; if (this.typeArguments != null) { int length = this.typeArguments.length; boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (isDiamond) { scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments); return null; } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // will check for null after args are resolved TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null) { hasError = true; } } } // limit of fault-tolerance if (hasError) { /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case. No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do not return the partially resolved type. */ if (isDiamond) { return null; // not the partially cooked this.resolvedType } if (receiverType instanceof ReferenceBinding) { ReferenceBinding referenceReceiver = (ReferenceBinding) receiverType; if (receiverType.isValidBinding()) { // record a best guess, for clients who need hint about possible contructor match int length = this.arguments == null ? 0 : this.arguments.length; TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0; ) { pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type } this.binding = scope.findMethod(referenceReceiver, TypeConstants.INIT, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method // match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw // method (175409) closestMatch = scope .environment() .createParameterizedGenericMethod( closestMatch.original(), (RawTypeBinding) null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct // recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } if (this.anonymousType != null) { // insert anonymous type in scope (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=210070) scope.addAnonymousType(this.anonymousType, referenceReceiver); this.anonymousType.resolve(scope); return this.resolvedType = this.anonymousType.binding; } } return this.resolvedType = receiverType; } if (this.anonymousType == null) { // qualified allocation with no anonymous type if (!receiverType.canBeInstantiated()) { scope.problemReporter().cannotInstantiate(this.type, receiverType); return this.resolvedType = receiverType; } if (isDiamond) { TypeBinding[] inferredTypes = inferElidedTypes( ((ParameterizedTypeBinding) receiverType).genericType(), receiverType.enclosingType(), argumentTypes, scope); if (inferredTypes == null) { scope.problemReporter().cannotInferElidedTypes(this); return this.resolvedType = null; } receiverType = this.type.resolvedType = scope .environment() .createParameterizedType( ((ParameterizedTypeBinding) receiverType).genericType(), inferredTypes, ((ParameterizedTypeBinding) receiverType).enclosingType()); } ReferenceBinding allocationType = (ReferenceBinding) receiverType; if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this)) .isValidBinding()) { if (isMethodUseDeprecated(this.binding, scope, true)) { scope.problemReporter().deprecatedMethod(this.binding, this); } if (checkInvocationArguments( scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope .problemReporter() .unnecessaryTypeArgumentsForMethodInvocation( this.binding, this.genericTypeArguments, this.typeArguments); } } else { if (this.binding.declaringClass == null) { this.binding.declaringClass = allocationType; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { // problem already got signaled on type reference, do not report secondary problem return null; } scope.problemReporter().invalidConstructor(this, this.binding); return this.resolvedType = receiverType; } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, this.binding); } if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) { checkTypeArgumentRedundancy( (ParameterizedTypeBinding) receiverType, receiverType.enclosingType(), argumentTypes, scope); } // The enclosing instance must be compatible with the innermost enclosing type ReferenceBinding expectedType = this.binding.declaringClass.enclosingType(); if (expectedType != enclosingInstanceType) // must call before computeConversion() and typeMismatchError() scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType); if (enclosingInstanceType.isCompatibleWith(expectedType) || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) { this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType); return this.resolvedType = receiverType; } scope .problemReporter() .typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null); return this.resolvedType = receiverType; } else { if (isDiamond) { scope.problemReporter().diamondNotWithAnoymousClasses(this.type); return null; } } ReferenceBinding superType = (ReferenceBinding) receiverType; if (superType.isTypeVariable()) { superType = new ProblemReferenceBinding( new char[][] {superType.sourceName()}, superType, ProblemReasons.IllegalSuperTypeVariable); scope.problemReporter().invalidType(this, superType); return null; } else if (this.type != null && superType.isEnum()) { // tolerate enum constant body scope.problemReporter().cannotInstantiate(this.type, superType); return this.resolvedType = superType; } // anonymous type scenario // an anonymous class inherits from java.lang.Object when declared "after" an interface ReferenceBinding anonymousSuperclass = superType.isInterface() ? scope.getJavaLangObject() : superType; // insert anonymous type in scope scope.addAnonymousType(this.anonymousType, superType); this.anonymousType.resolve(scope); // find anonymous super constructor this.resolvedType = this.anonymousType.binding; // 1.2 change if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) { return null; // stop secondary errors } MethodBinding inheritedBinding = scope.getConstructor(anonymousSuperclass, argumentTypes, this); if (!inheritedBinding.isValidBinding()) { if (inheritedBinding.declaringClass == null) { inheritedBinding.declaringClass = anonymousSuperclass; } if (this.type != null && !this.type.resolvedType.isValidBinding()) { // problem already got signaled on type reference, do not report secondary problem return null; } scope.problemReporter().invalidConstructor(this, inheritedBinding); return this.resolvedType; } if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInConstructor(this, inheritedBinding); } if (this.enclosingInstance != null) { ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType(); if (targetEnclosing == null) { scope .problemReporter() .unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType); return this.resolvedType; } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing) && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) { scope .problemReporter() .typeMismatchError( enclosingInstanceType, targetEnclosing, this.enclosingInstance, null); return this.resolvedType; } this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType); } if (this.arguments != null) { if (checkInvocationArguments( scope, null, anonymousSuperclass, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } } if (this.typeArguments != null && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope .problemReporter() .unnecessaryTypeArgumentsForMethodInvocation( inheritedBinding, this.genericTypeArguments, this.typeArguments); } // Update the anonymous inner class : superclass, interface this.binding = this.anonymousType.createDefaultConstructorWithBinding( inheritedBinding, (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null); return this.resolvedType; }
public TypeBinding resolveType(BlockScope scope) { // Answer the signature return type // Base type promotion this.constant = Constant.NotAConstant; boolean receiverCast = false, argsContainCast = false; if (this.receiver instanceof CastExpression) { this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on receiverCast = true; } this.actualReceiverType = this.receiver.resolveType(scope); boolean receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0; if (receiverCast && this.actualReceiverType != null) { // due to change of declaring class with receiver type, only identity cast should be notified if (((CastExpression) this.receiver).expression.resolvedType == this.actualReceiverType) { scope.problemReporter().unnecessaryCast((CastExpression) this.receiver); } } // resolve type arguments (for generic constructor call) if (this.typeArguments != null) { int length = this.typeArguments.length; boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5; // typeChecks all arguments this.genericTypeArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { TypeReference typeReference = this.typeArguments[i]; if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) { argHasError = true; } if (argHasError && typeReference instanceof Wildcard) { scope.problemReporter().illegalUsageOfWildcard(typeReference); } } if (argHasError) { if (this.arguments != null) { // still attempt to resolve arguments for (int i = 0, max = this.arguments.length; i < max; i++) { this.arguments[i].resolveType(scope); } } return null; } } // will check for null after args are resolved TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; if (this.arguments != null) { boolean argHasError = false; // typeChecks all arguments int length = this.arguments.length; argumentTypes = new TypeBinding[length]; for (int i = 0; i < length; i++) { Expression argument = this.arguments[i]; if (argument instanceof CastExpression) { argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on argsContainCast = true; } if ((argumentTypes[i] = argument.resolveType(scope)) == null) { argHasError = true; } } if (argHasError) { if (this.actualReceiverType instanceof ReferenceBinding) { // record a best guess, for clients who need hint about possible method match TypeBinding[] pseudoArgs = new TypeBinding[length]; for (int i = length; --i >= 0; ) pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type this.binding = this.receiver.isImplicitThis() ? scope.getImplicitMethod(this.selector, pseudoArgs, this) : scope.findMethod( (ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this); if (this.binding != null && !this.binding.isValidBinding()) { MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch; // record the closest match, for clients who may still need hint about possible method // match if (closestMatch != null) { if (closestMatch.original().typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method // shouldn't return generic method outside its context, rather convert it to raw // method (175409) closestMatch = scope .environment() .createParameterizedGenericMethod( closestMatch.original(), (RawTypeBinding) null); } this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct // recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } } } return null; } } if (this.actualReceiverType == null) { return null; } // base type cannot receive any message if (this.actualReceiverType.isBaseType()) { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); return null; } this.binding = this.receiver.isImplicitThis() ? scope.getImplicitMethod(this.selector, argumentTypes, this) : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); if (!this.binding.isValidBinding()) { if (this.binding.declaringClass == null) { if (this.actualReceiverType instanceof ReferenceBinding) { this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; } else { scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); return null; } } // https://bugs.eclipse.org/bugs/show_bug.cgi?id=245007 avoid secondary errors in case of // missing super type for anonymous classes ... ReferenceBinding declaringClass = this.binding.declaringClass; boolean avoidSecondary = declaringClass != null && declaringClass.isAnonymousType() && declaringClass.superclass() instanceof MissingTypeBinding; if (!avoidSecondary) scope.problemReporter().invalidMethod(this, this.binding); MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch; switch (this.binding.problemId()) { case ProblemReasons.Ambiguous: break; // no resilience on ambiguous case ProblemReasons.NotVisible: case ProblemReasons.NonStaticReferenceInConstructorInvocation: case ProblemReasons.NonStaticReferenceInStaticContext: case ProblemReasons.ReceiverTypeNotVisible: case ProblemReasons.ParameterBoundMismatch: // only steal returnType in cases listed above if (closestMatch != null) this.resolvedType = closestMatch.returnType; break; } // record the closest match, for clients who may still need hint about possible method match if (closestMatch != null) { this.binding = closestMatch; MethodBinding closestMatchOriginal = closestMatch.original(); if (closestMatchOriginal.isOrEnclosedByPrivateType() && !scope.isDefinedInMethod(closestMatchOriginal)) { // ignore cases where method is used from within inside itself (e.g. direct recursions) closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; } } return (this.resolvedType != null && (this.resolvedType.tagBits & TagBits.HasMissingType) == 0) ? this.resolvedType : null; } final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.complianceLevel <= ClassFileConstants.JDK1_6 && this.binding.isPolymorphic()) { scope.problemReporter().polymorphicMethodNotBelow17(this); return null; } if (((this.bits & ASTNode.InsideExpressionStatement) != 0) && this.binding.isPolymorphic()) { // we only set the return type to be void if this method invocation is used inside an // expression statement this.binding = scope .environment() .updatePolymorphicMethodReturnType( (PolymorphicMethodBinding) this.binding, TypeBinding.VOID); } if ((this.binding.tagBits & TagBits.HasMissingType) != 0) { scope.problemReporter().missingTypeInMethod(this, this.binding); } if (!this.binding.isStatic()) { // the "receiver" must not be a type if (receiverIsType) { scope.problemReporter().mustUseAStaticMethod(this, this.binding); if (this.actualReceiverType.isRawType() && (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0 && compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType); } } else { // handle indirect inheritance thru variable secondary bound // receiver may receive generic cast, as part of implicit conversion TypeBinding oldReceiverType = this.actualReceiverType; this.actualReceiverType = this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass); this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); if (this.actualReceiverType != oldReceiverType && this.receiver.postConversionType(scope) != this .actualReceiverType) { // record need for explicit cast at codegen since // receiver could not handle it this.bits |= NeedReceiverGenericCast; } } } else { // static message invoked through receiver? legal but unoptimal (optional warning). if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) { scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding); } if (!this.receiver.isImplicitThis() && this.binding.declaringClass != this.actualReceiverType) { scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); } } if (checkInvocationArguments( scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) { this.bits |= ASTNode.Unchecked; } // -------message send that are known to fail at compile time----------- if (this.binding.isAbstract()) { if (this.receiver.isSuper()) { scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding); } // abstract private methods cannot occur nor abstract static............ } if (isMethodUseDeprecated(this.binding, scope, true)) scope.problemReporter().deprecatedMethod(this.binding, this); // from 1.5 source level on, array#clone() returns the array type (but binding still shows // Object) if (this.binding == scope.environment().arrayClone && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) { this.resolvedType = this.actualReceiverType; } else { TypeBinding returnType; if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6 returnType = this.binding.returnType; if (returnType != null) { returnType = scope.environment().convertToRawType(returnType.erasure(), true); } } else { returnType = this.binding.returnType; if (returnType != null) { returnType = returnType.capture(scope, this.sourceEnd); } } this.resolvedType = returnType; } if (this.receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) { final ReferenceContext referenceContext = scope.methodScope().referenceContext; if (referenceContext instanceof AbstractMethodDeclaration) { final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext; MethodBinding enclosingMethodBinding = abstractMethodDeclaration.binding; if (enclosingMethodBinding.isOverriding() && CharOperation.equals(this.binding.selector, enclosingMethodBinding.selector) && this.binding.areParametersEqual(enclosingMethodBinding)) { abstractMethodDeclaration.bits |= ASTNode.OverridingMethodWithSupercall; } } } if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) { scope .problemReporter() .unnecessaryTypeArgumentsForMethodInvocation( this.binding, this.genericTypeArguments, this.typeArguments); } return (this.resolvedType.tagBits & TagBits.HasMissingType) == 0 ? this.resolvedType : null; }