示例#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
  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);
      }
    }
  }
示例#3
0
  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;
    }
  }
示例#4
0
 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());
     }
   }
 }
示例#5
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;
    }
示例#6
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);
  }
示例#7
0
  private void createCopyFunction(
      @NotNull MutableClassDescriptor classDescriptor,
      @NotNull ConstructorDescriptor constructorDescriptor) {
    SimpleFunctionDescriptor functionDescriptor =
        DescriptorResolver.createCopyFunctionDescriptor(
            constructorDescriptor.getValueParameters(), classDescriptor, trace);

    classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor);
  }
示例#8
0
  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));
          }
        }
      }
    }
  }
示例#9
0
  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);
      }
    }
  }
示例#10
0
  @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());
  }
示例#11
0
  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;
  }
示例#12
0
  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);
  }
示例#13
0
  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);
        }
      }
    }
  }
示例#14
0
  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);
  }
示例#15
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);
  }