/* 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; }
public static boolean checkInvocationArguments( BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding method, Expression[] arguments, TypeBinding[] argumentTypes, boolean argsContainCast, InvocationSite invocationSite) { TypeBinding[] params = method.parameters; int paramLength = params.length; boolean isRawMemberInvocation = !method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters(); boolean uncheckedBoundCheck = (method.tagBits & TagBits.HasUncheckedTypeArgumentForBoundCheck) != 0; MethodBinding rawOriginalGenericMethod = null; if (!isRawMemberInvocation) { if (method instanceof ParameterizedGenericMethodBinding) { ParameterizedGenericMethodBinding paramMethod = (ParameterizedGenericMethodBinding) method; if (paramMethod.isRaw && method.hasSubstitutedParameters()) { rawOriginalGenericMethod = method.original(); } } } int invocationStatus = INVOCATION_ARGUMENT_OK; if (arguments == null) { if (method.isVarargs()) { TypeBinding parameterType = ((ArrayBinding) params[paramLength - 1]) .elementsType(); // no element was supplied for vararg parameter if (!parameterType.isReifiable()) { scope .problemReporter() .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite); } } } else { if (method.isVarargs()) { // 4 possibilities exist for a call to the vararg method foo(int i, long ... value) : // foo(1), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new long[] {1, 2}) int lastIndex = paramLength - 1; for (int i = 0; i < lastIndex; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; invocationStatus |= checkInvocationArgument( scope, arguments[i], params[i], argumentTypes[i], originalRawParam); } int argLength = arguments.length; if (lastIndex < argLength) { // vararg argument was provided TypeBinding parameterType = params[lastIndex]; TypeBinding originalRawParam = null; if (paramLength != argLength || parameterType.dimensions() != argumentTypes[lastIndex].dimensions()) { parameterType = ((ArrayBinding) parameterType) .elementsType(); // single element was provided for vararg parameter if (!parameterType.isReifiable()) { scope .problemReporter() .unsafeGenericArrayForVarargs(parameterType, (ASTNode) invocationSite); } originalRawParam = rawOriginalGenericMethod == null ? null : ((ArrayBinding) rawOriginalGenericMethod.parameters[lastIndex]) .elementsType(); } for (int i = lastIndex; i < argLength; i++) { invocationStatus |= checkInvocationArgument( scope, arguments[i], parameterType, argumentTypes[i], originalRawParam); } } if (paramLength == argLength) { // 70056 int varargsIndex = paramLength - 1; ArrayBinding varargsType = (ArrayBinding) params[varargsIndex]; TypeBinding lastArgType = argumentTypes[varargsIndex]; int dimensions; if (lastArgType == TypeBinding.NULL) { if (!(varargsType.leafComponentType().isBaseType() && varargsType.dimensions() == 1)) scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } else if (varargsType.dimensions <= (dimensions = lastArgType.dimensions())) { if (lastArgType.leafComponentType().isBaseType()) { dimensions--; } if (varargsType.dimensions < dimensions) { scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } else if (varargsType.dimensions == dimensions && lastArgType != varargsType && lastArgType.leafComponentType().erasure() != varargsType.leafComponentType.erasure() && lastArgType.isCompatibleWith(varargsType.elementsType()) && lastArgType.isCompatibleWith(varargsType)) { scope.problemReporter().varargsArgumentNeedCast(method, lastArgType, invocationSite); } } } } else { for (int i = 0; i < paramLength; i++) { TypeBinding originalRawParam = rawOriginalGenericMethod == null ? null : rawOriginalGenericMethod.parameters[i]; invocationStatus |= checkInvocationArgument( scope, arguments[i], params[i], argumentTypes[i], originalRawParam); } } if (argsContainCast) { CastExpression.checkNeedForArgumentCasts( scope, receiver, receiverType, method, arguments, argumentTypes, invocationSite); } } if ((invocationStatus & INVOCATION_ARGUMENT_WILDCARD) != 0) { scope .problemReporter() .wildcardInvocation((ASTNode) invocationSite, receiverType, method, argumentTypes); } else if (!method.isStatic() && !receiverType.isUnboundWildcard() && method.declaringClass.isRawType() && method.hasSubstitutedParameters()) { scope.problemReporter().unsafeRawInvocation((ASTNode) invocationSite, method); } else if (rawOriginalGenericMethod != null || uncheckedBoundCheck || ((invocationStatus & INVOCATION_ARGUMENT_UNCHECKED) != 0 && method instanceof ParameterizedGenericMethodBinding /*&& method.returnType != scope.environment().convertToRawType(method.returnType.erasure(), true)*/ )) { scope .problemReporter() .unsafeRawGenericMethodInvocation((ASTNode) invocationSite, method, argumentTypes); return true; } return false; }
/** * The main algorithm in this class. * * @param currentMethod focus method * @param srcMethod AST of 'currentMethod' if present * @param hasReturnNonNullDefault is a @NonNull default applicable for the return type of * currentMethod? * @param hasParameterNonNullDefault is a @NonNull default applicable for parameters of * currentMethod? * @param shouldComplain should we report any errors found? (see also comment about flows into * this method, below). * @param inheritedMethod one overridden method from a super type * @param allInheritedMethods look here to see if nonnull-unannotated conflict already exists in * one super type * @param scope provides context for error reporting etc. * @param inheritedNonNullnessInfos if non-null, this array of non-null elements is used for * interim recording of nullness information from inheritedMethod rather than prematurely * updating currentMethod. Index position 0 is used for the return type, positions i+1 for * argument i. */ void checkNullSpecInheritance( MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, boolean hasReturnNonNullDefault, boolean hasParameterNonNullDefault, boolean shouldComplain, MethodBinding inheritedMethod, MethodBinding[] allInheritedMethods, Scope scope, InheritedNonNullnessInfo[] inheritedNonNullnessInfos) { // Note that basically two different flows lead into this method: // (1) during MethodVerifyer15.checkMethods() we want to report errors (against srcMethod or // against the current type) // In this case this method is directly called from MethodVerifier15 // (checkAgainstInheritedMethod / checkConcreteInheritedMethod) // (2) during on-demand invocation we are mainly interested in the side effects of copying // inherited null annotations // In this case this method is called via checkImplicitNullAnnotations from // - MessageSend.resolveType(..) // - SourceTypeBinding.createArgumentBindings(..) // - recursive calls within this class // Still we *might* want to complain about problems found (controlled by 'complain') if ((inheritedMethod.tagBits & TagBits.IsNullnessKnown) == 0) { // TODO (stephan): even here we may need to report problems? How to discriminate? this.buddyImplicitNullAnnotationsVerifier.checkImplicitNullAnnotations( inheritedMethod, null, false, scope); } boolean useTypeAnnotations = this.environment.usesNullTypeAnnotations(); long inheritedNullnessBits = getReturnTypeNullnessTagBits(inheritedMethod, useTypeAnnotations); long currentNullnessBits = getReturnTypeNullnessTagBits(currentMethod, useTypeAnnotations); boolean shouldInherit = this.inheritNullAnnotations; // return type: returnType: { if (currentMethod.returnType == null || currentMethod.returnType.isBaseType()) break returnType; // no nullness for primitive types if (currentNullnessBits == 0) { // unspecified, may fill in either from super or from default if (shouldInherit) { if (inheritedNullnessBits != 0) { if (hasReturnNonNullDefault) { // both inheritance and default: check for conflict? if (shouldComplain && inheritedNullnessBits == TagBits.AnnotationNullable) scope .problemReporter() .conflictingNullAnnotations( currentMethod, ((MethodDeclaration) srcMethod).returnType, inheritedMethod); // still use the inherited bits to avoid incompatibility } if (inheritedNonNullnessInfos != null && srcMethod != null) { recordDeferredInheritedNullness( scope, ((MethodDeclaration) srcMethod).returnType, inheritedMethod, Boolean.valueOf(inheritedNullnessBits == TagBits.AnnotationNonNull), inheritedNonNullnessInfos[0]); } else { // no need to defer, record this info now: applyReturnNullBits(currentMethod, inheritedNullnessBits); } break returnType; // compatible by construction, skip complain phase below } } if (hasReturnNonNullDefault && (!useTypeAnnotations || currentMethod.returnType .acceptsNonNullDefault())) { // conflict with inheritance already checked currentNullnessBits = TagBits.AnnotationNonNull; applyReturnNullBits(currentMethod, currentNullnessBits); } } if (shouldComplain) { if ((inheritedNullnessBits & TagBits.AnnotationNonNull) != 0 && currentNullnessBits != TagBits.AnnotationNonNull) { if (srcMethod != null) { scope .problemReporter() .illegalReturnRedefinition( srcMethod, inheritedMethod, this.environment.getNonNullAnnotationName()); break returnType; } else { scope .problemReporter() .cannotImplementIncompatibleNullness( currentMethod, inheritedMethod, useTypeAnnotations); return; } } if (useTypeAnnotations) { TypeBinding substituteReturnType = null; // for TVB identity checks inside NullAnnotationMatching.analyze() TypeVariableBinding[] typeVariables = inheritedMethod.original().typeVariables; if (typeVariables != null && currentMethod.returnType.id != TypeIds.T_void) { ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(currentMethod, typeVariables); substituteReturnType = substitute.returnType; } if (NullAnnotationMatching.analyse( inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, 0, CheckMode.OVERRIDE) .isAnyMismatch()) { if (srcMethod != null) scope .problemReporter() .illegalReturnRedefinition( srcMethod, inheritedMethod, this.environment.getNonNullAnnotationName()); else scope .problemReporter() .cannotImplementIncompatibleNullness( currentMethod, inheritedMethod, useTypeAnnotations); return; } } } } // parameters: TypeBinding[] substituteParameters = null; // for TVB identity checks inside NullAnnotationMatching.analyze() if (shouldComplain) { TypeVariableBinding[] typeVariables = currentMethod.original().typeVariables; if (typeVariables != Binding.NO_TYPE_VARIABLES) { ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(inheritedMethod, typeVariables); substituteParameters = substitute.parameters; } } Argument[] currentArguments = srcMethod == null ? null : srcMethod.arguments; int length = 0; if (currentArguments != null) length = currentArguments.length; if (useTypeAnnotations) // need to look for type annotations on all parameters: length = currentMethod.parameters.length; else if (inheritedMethod.parameterNonNullness != null) length = inheritedMethod.parameterNonNullness.length; else if (currentMethod.parameterNonNullness != null) length = currentMethod.parameterNonNullness.length; parameterLoop: for (int i = 0; i < length; i++) { if (currentMethod.parameters[i].isBaseType()) continue; Argument currentArgument = currentArguments == null ? null : currentArguments[i]; Boolean inheritedNonNullNess = getParameterNonNullness(inheritedMethod, i, useTypeAnnotations); Boolean currentNonNullNess = getParameterNonNullness(currentMethod, i, useTypeAnnotations); if (currentNonNullNess == null) { // unspecified, may fill in either from super or from default if (inheritedNonNullNess != null) { if (shouldInherit) { if (hasParameterNonNullDefault) { // both inheritance and default: check for conflict? if (shouldComplain && inheritedNonNullNess == Boolean.FALSE && currentArgument != null) { scope .problemReporter() .conflictingNullAnnotations(currentMethod, currentArgument, inheritedMethod); } // still use the inherited info to avoid incompatibility } if (inheritedNonNullnessInfos != null && srcMethod != null) { recordDeferredInheritedNullness( scope, srcMethod.arguments[i].type, inheritedMethod, inheritedNonNullNess, inheritedNonNullnessInfos[i + 1]); } else { // no need to defer, record this info now: if (!useTypeAnnotations) recordArgNonNullness( currentMethod, length, i, currentArgument, inheritedNonNullNess); else recordArgNonNullness18( currentMethod, i, currentArgument, inheritedNonNullNess, this.environment); } continue; // compatible by construction, skip complain phase below } } if (hasParameterNonNullDefault) { // conflict with inheritance already checked currentNonNullNess = Boolean.TRUE; if (!useTypeAnnotations) recordArgNonNullness(currentMethod, length, i, currentArgument, Boolean.TRUE); else if (currentMethod.parameters[i].acceptsNonNullDefault()) recordArgNonNullness18( currentMethod, i, currentArgument, Boolean.TRUE, this.environment); else currentNonNullNess = null; // cancel if parameter doesn't accept the default } } if (shouldComplain) { char[][] annotationName; if (inheritedNonNullNess == Boolean.TRUE) { annotationName = this.environment.getNonNullAnnotationName(); } else { annotationName = this.environment.getNullableAnnotationName(); } if (inheritedNonNullNess != Boolean.TRUE // super parameter is not restricted to @NonNull && currentNonNullNess == Boolean.TRUE) // current parameter is restricted to @NonNull { // incompatible if (currentArgument != null) { scope .problemReporter() .illegalRedefinitionToNonNullParameter( currentArgument, inheritedMethod.declaringClass, (inheritedNonNullNess == null) ? null : this.environment.getNullableAnnotationName()); } else { scope .problemReporter() .cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); } continue; } else if (currentNonNullNess == null) { // unannotated strictly conflicts only with inherited @Nullable if (inheritedNonNullNess == Boolean.FALSE) { if (currentArgument != null) { scope .problemReporter() .parameterLackingNullableAnnotation( currentArgument, inheritedMethod.declaringClass, annotationName); } else { scope .problemReporter() .cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); } continue; } else if (inheritedNonNullNess == Boolean.TRUE) { // not strictly a conflict, but a configurable warning is given anyway: if (allInheritedMethods != null) { // avoid this optional warning if the conflict already existed in one supertype // (merging of two methods into one?) for (MethodBinding one : allInheritedMethods) if (TypeBinding.equalsEquals(inheritedMethod.declaringClass, one.declaringClass) && getParameterNonNullness(one, i, useTypeAnnotations) != Boolean.TRUE) continue parameterLoop; } scope .problemReporter() .parameterLackingNonnullAnnotation( currentArgument, inheritedMethod.declaringClass, annotationName); continue; } } if (useTypeAnnotations) { TypeBinding inheritedParameter = inheritedMethod.parameters[i]; TypeBinding substituteParameter = substituteParameters != null ? substituteParameters[i] : null; if (NullAnnotationMatching.analyse( currentMethod.parameters[i], inheritedParameter, substituteParameter, 0, CheckMode.OVERRIDE) .isAnyMismatch()) { if (currentArgument != null) scope .problemReporter() .illegalParameterRedefinition( currentArgument, inheritedMethod.declaringClass, inheritedParameter); else scope .problemReporter() .cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); } } } } }
/** * Check and fill in implicit annotations from overridden methods and from default. Precondition: * caller has checked whether annotation-based null analysis is enabled. */ public void checkImplicitNullAnnotations( MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, boolean complain, Scope scope) { // check inherited nullness from superclass and superInterfaces try { ReferenceBinding currentType = currentMethod.declaringClass; if (currentType.id == TypeIds.T_JavaLangObject) { return; } boolean usesTypeAnnotations = scope.environment().usesNullTypeAnnotations(); boolean needToApplyReturnNonNullDefault = currentMethod.hasNonNullDefaultFor( Binding.DefaultLocationReturnType, usesTypeAnnotations); boolean needToApplyParameterNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter, usesTypeAnnotations); boolean needToApplyNonNullDefault = needToApplyReturnNonNullDefault | needToApplyParameterNonNullDefault; // compatibility & inheritance do not consider constructors / static methods: boolean isInstanceMethod = !currentMethod.isConstructor() && !currentMethod.isStatic(); complain &= isInstanceMethod; if (!needToApplyNonNullDefault && !complain && !(this.inheritNullAnnotations && isInstanceMethod)) { return; // short cut, no work to be done } if (isInstanceMethod) { List superMethodList = new ArrayList(); // need super types connected: if (currentType instanceof SourceTypeBinding && !currentType.isHierarchyConnected() && !currentType.isAnonymousType()) { ((SourceTypeBinding) currentType).scope.connectTypeHierarchy(); } int paramLen = currentMethod.parameters.length; findAllOverriddenMethods( currentMethod.original(), currentMethod.selector, paramLen, currentType, new HashSet(), superMethodList); // prepare interim storage for nullness info so we don't pollute currentMethod before we // know its conflict-free: InheritedNonNullnessInfo[] inheritedNonNullnessInfos = new InheritedNonNullnessInfo[paramLen + 1]; // index 0 is for the return type for (int i = 0; i < paramLen + 1; i++) inheritedNonNullnessInfos[i] = new InheritedNonNullnessInfo(); int length = superMethodList.size(); for (int i = length; --i >= 0; ) { MethodBinding currentSuper = (MethodBinding) superMethodList.get(i); if ((currentSuper.tagBits & TagBits.IsNullnessKnown) == 0) { // recurse to prepare currentSuper checkImplicitNullAnnotations( currentSuper, null, false, scope); // TODO (stephan) complain=true if currentSuper is source method?? } checkNullSpecInheritance( currentMethod, srcMethod, needToApplyReturnNonNullDefault, needToApplyParameterNonNullDefault, complain, currentSuper, null, scope, inheritedNonNullnessInfos); needToApplyNonNullDefault = false; } // transfer collected information into currentMethod: InheritedNonNullnessInfo info = inheritedNonNullnessInfos[0]; if (!info.complained) { long tagBits = 0; if (info.inheritedNonNullness == Boolean.TRUE) { tagBits = TagBits.AnnotationNonNull; } else if (info.inheritedNonNullness == Boolean.FALSE) { tagBits = TagBits.AnnotationNullable; } if (tagBits != 0) { if (!usesTypeAnnotations) { currentMethod.tagBits |= tagBits; } else { if (!currentMethod.returnType.isBaseType()) { LookupEnvironment env = scope.environment(); currentMethod.returnType = env.createAnnotatedType( currentMethod.returnType, env.nullAnnotationsFromTagBits(tagBits)); } } } } for (int i = 0; i < paramLen; i++) { info = inheritedNonNullnessInfos[i + 1]; if (!info.complained && info.inheritedNonNullness != null) { Argument currentArg = srcMethod == null ? null : srcMethod.arguments[i]; if (!usesTypeAnnotations) recordArgNonNullness( currentMethod, paramLen, i, currentArg, info.inheritedNonNullness); else recordArgNonNullness18( currentMethod, i, currentArg, info.inheritedNonNullness, scope.environment()); } } } if (needToApplyNonNullDefault) { if (!usesTypeAnnotations) currentMethod.fillInDefaultNonNullness(srcMethod); else currentMethod.fillInDefaultNonNullness18(srcMethod, scope.environment()); } } finally { currentMethod.tagBits |= TagBits.IsNullnessKnown; } }
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; }