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); } } }
void recordArgNonNullness18( MethodBinding method, int paramIdx, Argument currentArgument, Boolean nonNullNess, LookupEnvironment env) { AnnotationBinding annotationBinding = nonNullNess.booleanValue() ? env.getNonNullAnnotation() : env.getNullableAnnotation(); method.parameters[paramIdx] = env.createAnnotatedType( method.parameters[paramIdx], new AnnotationBinding[] {annotationBinding}); if (currentArgument != null) { currentArgument.binding.type = method.parameters[paramIdx]; } }
public HierarchyResolver( INameEnvironment nameEnvironment, Map settings, HierarchyBuilder builder, IProblemFactory problemFactory) { // create a problem handler with the 'exit after all problems' handling policy this.options = new CompilerOptions(settings); IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.exitAfterAllProblems(); ProblemReporter problemReporter = new ProblemReporter(policy, this.options, problemFactory); LookupEnvironment environment = new LookupEnvironment(this, this.options, problemReporter, nameEnvironment); environment.mayTolerateMissingType = true; setEnvironment(environment, builder); }
public static ReferenceBinding resolveType(LookupEnvironment lookupEnvironment, String typeName) { ReferenceBinding type = null; int p = typeName.indexOf('$'); if (p > 0) { // resolve an outer type before trying to get the cached inner String cupName = typeName.substring(0, p); char[][] chars = CharOperation.splitOn('.', cupName.toCharArray()); ReferenceBinding outerType = lookupEnvironment.getType(chars); if (outerType != null) { // outer class was found resolveRecursive(outerType); chars = CharOperation.splitOn('.', typeName.toCharArray()); type = lookupEnvironment.getCachedType(chars); if (type == null) { // no inner type; this is a pure failure return null; } } } else { // just resolve the type straight out char[][] chars = CharOperation.splitOn('.', typeName.toCharArray()); type = lookupEnvironment.getType(chars); } if (type != null) { if (type instanceof UnresolvedReferenceBinding) { /* * Since type is an instance of UnresolvedReferenceBinding, we know that * the return value BinaryTypeBinding.resolveType will be of type * ReferenceBinding */ type = (ReferenceBinding) BinaryTypeBinding.resolveType(type, lookupEnvironment, true); } // found it return type; } // Assume that the last '.' should be '$' and try again. // p = typeName.lastIndexOf('.'); if (p >= 0) { typeName = typeName.substring(0, p) + "$" + typeName.substring(p + 1); return resolveType(lookupEnvironment, typeName); } return null; }
/** * Feed null information from argument annotations into the analysis and mark arguments as * assigned. */ static void analyseArguments( LookupEnvironment environment, FlowInfo flowInfo, Argument[] methodArguments, MethodBinding methodBinding) { if (methodArguments != null) { boolean usesNullTypeAnnotations = environment.usesNullTypeAnnotations(); int length = Math.min(methodBinding.parameters.length, methodArguments.length); for (int i = 0; i < length; i++) { if (usesNullTypeAnnotations) { // leverage null type annotations: long tagBits = methodBinding.parameters[i].tagBits & TagBits.AnnotationNullMASK; if (tagBits == TagBits.AnnotationNonNull) flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding); else if (tagBits == TagBits.AnnotationNullable) flowInfo.markPotentiallyNullBit(methodArguments[i].binding); } else { if (methodBinding.parameterNonNullness != null) { // leverage null-info from parameter annotations: Boolean nonNullNess = methodBinding.parameterNonNullness[i]; if (nonNullNess != null) { if (nonNullNess.booleanValue()) flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding); else flowInfo.markPotentiallyNullBit(methodArguments[i].binding); } } } // tag parameters as being set: flowInfo.markAsDefinitelyAssigned(methodArguments[i].binding); } } }
public void swapUnresolved( UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { if (this.leafComponentType == unresolvedType) { this.leafComponentType = env.convertUnresolvedBinaryToRawType(resolvedType); this.tagBits |= this.leafComponentType.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType); } }
public void swapUnresolved( UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) { boolean affected = false; if (this.genericType == unresolvedType) { this.genericType = resolvedType; // no raw conversion affected = true; } if (this.bound == unresolvedType) { this.bound = env.convertUnresolvedBinaryToRawType(resolvedType); affected = true; } if (this.otherBounds != null) { for (int i = 0, length = this.otherBounds.length; i < length; i++) { if (this.otherBounds[i] == unresolvedType) { this.otherBounds[i] = env.convertUnresolvedBinaryToRawType(resolvedType); affected = true; } } } if (affected) initialize(this.genericType, this.bound, this.otherBounds); }
/** * Create raw generic method for raw type (double substitution from type vars with raw type * arguments, and erasure of method variables) Only invoked for non-static generic methods of raw * type */ public ParameterizedGenericMethodBinding( MethodBinding originalMethod, RawTypeBinding rawType, LookupEnvironment environment) { TypeVariableBinding[] originalVariables = originalMethod.typeVariables; int length = originalVariables.length; TypeBinding[] rawArguments = new TypeBinding[length]; for (int i = 0; i < length; i++) { rawArguments[i] = environment.convertToRawType( originalVariables[i].erasure(), false /*do not force conversion of enclosing types*/); } this.isRaw = true; this.tagBits = originalMethod.tagBits; this.environment = environment; this.modifiers = originalMethod.modifiers; this.selector = originalMethod.selector; this.declaringClass = rawType == null ? originalMethod.declaringClass : rawType; this.typeVariables = Binding.NO_TYPE_VARIABLES; this.typeArguments = rawArguments; this.originalMethod = originalMethod; boolean ignoreRawTypeSubstitution = rawType == null || originalMethod.isStatic(); this.parameters = Scope.substitute( this, ignoreRawTypeSubstitution ? originalMethod.parameters // no substitution if original was static : Scope.substitute(rawType, originalMethod.parameters)); this.thrownExceptions = Scope.substitute( this, ignoreRawTypeSubstitution ? originalMethod.thrownExceptions // no substitution if original was static : Scope.substitute(rawType, originalMethod.thrownExceptions)); // error case where exception type variable would have been substituted by a non-reference type // (207573) if (this.thrownExceptions == null) this.thrownExceptions = Binding.NO_EXCEPTIONS; this.returnType = Scope.substitute( this, ignoreRawTypeSubstitution ? originalMethod.returnType // no substitution if original was static : Scope.substitute(rawType, originalMethod.returnType)); this.wasInferred = false; // not resulting from method invocation inferrence this.parameterNonNullness = originalMethod.parameterNonNullness; }
/** * 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) { this.constant = Constant.NotAConstant; if ((this.targetType = this.type.resolveType(scope, true /* check bounds*/)) == null) return null; /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=320463 https://bugs.eclipse.org/bugs/show_bug.cgi?id=312076 JLS3 15.8.2 forbids the type named in the class literal expression from being a parameterized type. And the grammar in 18.1 disallows (where X and Y are some concrete types) constructs of the form Outer<X>.class, Outer<X>.Inner.class, Outer.Inner<X>.class, Outer<X>.Inner<Y>.class etc. Corollary wise, we should resolve the type of the class literal expression to be a raw type as class literals exist only for the raw underlying type. */ LookupEnvironment environment = scope.environment(); this.targetType = environment.convertToRawType( this.targetType, true /* force conversion of enclosing types*/); if (this.targetType.isArrayType()) { ArrayBinding arrayBinding = (ArrayBinding) this.targetType; TypeBinding leafComponentType = arrayBinding.leafComponentType; if (leafComponentType == TypeBinding.VOID) { scope.problemReporter().cannotAllocateVoidArray(this); return null; } else if (leafComponentType.isTypeVariable()) { scope .problemReporter() .illegalClassLiteralForTypeVariable((TypeVariableBinding) leafComponentType, this); } } else if (this.targetType.isTypeVariable()) { scope .problemReporter() .illegalClassLiteralForTypeVariable((TypeVariableBinding) this.targetType, this); } // {ObjectTeams: do we need a RoleClassLiteralAccess? if (this.targetType instanceof ReferenceBinding) { ReferenceBinding targetRef = (ReferenceBinding) this.targetType; if (targetRef.isRole()) { if (this.verbatim) { this.targetType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, this.targetType, this); } else { SourceTypeBinding site = scope.enclosingSourceType(); if (scope.methodScope().isStatic // role class literal needs team instance && !site.isRole() // static role method are OK. && !RoleTypeBinding.isRoleWithExplicitAnchor(this.targetType)) // t.R.class? { scope.problemReporter().roleClassLiteralLacksTeamInstance(this, targetRef); return null; } ReferenceBinding teamBinding; if (RoleTypeBinding.isRoleWithExplicitAnchor(targetRef)) teamBinding = targetRef.enclosingType(); else teamBinding = TeamModel.findEnclosingTeamContainingRole(site, targetRef); if (teamBinding == null) scope.problemReporter().externalizedRoleClassLiteral(this, targetRef); else { TypeBinding methodType = RoleClassLiteralAccess.ensureGetClassMethod( teamBinding.getTeamModel(), targetRef.roleModel); // not affected by visibility check (for resilience) this.roleClassLiteralAccess = new RoleClassLiteralAccess(this, methodType); this.resolvedType = this.roleClassLiteralAccess.resolveType(scope); } return this.resolvedType; } } } // SH} ReferenceBinding classType = scope.getJavaLangClass(); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=328689 if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // Integer.class --> Class<Integer>, perform boxing of base types (int.class --> // Class<Integer>) TypeBinding boxedType = null; if (this.targetType.id == T_void) { boxedType = environment.getResolvedType(JAVA_LANG_VOID, scope); } else { boxedType = scope.boxing(this.targetType); } if (environment.usesNullTypeAnnotations()) boxedType = environment.createAnnotatedType( boxedType, new AnnotationBinding[] {environment.getNonNullAnnotation()}); this.resolvedType = environment.createParameterizedType( classType, new TypeBinding[] {boxedType}, null /*not a member*/); } else { this.resolvedType = classType; } return this.resolvedType; }