Пример #1
0
  private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) {
    Multimap<TypeConstructor, TypeProjection> multimap =
        SubstitutionUtils.buildDeepSubstitutionMultimap(classDescriptor.getDefaultType());
    for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry :
        multimap.asMap().entrySet()) {
      Collection<TypeProjection> projections = entry.getValue();
      if (projections.size() > 1) {
        TypeConstructor typeConstructor = entry.getKey();
        DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
        assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
        TypeParameterDescriptor typeParameterDescriptor =
            (TypeParameterDescriptor) declarationDescriptor;

        // Immediate arguments of supertypes cannot be projected
        Set<JetType> conflictingTypes = Sets.newLinkedHashSet();
        for (TypeProjection projection : projections) {
          conflictingTypes.add(projection.getType());
        }
        removeDuplicateTypes(conflictingTypes);
        if (conflictingTypes.size() > 1) {
          DeclarationDescriptor containingDeclaration =
              typeParameterDescriptor.getContainingDeclaration();
          assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
          JetClassOrObject psiElement =
              (JetClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);
          assert psiElement != null;
          JetDelegationSpecifierList delegationSpecifierList =
              psiElement.getDelegationSpecifierList();
          assert delegationSpecifierList != null;
          //
          // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter
          // " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + "
          // has inconsistent values: " + conflictingTypes);
          trace.report(
              INCONSISTENT_TYPE_PARAMETER_VALUES.on(
                  delegationSpecifierList,
                  typeParameterDescriptor,
                  (ClassDescriptor) containingDeclaration,
                  conflictingTypes));
        }
      }
    }
  }
Пример #2
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);
      }
    }
  }
Пример #3
0
  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());
    }
  }
Пример #4
0
  private void checkPrimaryConstructor(
      JetClassOrObject classOrObject, ClassDescriptor classDescriptor) {
    ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
    JetPrimaryConstructor declaration = classOrObject.getPrimaryConstructor();
    if (primaryConstructor == null || declaration == null) return;

    for (JetParameter parameter : declaration.getValueParameters()) {
      PropertyDescriptor propertyDescriptor =
          trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
      if (propertyDescriptor != null) {
        modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor);
      }
    }

    if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) {
      trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList()));
    }

    if (!(classOrObject instanceof JetClass)) {
      trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration));
    }

    checkConstructorDeclaration(primaryConstructor, declaration);
  }
Пример #5
0
 private void checkAnnotationClassWithBody(JetClassOrObject classOrObject) {
   if (classOrObject.getBody() != null) {
     trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody()));
   }
 }
Пример #6
0
  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);
  }