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 processPrimaryConstructor( @NotNull TopDownAnalysisContext c, @NotNull MutableClassDescriptor classDescriptor, @NotNull JetClass klass) { // TODO : not all the parameters are real properties JetScope memberScope = classDescriptor.getScopeForClassHeaderResolution(); ConstructorDescriptor constructorDescriptor = descriptorResolver.resolvePrimaryConstructorDescriptor( memberScope, classDescriptor, klass, trace); if (constructorDescriptor != null) { List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters(); List<JetParameter> primaryConstructorParameters = klass.getPrimaryConstructorParameters(); assert valueParameterDescriptors.size() == primaryConstructorParameters.size(); List<ValueParameterDescriptor> notProperties = new ArrayList<ValueParameterDescriptor>(); for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) { JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex()); if (parameter.getValOrVarNode() != null) { PropertyDescriptor propertyDescriptor = descriptorResolver.resolvePrimaryConstructorParameterToAProperty( classDescriptor, valueParameterDescriptor, memberScope, parameter, trace); classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor); c.getPrimaryConstructorParameterProperties().put(parameter, propertyDescriptor); } else { notProperties.add(valueParameterDescriptor); } } if (classDescriptor.getKind() != ClassKind.TRAIT) { classDescriptor.setPrimaryConstructor(constructorDescriptor); classDescriptor.addConstructorParametersToInitializersScope(notProperties); } } }
private void resolveSecondaryConstructorBodies() { for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : this.context.getConstructors().entrySet()) { JetSecondaryConstructor constructor = entry.getKey(); ConstructorDescriptor descriptor = entry.getValue(); resolveSecondaryConstructorBody(constructor, descriptor); assert descriptor.getReturnType() != null; } }
private void resolvePrimaryConstructorParameters() { for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { JetClass klass = entry.getKey(); MutableClassDescriptor classDescriptor = entry.getValue(); ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); if (unsubstitutedPrimaryConstructor != null) { checkDefaultParameterValues( klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), classDescriptor.getScopeForInitializers()); } } }
@Override public Void visitConstructorDescriptor( ConstructorDescriptor constructorDescriptor, StringBuilder builder) { renderVisibility(constructorDescriptor.getVisibility(), builder); builder.append(renderKeyword("ctor")).append(" "); ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration(); builder.append(classDescriptor.getName()); renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder); renderValueParameters(constructorDescriptor, builder); return null; }
private void renderConstructor( @NotNull ConstructorDescriptor constructor, @NotNull StringBuilder builder) { renderAnnotations(constructor, builder); renderVisibility(constructor.getVisibility(), builder); renderMemberKind(constructor, builder); builder.append(renderKeyword("constructor")).append(" "); ClassDescriptor classDescriptor = constructor.getContainingDeclaration(); renderName(classDescriptor, builder); renderTypeParameters(classDescriptor.getTypeConstructor().getParameters(), builder, false); renderValueParameters(constructor, builder); renderWhereSuffix(constructor.getTypeParameters(), builder); }
private void createCopyFunction( @NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createCopyFunctionDescriptor( constructorDescriptor.getValueParameters(), classDescriptor, trace); classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); }
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); } } }
@NotNull private JetScope computeScopeForPropertyInitializerResolution() { ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor(); if (primaryConstructor == null) return getScopeForMemberDeclarationResolution(); WritableScopeImpl scope = new WritableScopeImpl( JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with constructor parameters in " + getName()); for (ValueParameterDescriptor valueParameterDescriptor : primaryConstructor.getValueParameters()) { scope.addVariableDescriptor(valueParameterDescriptor); } scope.changeLockLevel(WritableScope.LockLevel.READING); return new ChainedScope( this, "ScopeForPropertyInitializerResolution: " + getName(), scope, getScopeForMemberDeclarationResolution()); }
public JetScope getScopeForPropertyInitializerResolution() { ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor(); if (primaryConstructor == null) return getScopeForMemberDeclarationResolution(); if (scopeForPropertyInitializerResolution == null) { WritableScopeImpl scope = new WritableScopeImpl( JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Property Initializer Resolution"); List<ValueParameterDescriptor> parameters = primaryConstructor.getValueParameters(); for (ValueParameterDescriptor valueParameterDescriptor : parameters) { scope.addVariableDescriptor(valueParameterDescriptor); } scope.changeLockLevel(WritableScope.LockLevel.READING); scopeForPropertyInitializerResolution = new ChainedScope(this, scope, getScopeForMemberDeclarationResolution()); } return scopeForPropertyInitializerResolution; }
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); }
private void createComponentFunctions( @NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { int parameterIndex = 0; for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) { if (!parameter.getType().isError()) { PropertyDescriptor property = trace.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter); if (property != null) { ++parameterIndex; SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createComponentFunctionDescriptor( parameterIndex, property, parameter, classDescriptor, trace); classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); } } } }
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); }
private void resolveSecondaryConstructorBody( JetSecondaryConstructor declaration, final ConstructorDescriptor descriptor) { if (!context.completeAnalysisNeeded(declaration)) return; MutableClassDescriptor classDescriptor = (MutableClassDescriptor) descriptor.getContainingDeclaration(); final JetScope scopeForSupertypeInitializers = FunctionDescriptorUtil.getFunctionInnerScope( classDescriptor.getScopeForSupertypeResolution(), descriptor, trace); // contains only constructor parameters final JetScope scopeForConstructorBody = FunctionDescriptorUtil.getFunctionInnerScope( classDescriptor.getScopeForInitializers(), descriptor, trace); // contains members & backing fields final DataFlowInfo dataFlowInfo = DataFlowInfo.EMPTY; // TODO: dataFlowInfo PsiElement nameElement = declaration.getNameNode().getPsi(); if (classDescriptor.getUnsubstitutedPrimaryConstructor() == null) { trace.report(SECONDARY_CONSTRUCTOR_BUT_NO_PRIMARY.on(nameElement)); } else { List<JetDelegationSpecifier> initializers = declaration.getInitializers(); if (initializers.isEmpty()) { trace.report(SECONDARY_CONSTRUCTOR_NO_INITIALIZER_LIST.on(nameElement)); } else { initializers .get(0) .accept( new JetVisitorVoid() { @Override public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) { JetTypeReference typeReference = call.getTypeReference(); if (typeReference != null) { callResolver.resolveFunctionCall( trace, scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); } } @Override public void visitDelegationToThisCall(JetDelegatorToThisCall call) { // TODO : check that there's no recursion in this() calls // TODO : check: if a this() call is present, no other initializers are allowed ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); callResolver.resolveFunctionCall( trace, scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo); // call.getThisReference(), // classDescriptor, // classDescriptor.getDefaultType(), // call); // trace.getErrorHandler().genericError(call.getNode(), // "this-calls are not supported"); } @Override public void visitDelegationByExpressionSpecifier( JetDelegatorByExpressionSpecifier specifier) { trace.report(BY_IN_SECONDARY_CONSTRUCTOR.on(specifier)); } @Override public void visitDelegationToSuperClassSpecifier( JetDelegatorToSuperClass specifier) { trace.report(INITIALIZER_WITH_NO_ARGUMENTS.on(specifier)); } @Override public void visitDelegationSpecifier(JetDelegationSpecifier specifier) { throw new IllegalStateException(); } }); for (int i = 1, initializersSize = initializers.size(); i < initializersSize; i++) { JetDelegationSpecifier initializer = initializers.get(i); trace.report(MANY_CALLS_TO_THIS.on(initializer)); } } } JetExpression bodyExpression = declaration.getBodyExpression(); if (bodyExpression != null) { expressionTypingServices.checkFunctionReturnType( scopeForConstructorBody, declaration, descriptor, JetStandardClasses.getUnitType(), trace); } checkDefaultParameterValues( declaration.getValueParameters(), descriptor.getValueParameters(), scopeForConstructorBody); }