private static JetDelegatorToSuperCall findSuperCall( BindingContext bindingContext, JetElement classOrObject) { if (!(classOrObject instanceof JetClassOrObject)) { return null; } if (classOrObject instanceof JetClass && ((JetClass) classOrObject).isTrait()) { return null; } for (JetDelegationSpecifier specifier : ((JetClassOrObject) classOrObject).getDelegationSpecifiers()) { if (specifier instanceof JetDelegatorToSuperCall) { JetType superType = bindingContext.get(TYPE, specifier.getTypeReference()); assert superType != null; ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); assert superClassDescriptor != null; if (!isInterface(superClassDescriptor)) { return (JetDelegatorToSuperCall) specifier; } } } return null; }
public static void reportCyclicInheritanceHierarchyError( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor superclass) { PsiElement psiElement = BindingContextUtils.classDescriptorToDeclaration( trace.getBindingContext(), classDescriptor); PsiElement elementToMark = null; if (psiElement instanceof JetClassOrObject) { JetClassOrObject classOrObject = (JetClassOrObject) psiElement; for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { JetTypeReference typeReference = delegationSpecifier.getTypeReference(); if (typeReference == null) continue; JetType supertype = trace.get(TYPE, typeReference); if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) { elementToMark = typeReference; } } } if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) { PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement; PsiElement nameIdentifier = namedElement.getNameIdentifier(); if (nameIdentifier != null) { elementToMark = nameIdentifier; } } if (elementToMark != null) { trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark)); } }
private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) { for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { checkBoundsForTypeInClassHeader(delegationSpecifier.getTypeReference()); } if (!(classOrObject instanceof JetClass)) return; JetClass jetClass = (JetClass) classOrObject; for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) { checkBoundsForTypeInClassHeader(jetTypeParameter.getExtendsBound()); checkFinalUpperBounds(jetTypeParameter.getExtendsBound()); } for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) { checkBoundsForTypeInClassHeader(constraint.getBoundTypeReference()); checkFinalUpperBounds(constraint.getBoundTypeReference()); } }
private void checkEnumEntry( @NotNull JetEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) { DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration(); assert DescriptorUtils.isEnumClass(declaration) : "Enum entry should be declared in enum class: " + classDescriptor; ClassDescriptor enumClass = (ClassDescriptor) declaration; if (enumEntryUsesDeprecatedSuperConstructor(enumEntry)) { trace.report( Errors.ENUM_ENTRY_USES_DEPRECATED_SUPER_CONSTRUCTOR.on(enumEntry, classDescriptor)); } String neededDelimiter = enumEntryExpectedDelimiter(enumEntry); if (!neededDelimiter.isEmpty()) { trace.report( Errors.ENUM_ENTRY_USES_DEPRECATED_OR_NO_DELIMITER.on( enumEntry, classDescriptor, neededDelimiter)); } if (enumEntryAfterEnumMember(enumEntry)) { trace.report(Errors.ENUM_ENTRY_AFTER_ENUM_MEMBER.on(enumEntry, classDescriptor)); } List<JetDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers(); ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor(); if ((constructor == null || !constructor.getValueParameters().isEmpty()) && delegationSpecifiers.isEmpty()) { trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry, enumClass)); } for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { JetTypeReference typeReference = delegationSpecifier.getTypeReference(); if (typeReference != null) { JetType type = trace.getBindingContext().get(TYPE, typeReference); if (type != null) { JetType enumType = enumClass.getDefaultType(); if (!type.getConstructor().equals(enumType.getConstructor())) { trace.report(ENUM_ENTRY_ILLEGAL_TYPE.on(typeReference, enumClass)); } } } } }
private void resolveDelegationSpecifierList( final JetClassOrObject jetClass, final MutableClassDescriptor descriptor) { if (!context.completeAnalysisNeeded(jetClass)) return; final ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor(); final JetScope scopeForConstructor = primaryConstructor == null ? null : FunctionDescriptorUtil.getFunctionInnerScope( descriptor.getScopeForSupertypeResolution(), primaryConstructor, trace); final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap(); JetVisitorVoid visitor = new JetVisitorVoid() { private void recordSupertype(JetTypeReference typeReference, JetType supertype) { if (supertype == null) return; supertypes.put(typeReference, supertype); } @Override public void visitDelegationByExpressionSpecifier( JetDelegatorByExpressionSpecifier specifier) { if (descriptor.getKind() == ClassKind.TRAIT) { 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.TRAIT) { trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference())); } } } JetExpression delegateExpression = specifier.getDelegateExpression(); if (delegateExpression != null) { JetScope scope = scopeForConstructor == null ? descriptor.getScopeForMemberResolution() : scopeForConstructor; JetType type = typeInferrer.getType(scope, delegateExpression, NO_EXPECTED_TYPE, trace); if (type != null && supertype != null && !JetTypeChecker.INSTANCE.isSubtypeOf(type, supertype)) { trace.report(TYPE_MISMATCH.on(delegateExpression, supertype, type)); } } } @Override public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetValueArgumentList valueArgumentList = call.getValueArgumentList(); PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList; if (descriptor.getKind() == ClassKind.TRAIT) { trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark)); } JetTypeReference typeReference = call.getTypeReference(); if (typeReference == null) return; if (descriptor.getUnsubstitutedPrimaryConstructor() == null) { assert descriptor.getKind() == ClassKind.TRAIT; return; } OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall( trace, scopeForConstructor, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, DataFlowInfo.EMPTY); if (results.isSuccess()) { JetType supertype = results.getResultingDescriptor().getReturnType(); recordSupertype(typeReference, supertype); ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (classDescriptor.getKind() == ClassKind.TRAIT) { trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark)); } } } else { recordSupertype( typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference)); } } @Override public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) { JetTypeReference typeReference = specifier.getTypeReference(); JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference); recordSupertype(typeReference, supertype); if (supertype == null) return; ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor == null) return; if (descriptor.getKind() != ClassKind.TRAIT && classDescriptor.hasConstructors() && !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && classDescriptor.getKind() != ClassKind.TRAIT) { boolean hasConstructorWithoutParams = false; for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) { if (constructor.getValueParameters().isEmpty()) { hasConstructorWithoutParams = true; } } if (!hasConstructorWithoutParams) { trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier)); } else { trace.report(SUPERTYPE_NOT_INITIALIZED_DEFAULT.on(specifier)); } } } @Override public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) { throw new IllegalStateException("This-calls should be prohibited by the parser"); } @Override public void visitJetElement(JetElement element) { throw new UnsupportedOperationException(element.getText() + " : " + element); } }; for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) { delegationSpecifier.accept(visitor); } Set<TypeConstructor> parentEnum = Collections.emptySet(); if (jetClass instanceof JetEnumEntry) { parentEnum = Collections.singleton( ((ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration()) .getTypeConstructor()); } checkSupertypeList(descriptor, supertypes, parentEnum); }
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); }