/** * This method tries to resolve descriptors ambiguity between class descriptor and package * descriptor for the same class. It's ok choose class for expression reference resolution. * * @return <code>true</code> if method has successfully resolved ambiguity */ private static boolean resolveClassPackageAmbiguity( @NotNull Collection<DeclarationDescriptor> filteredDescriptors, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope resolutionScope, @NotNull BindingTrace trace, @NotNull JetScope scopeToCheckVisibility) { if (filteredDescriptors.size() == 2) { PackageViewDescriptor packageView = null; ClassDescriptor classDescriptor = null; for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) { if (filteredDescriptor instanceof PackageViewDescriptor) { packageView = (PackageViewDescriptor) filteredDescriptor; } else if (filteredDescriptor instanceof ClassDescriptor) { classDescriptor = (ClassDescriptor) filteredDescriptor; } } if (packageView != null && classDescriptor != null) { if (packageView.getFqName().equalsTo(DescriptorUtils.getFqName(classDescriptor))) { trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); checkVisibility(classDescriptor, trace, referenceExpression, scopeToCheckVisibility); return true; } } } return false; }
// Note: headers of member classes' members are not resolved public void resolveMemberHeaders() { ForceResolveUtil.forceResolveAllContents(getAnnotations()); ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations()); getCompanionObjectDescriptor(); getDescriptorsForExtraCompanionObjects(); getConstructors(); getContainingDeclaration(); getThisAsReceiverParameter(); getKind(); getModality(); getName(); getOriginal(); getScopeForClassHeaderResolution(); getScopeForMemberDeclarationResolution(); DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope()); getScopeForInitializerResolution(); getUnsubstitutedInnerClassesScope(); getTypeConstructor().getSupertypes(); for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) { typeParameterDescriptor.getUpperBounds(); } getUnsubstitutedPrimaryConstructor(); getVisibility(); }
@NotNull public static Pair<FunctionDescriptor, PsiElement> getContainingFunctionSkipFunctionLiterals( @Nullable DeclarationDescriptor startDescriptor, boolean strict) { FunctionDescriptor containingFunctionDescriptor = DescriptorUtils.getParentOfType(startDescriptor, FunctionDescriptor.class, strict); PsiElement containingFunction = containingFunctionDescriptor != null ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor) : null; while (containingFunction instanceof JetFunctionLiteral) { containingFunctionDescriptor = DescriptorUtils.getParentOfType(containingFunctionDescriptor, FunctionDescriptor.class); containingFunction = containingFunctionDescriptor != null ? DescriptorToSourceUtils.getSourceFromDescriptor(containingFunctionDescriptor) : null; } return new Pair<FunctionDescriptor, PsiElement>( containingFunctionDescriptor, containingFunction); }
@NotNull private static InnerModifierCheckResult checkIllegalInner( @NotNull DeclarationDescriptor descriptor) { if (!(descriptor instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION; ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; if (classDescriptor.getKind() != ClassKind.CLASS) return InnerModifierCheckResult.ILLEGAL_POSITION; DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration(); if (!(containingDeclaration instanceof ClassDescriptor)) return InnerModifierCheckResult.ILLEGAL_POSITION; if (DescriptorUtils.isTrait(containingDeclaration)) { return InnerModifierCheckResult.IN_TRAIT; } else if (DescriptorUtils.isObject(containingDeclaration)) { return InnerModifierCheckResult.IN_OBJECT; } else { return InnerModifierCheckResult.ALLOWED; } }
@NotNull @Override public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() { //noinspection unchecked return (Collection) CollectionsKt.filter( DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope), new Function1<DeclarationDescriptor, Boolean>() { @Override public Boolean invoke(DeclarationDescriptor descriptor) { return descriptor instanceof CallableMemberDescriptor && ((CallableMemberDescriptor) descriptor).getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE; } }); }
@Nullable private LazyClassDescriptor computeCompanionObjectDescriptor( @Nullable KtObjectDeclaration companionObject) { KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject); if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) { return null; } Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName(); assert name != null; getUnsubstitutedMemberScope() .getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT); ClassDescriptor companionObjectDescriptor = c.getTrace().get(BindingContext.CLASS, companionObject); if (companionObjectDescriptor instanceof LazyClassDescriptor) { assert DescriptorUtils.isCompanionObject(companionObjectDescriptor) : "Not a companion object: " + companionObjectDescriptor; return (LazyClassDescriptor) companionObjectDescriptor; } else { return null; } }
private boolean isCompanionObjectAllowed() { return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this)); }
public LazyClassDescriptor( @NotNull final LazyClassContext c, @NotNull DeclarationDescriptor containingDeclaration, @NotNull Name name, @NotNull final KtClassLikeInfo classLikeInfo) { super( c.getStorageManager(), containingDeclaration, name, KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject())); this.c = c; KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject(); if (classOrObject != null) { this.c.getTrace().record(BindingContext.CLASS, classOrObject, this); } this.c .getTrace() .record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this); this.declarationProvider = c.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo); StorageManager storageManager = c.getStorageManager(); this.unsubstitutedMemberScope = createMemberScope(c, this.declarationProvider); this.kind = classLikeInfo.getClassKind(); this.staticScope = kind == ClassKind.ENUM_CLASS ? new StaticScopeForKotlinEnum(storageManager, this) : MemberScope.Empty.INSTANCE; this.typeConstructor = new LazyClassTypeConstructor(); this.isCompanionObject = classLikeInfo instanceof KtObjectInfo && ((KtObjectInfo) classLikeInfo).isCompanionObject(); KtModifierList modifierList = classLikeInfo.getModifierList(); if (kind.isSingleton()) { this.modality = Modality.FINAL; } else { Modality defaultModality = kind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL; this.modality = resolveModalityFromModifiers(modifierList, defaultModality, /* allowSealed = */ true); } boolean isLocal = classOrObject != null && KtPsiUtil.isLocal(classOrObject); Visibility defaultVisibility; if (kind == ClassKind.ENUM_ENTRY || (kind == ClassKind.OBJECT && isCompanionObject)) { defaultVisibility = Visibilities.PUBLIC; } else { defaultVisibility = Visibilities.DEFAULT_VISIBILITY; } this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, defaultVisibility); this.isInner = isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(this); this.isData = modifierList != null && modifierList.hasModifier(KtTokens.DATA_KEYWORD); // Annotation entries are taken from both own annotations (if any) and object literal // annotations (if any) List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>(); if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) { // TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic annotationEntries.addAll( KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent())); } if (modifierList != null) { annotationEntries.addAll(modifierList.getAnnotationEntries()); } if (!annotationEntries.isEmpty()) { this.annotations = new LazyAnnotations( new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) { @NotNull @Override public LexicalScope getScope() { return getOuterScope(); } }, annotationEntries); } else { this.annotations = Annotations.Companion.getEMPTY(); } List<KtAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations(); if (jetDanglingAnnotations.isEmpty()) { this.danglingAnnotations = Annotations.Companion.getEMPTY(); } else { this.danglingAnnotations = new LazyAnnotations( new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) { @NotNull @Override public LexicalScope getScope() { return getScopeForMemberDeclarationResolution(); } }, jetDanglingAnnotations); } this.companionObjectDescriptor = storageManager.createNullableLazyValue( new Function0<LazyClassDescriptor>() { @Override public LazyClassDescriptor invoke() { return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed()); } }); this.extraCompanionObjectDescriptors = storageManager.createMemoizedFunction( new Function1<KtObjectDeclaration, ClassDescriptor>() { @Override public ClassDescriptor invoke(KtObjectDeclaration companionObject) { return computeCompanionObjectDescriptor(companionObject); } }); this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue( new Function0<Void>() { @Override public Void invoke() { doForceResolveAllContents(); return null; } }, null); this.resolutionScopesSupport = new ClassResolutionScopesSupport( this, storageManager, new Function0<LexicalScope>() { @Override public LexicalScope invoke() { return getOuterScope(); } }); this.parameters = c.getStorageManager() .createLazyValue( new Function0<List<TypeParameterDescriptor>>() { @Override public List<TypeParameterDescriptor> invoke() { KtClassLikeInfo classInfo = declarationProvider.getOwnerInfo(); KtTypeParameterList typeParameterList = classInfo.getTypeParameterList(); if (typeParameterList == null) return Collections.emptyList(); if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) { c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList)); } List<KtTypeParameter> typeParameters = typeParameterList.getParameters(); if (typeParameters.isEmpty()) return Collections.emptyList(); List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size()); for (int i = 0; i < typeParameters.size(); i++) { parameters.add( new LazyTypeParameterDescriptor( c, LazyClassDescriptor.this, typeParameters.get(i), i)); } return parameters; } }); this.scopeForInitializerResolution = storageManager.createLazyValue( new Function0<LexicalScope>() { @Override public LexicalScope invoke() { return ClassResolutionScopesSupportKt.scopeForInitializerResolution( LazyClassDescriptor.this, createInitializerScopeParent(), classLikeInfo.getPrimaryConstructorParameters()); } }); }
private void checkSupertypeList( @NotNull ClassDescriptor supertypeOwner, @NotNull Map<JetTypeReference, JetType> supertypes, @NotNull JetClassOrObject jetClass) { Set<TypeConstructor> allowedFinalSupertypes = getAllowedFinalSupertypes(supertypeOwner, jetClass); Set<TypeConstructor> typeConstructors = Sets.newHashSet(); boolean classAppeared = false; for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) { JetTypeReference typeReference = entry.getKey(); JetType supertype = entry.getValue(); boolean addSupertype = true; ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (ErrorUtils.isError(classDescriptor)) continue; if (classDescriptor.getKind() != ClassKind.INTERFACE) { if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) { trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference)); addSupertype = false; } else if (supertypeOwner.getKind() == ClassKind.INTERFACE && !classAppeared && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) { trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference)); addSupertype = false; } if (classAppeared) { trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference)); } else { classAppeared = true; } } } else { trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference)); } TypeConstructor constructor = supertype.getConstructor(); if (addSupertype && !typeConstructors.add(constructor)) { trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference)); } if (DescriptorUtils.isSingleton(classDescriptor)) { trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference)); } else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) { if (classDescriptor.getModality() == Modality.SEALED) { DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration(); while (containingDescriptor != null && containingDescriptor != classDescriptor) { containingDescriptor = containingDescriptor.getContainingDeclaration(); } if (containingDescriptor == null) { trace.report(SEALED_SUPERTYPE.on(typeReference)); } else { trace.report(SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(typeReference)); } } else { trace.report(FINAL_SUPERTYPE.on(typeReference)); } } } }
public void resolveDelegationSpecifierList( @NotNull final DataFlowInfo outerDataFlowInfo, @NotNull JetClassOrObject jetClass, @NotNull final ClassDescriptor descriptor, @Nullable final ConstructorDescriptor primaryConstructor, @NotNull LexicalScope scopeForSupertypeResolution, @NotNull final LexicalScope scopeForMemberResolution) { final LexicalScope scopeForConstructor = primaryConstructor == null ? null : FunctionDescriptorUtil.getFunctionInnerScope( scopeForSupertypeResolution, primaryConstructor, trace); final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap(); final ResolvedCall<?>[] primaryConstructorDelegationCall = new ResolvedCall[1]; JetVisitorVoid visitor = new JetVisitorVoid() { private void recordSupertype(JetTypeReference typeReference, JetType supertype) { if (supertype == null) return; supertypes.put(typeReference, supertype); } @Override public void visitDelegationByExpressionSpecifier( @NotNull JetDelegatorByExpressionSpecifier specifier) { if (descriptor.getKind() == ClassKind.INTERFACE) { trace.report(DELEGATION_IN_TRAIT.on(specifier)); } JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference()); recordSupertype(specifier.getTypeReference(), supertype); if (supertype != null) { DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); if (declarationDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor; if (classDescriptor.getKind() != ClassKind.INTERFACE) { trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference())); } } } JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { LexicalScope scope = scopeForConstructor == null ? scopeForMemberResolution : scopeForConstructor; JetType expectedType = supertype != null ? supertype : NO_EXPECTED_TYPE; typeInferrer.getType( scope, delegateExpression, expectedType, outerDataFlowInfo, trace); } if (primaryConstructor == null) { trace.report( UNSUPPORTED.on( specifier, "Delegation without primary constructor is not supported")); } } @Override public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList; if (descriptor.getKind() == ClassKind.INTERFACE) { trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark)); } JetTypeReference typeReference = call.getTypeReference(); if (typeReference == null) return; if (primaryConstructor == null) { if (descriptor.getKind() != ClassKind.INTERFACE) { trace.report(SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(call)); } recordSupertype( typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference)); return; } OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall( trace, scopeForConstructor, CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, outerDataFlowInfo, false); if (results.isSuccess()) { JetType supertype = results.getResultingDescriptor().getReturnType(); recordSupertype(typeReference, supertype); ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { // allow only one delegating constructor if (primaryConstructorDelegationCall[0] == null) { primaryConstructorDelegationCall[0] = results.getResultingCall(); } else { primaryConstructorDelegationCall[0] = null; } } // Recording type info for callee to use later in JetObjectLiteralExpression trace.record(PROCESSED, call.getCalleeExpression(), true); trace.record( EXPRESSION_TYPE_INFO, call.getCalleeExpression(), TypeInfoFactoryPackage.noTypeInfo( results.getResultingCall().getDataFlowInfoForArguments().getResultInfo())); } else { recordSupertype( typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference)); } } @Override public void visitDelegationToSuperClassSpecifier( @NotNull JetDelegatorToSuperClass specifier) { JetTypeReference typeReference = specifier.getTypeReference(); JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference); recordSupertype(typeReference, supertype); if (supertype == null) return; ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype); if (superClass == null) return; if (superClass.getKind().isSingleton()) { // A "singleton in supertype" diagnostic will be reported later return; } if (descriptor.getKind() != ClassKind.INTERFACE && descriptor.getUnsubstitutedPrimaryConstructor() != null && superClass.getKind() != ClassKind.INTERFACE && !superClass.getConstructors().isEmpty() && !ErrorUtils.isError(superClass)) { trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier)); } } @Override public void visitJetElement(@NotNull JetElement element) { throw new UnsupportedOperationException(element.getText() + " : " + element); } }; for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { delegationSpecifier.accept(visitor); } if (DescriptorUtils.isAnnotationClass(descriptor) && jetClass.getDelegationSpecifierList() != null) { trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(jetClass.getDelegationSpecifierList())); } if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) { recordConstructorDelegationCall( trace, primaryConstructor, primaryConstructorDelegationCall[0]); } checkSupertypeList(descriptor, supertypes, jetClass); }