private void checkCyclicConstructorDelegationCall( @NotNull ConstructorDescriptor constructorDescriptor, @NotNull Set<ConstructorDescriptor> visitedConstructors) { if (visitedConstructors.contains(constructorDescriptor)) return; // if visit constructor that is already in current chain // such constructor is on cycle Set<ConstructorDescriptor> visitedInCurrentChain = Sets.newHashSet(); ConstructorDescriptor currentConstructorDescriptor = constructorDescriptor; while (true) { visitedInCurrentChain.add(currentConstructorDescriptor); ConstructorDescriptor delegatedConstructorDescriptor = getDelegatedConstructor(currentConstructorDescriptor); if (delegatedConstructorDescriptor == null) break; // if next delegation call is super or primary constructor or already visited if (!constructorDescriptor .getContainingDeclaration() .equals(delegatedConstructorDescriptor.getContainingDeclaration()) || delegatedConstructorDescriptor.isPrimary() || visitedConstructors.contains(delegatedConstructorDescriptor)) { break; } if (visitedInCurrentChain.contains(delegatedConstructorDescriptor)) { reportEachConstructorOnCycle(delegatedConstructorDescriptor); break; } currentConstructorDescriptor = delegatedConstructorDescriptor; } visitedConstructors.addAll(visitedInCurrentChain); }
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 resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) { for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) { JetClassOrObject klass = entry.getKey(); ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue(); ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); if (unsubstitutedPrimaryConstructor != null) { ForceResolveUtil.forceResolveAllContents(unsubstitutedPrimaryConstructor.getAnnotations()); LexicalScope parameterScope = getPrimaryConstructorParametersScope( classDescriptor.getScopeForClassHeaderResolution(), unsubstitutedPrimaryConstructor); valueParameterResolver.resolveValueParameters( klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), parameterScope, c.getOuterDataFlowInfo(), trace); } } }
public void resolveConstructorParameterDefaultValuesAndAnnotations( @NotNull DataFlowInfo outerDataFlowInfo, @NotNull BindingTrace trace, @NotNull JetClass klass, @NotNull ConstructorDescriptor constructorDescriptor, @NotNull LexicalScope declaringScope) { List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters(); List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters(); LexicalScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor); valueParameterResolver.resolveValueParameters( valueParameters, valueParameterDescriptors, scope, outerDataFlowInfo, trace); }
public void resolveSecondaryConstructorBody( @NotNull final DataFlowInfo outerDataFlowInfo, @NotNull final BindingTrace trace, @NotNull final JetSecondaryConstructor constructor, @NotNull final ConstructorDescriptor descriptor, @NotNull LexicalScope declaringScope) { ForceResolveUtil.forceResolveAllContents(descriptor.getAnnotations()); final CallChecker callChecker = new ConstructorHeaderCallChecker(descriptor); resolveFunctionBody( outerDataFlowInfo, trace, constructor, descriptor, declaringScope, new Function1<LexicalScope, DataFlowInfo>() { @Override public DataFlowInfo invoke(@NotNull LexicalScope headerInnerScope) { return resolveSecondaryConstructorDelegationCall( outerDataFlowInfo, trace, headerInnerScope, constructor, descriptor, callChecker); } }, callChecker); }