예제 #1
0
  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);
  }
예제 #2
0
    @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;
    }
예제 #3
0
  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);
  }
예제 #4
0
  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);
  }