@NotNull
  private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>>
      getSuperclassToFunctionsMultimap(
          @NotNull PsiMethodWrapper method,
          @NotNull BindingContext bindingContext,
          @NotNull ClassDescriptor containingClass) {
    Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create();

    Name functionName = Name.identifier(method.getName());
    int parameterCount = method.getParameters().size();

    for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
      ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor();
      assert klass != null;
      FqName fqName = DescriptorUtils.getFQName(klass).toSafe();

      for (FunctionDescriptor fun :
          klass.getDefaultType().getMemberScope().getFunctions(functionName)) {
        if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) {
          PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
          if (declaration instanceof PsiMethod) {
            result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
          } // else declaration is null or JetNamedFunction: both cases are processed later
        }
      }
    }
    return result;
  }
  @NotNull
  private JetType modifyTypeAccordingToSuperMethods(
      @NotNull JetType autoType,
      @NotNull List<TypeAndVariance> typesFromSuper,
      @NotNull TypeUsage howThisTypeIsUsed) {
    if (ErrorUtils.isErrorType(autoType)) {
      return autoType;
    }

    boolean resultNullable = typeMustBeNullable(autoType, typesFromSuper, howThisTypeIsUsed);
    ClassifierDescriptor resultClassifier = modifyTypeClassifier(autoType, typesFromSuper);
    List<TypeProjection> resultArguments =
        getTypeArgsOfType(autoType, resultClassifier, typesFromSuper);
    JetScope resultScope;
    if (resultClassifier instanceof ClassDescriptor) {
      resultScope = ((ClassDescriptor) resultClassifier).getMemberScope(resultArguments);
    } else {
      resultScope = autoType.getMemberScope();
    }

    JetTypeImpl type =
        new JetTypeImpl(
            autoType.getAnnotations(),
            resultClassifier.getTypeConstructor(),
            resultNullable,
            resultArguments,
            resultScope);

    PropagationHeuristics.checkArrayInReturnType(this, type, typesFromSuper);
    return type;
  }
Example #3
0
  // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
  private void checkSupertypeList(
      @NotNull MutableClassDescriptor supertypeOwner,
      @NotNull Map<JetTypeReference, JetType> supertypes,
      Set<TypeConstructor> allowedFinalSupertypes) {
    Set<TypeConstructor> typeConstructors = Sets.newHashSet();
    boolean classAppeared = false;
    for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
      JetTypeReference typeReference = entry.getKey();
      JetType supertype = entry.getValue();

      ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
      if (classDescriptor != null) {
        if (classDescriptor.getKind() != ClassKind.TRAIT) {
          if (classAppeared) {
            trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
          } else {
            classAppeared = true;
          }
        }
      } else {
        trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
      }

      TypeConstructor constructor = supertype.getConstructor();
      if (!typeConstructors.add(constructor)) {
        trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
      }

      if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) {
        trace.report(FINAL_SUPERTYPE.on(typeReference));
      }
    }
  }
  @NotNull
  public TypeInfoForCall getQualifiedExpressionExtendedTypeInfo(
      @NotNull JetQualifiedExpression expression,
      @NotNull ResolutionContext context,
      @NotNull ResolveMode resolveMode) {
    // TODO : functions as values
    JetExpression selectorExpression = expression.getSelectorExpression();
    JetExpression receiverExpression = expression.getReceiverExpression();
    JetTypeInfo receiverTypeInfo =
        expressionTypingServices.getTypeInfoWithNamespaces(
            receiverExpression,
            context.scope,
            NO_EXPECTED_TYPE,
            context.dataFlowInfo,
            context.trace);
    JetType receiverType = receiverTypeInfo.getType();
    if (selectorExpression == null) return TypeInfoForCall.create(null, context.dataFlowInfo);
    if (receiverType == null)
      receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());

    context = context.replaceDataFlowInfo(receiverTypeInfo.getDataFlowInfo());

    if (selectorExpression instanceof JetSimpleNameExpression) {
      ConstantUtils.propagateConstantValues(
          expression, context.trace, (JetSimpleNameExpression) selectorExpression);
    }

    TypeInfoForCall selectorReturnTypeInfo =
        getSelectorReturnTypeInfo(
            new ExpressionReceiver(receiverExpression, receiverType),
            expression.getOperationTokenNode(),
            selectorExpression,
            context,
            resolveMode);
    JetType selectorReturnType = selectorReturnTypeInfo.getType();

    // TODO move further
    if (!(receiverType instanceof NamespaceType)
        && expression.getOperationSign() == JetTokens.SAFE_ACCESS) {
      if (selectorReturnType != null
          && !selectorReturnType.isNullable()
          && !KotlinBuiltIns.getInstance().isUnit(selectorReturnType)) {
        if (receiverType.isNullable()) {
          selectorReturnType = TypeUtils.makeNullable(selectorReturnType);
        }
      }
    }

    // TODO : this is suspicious: remove this code?
    if (selectorReturnType != null) {
      context.trace.record(BindingContext.EXPRESSION_TYPE, selectorExpression, selectorReturnType);
    }
    JetTypeInfo typeInfo =
        JetTypeInfo.create(selectorReturnType, selectorReturnTypeInfo.getDataFlowInfo());
    if (resolveMode == ResolveMode.TOP_LEVEL_CALL) {
      DataFlowUtils.checkType(typeInfo.getType(), expression, context, typeInfo.getDataFlowInfo());
    }
    return TypeInfoForCall.create(typeInfo, selectorReturnTypeInfo);
  }
Example #5
0
 public static boolean containsErrorType(@Nullable JetType type) {
   if (type == null) return false;
   if (type.isError()) return true;
   for (TypeProjection projection : type.getArguments()) {
     if (containsErrorType(projection.getType())) return true;
   }
   return false;
 }
 private static Map<ClassDescriptor, JetType> getSuperclassToSupertypeMap(
     ClassDescriptor containingClass) {
   Map<ClassDescriptor, JetType> superclassToSupertype = Maps.newHashMap();
   for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) {
     ClassifierDescriptor superclass = supertype.getConstructor().getDeclarationDescriptor();
     assert superclass instanceof ClassDescriptor;
     superclassToSupertype.put((ClassDescriptor) superclass, supertype);
   }
   return superclassToSupertype;
 }
Example #7
0
 private String renderTypeWithoutEscape(@NotNull JetType type) {
   if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == CANT_INFER_TYPE_PARAMETER) {
     return "???";
   }
   if (type.isError()) {
     return type.toString();
   }
   if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(type)
       && prettyFunctionTypes) {
     return renderFunctionType(type);
   }
   return renderDefaultType(type);
 }
  public static FunctionDescriptor getInvokeFunction(@NotNull JetType functionType) {
    assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType);

    ClassifierDescriptor classDescriptorForFunction =
        functionType.getConstructor().getDeclarationDescriptor();
    assert classDescriptorForFunction instanceof ClassDescriptor;
    Collection<FunctionDescriptor> invokeFunctions =
        ((ClassDescriptor) classDescriptorForFunction)
            .getMemberScope(functionType.getArguments())
            .getFunctions(Name.identifier("invoke"));
    assert invokeFunctions.size() == 1;
    return invokeFunctions.iterator().next();
  }
 @Nullable
 private JetType lookupNamespaceOrClassObject(
     @NotNull JetSimpleNameExpression expression, @NotNull ResolutionContext context) {
   Name referencedName = expression.getReferencedNameAsName();
   ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
   if (classifier != null) {
     JetType classObjectType = classifier.getClassObjectType();
     if (classObjectType != null) {
       context.trace.record(REFERENCE_TARGET, expression, classifier);
       JetType result;
       if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
           && classifier instanceof ClassDescriptor) {
         JetScope scope =
             new ChainedScope(
                 classifier,
                 classObjectType.getMemberScope(),
                 getStaticNestedClassesScope((ClassDescriptor) classifier));
         result = new NamespaceType(referencedName, scope);
       } else if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
           || classifier.isClassObjectAValue()) {
         result = classObjectType;
       } else {
         context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
         result = null;
       }
       return DataFlowUtils.checkType(result, expression, context);
     }
   }
   JetType[] result = new JetType[1];
   TemporaryBindingTrace temporaryTrace =
       TemporaryBindingTrace.create(
           context.trace, "trace for namespace/class object lookup of name", referencedName);
   if (furtherNameLookup(expression, result, context.replaceBindingTrace(temporaryTrace))) {
     temporaryTrace.commit();
     return DataFlowUtils.checkType(result[0], expression, context);
   }
   // To report NO_CLASS_OBJECT when no namespace found
   if (classifier != null) {
     if (context.expressionPosition == ExpressionPosition.FREE) {
       context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
     }
     context.trace.record(REFERENCE_TARGET, expression, classifier);
     JetScope scopeForStaticMembersResolution =
         classifier instanceof ClassDescriptor
             ? getStaticNestedClassesScope((ClassDescriptor) classifier)
             : JetScope.EMPTY;
     return new NamespaceType(referencedName, scopeForStaticMembersResolution);
   }
   temporaryTrace.commit();
   return result[0];
 }
Example #10
0
  @NotNull
  private String renderDefaultType(@NotNull JetType type) {
    StringBuilder sb = new StringBuilder();

    sb.append(renderTypeName(type.getConstructor()));
    if (!type.getArguments().isEmpty()) {
      sb.append("<");
      appendTypeProjections(type.getArguments(), sb);
      sb.append(">");
    }
    if (type.isNullable()) {
      sb.append("?");
    }
    return sb.toString();
  }
Example #11
0
  /* TYPE PARAMETERS */
  private void renderTypeParameter(
      @NotNull TypeParameterDescriptor typeParameter,
      @NotNull StringBuilder builder,
      boolean topLevel) {
    if (topLevel) {
      builder.append(lt());
    }

    if (verbose) {
      builder.append("/*").append(typeParameter.getIndex()).append("*/ ");
    }

    if (typeParameter.isReified()) {
      builder.append(renderKeyword("reified")).append(" ");
    }
    String variance = typeParameter.getVariance().toString();
    if (!variance.isEmpty()) {
      builder.append(renderKeyword(variance)).append(" ");
    }
    renderName(typeParameter, builder);
    int upperBoundsCount = typeParameter.getUpperBounds().size();
    if ((upperBoundsCount > 1 && !topLevel) || upperBoundsCount == 1) {
      JetType upperBound = typeParameter.getUpperBounds().iterator().next();
      if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound) || alwaysRenderAny) {
        builder.append(" : ").append(renderType(upperBound));
      }
    } else if (topLevel) {
      boolean first = true;
      for (JetType upperBound : typeParameter.getUpperBounds()) {
        if (upperBound.equals(KotlinBuiltIns.getInstance().getDefaultBound())) {
          continue;
        }
        if (first) {
          builder.append(" : ");
        } else {
          builder.append(" & ");
        }
        builder.append(renderType(upperBound));
        first = false;
      }
    } else {
      // rendered with "where"
    }

    if (topLevel) {
      builder.append(">");
    }
  }
  @Nullable
  private JetType getExtendedClassObjectType(
      @NotNull JetType classObjectType,
      @NotNull Name referencedName,
      @NotNull ClassifierDescriptor classifier,
      @NotNull ResolutionContext context) {
    if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
        && classifier instanceof ClassDescriptor) {
      List<JetScope> scopes = new ArrayList<JetScope>(3);

      scopes.add(classObjectType.getMemberScope());
      scopes.add(getStaticNestedClassesScope((ClassDescriptor) classifier));

      NamespaceDescriptor namespace = context.scope.getNamespace(referencedName);
      if (namespace != null) {
        scopes.add(namespace.getMemberScope());
      }

      JetScope scope = new ChainedScope(classifier, scopes.toArray(new JetScope[scopes.size()]));
      return new NamespaceType(referencedName, scope);
    } else if (context.expressionPosition == ExpressionPosition.LHS_OF_DOT
        || classifier.isClassObjectAValue()) {
      return classObjectType;
    } else {
      return null;
    }
  }
 public void addSupertype(@NotNull JetType supertype) {
   assert !supertype.isError() : "Error types must be filtered out in DescriptorResolver";
   if (TypeUtils.getClassDescriptor(supertype) != null) {
     // See the Errors.SUPERTYPE_NOT_A_CLASS_OR_TRAIT
     supertypes.add(supertype);
   }
 }
Example #14
0
 public static boolean isErrorType(@NotNull JetType type) {
   return type != TypeUtils.NO_EXPECTED_TYPE
       && !(type instanceof NamespaceType)
       && ((type instanceof DeferredType
               && (((DeferredType) type).getActualType() == null
                   || isErrorType(((DeferredType) type).getActualType())))
           || type instanceof ErrorTypeImpl
           || isError(type.getConstructor()));
 }
  @NotNull
  private ClassifierDescriptor modifyTypeClassifier(
      @NotNull JetType autoType, @NotNull List<TypeAndVariance> typesFromSuper) {
    ClassifierDescriptor classifier = autoType.getConstructor().getDeclarationDescriptor();
    if (!(classifier instanceof ClassDescriptor)) {
      assert classifier != null : "no declaration descriptor for type " + autoType;

      if (classifier instanceof TypeParameterDescriptor
          && autoTypeParameterToModified.containsKey(classifier)) {
        return autoTypeParameterToModified.get(classifier);
      }
      return classifier;
    }
    ClassDescriptor klass = (ClassDescriptor) classifier;

    CollectionClassMapping collectionMapping = CollectionClassMapping.getInstance();

    boolean someSupersMutable = false;
    boolean someSupersCovariantReadOnly = false;
    boolean someSupersNotCovariantReadOnly = false;
    for (TypeAndVariance typeFromSuper : typesFromSuper) {
      ClassifierDescriptor classifierFromSuper =
          typeFromSuper.type.getConstructor().getDeclarationDescriptor();
      if (classifierFromSuper instanceof ClassDescriptor) {
        ClassDescriptor classFromSuper = (ClassDescriptor) classifierFromSuper;

        if (collectionMapping.isMutableCollection(classFromSuper)) {
          someSupersMutable = true;
        } else if (collectionMapping.isReadOnlyCollection(classFromSuper)) {
          if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
            someSupersCovariantReadOnly = true;
          } else {
            someSupersNotCovariantReadOnly = true;
          }
        }
      }
    }

    if (someSupersMutable && someSupersNotCovariantReadOnly) {
      reportError("Incompatible types in superclasses: " + typesFromSuper);
      return classifier;
    } else if (someSupersMutable) {
      if (collectionMapping.isReadOnlyCollection(klass)) {
        return collectionMapping.convertReadOnlyToMutable(klass);
      }
    } else if (someSupersNotCovariantReadOnly || someSupersCovariantReadOnly) {
      if (collectionMapping.isMutableCollection(klass)) {
        return collectionMapping.convertMutableToReadOnly(klass);
      }
    }

    ClassifierDescriptor fixed =
        PropagationHeuristics.tryToFixOverridingTWithRawType(this, typesFromSuper);
    return fixed != null ? fixed : classifier;
  }
  private boolean typeMustBeNullable(
      @NotNull JetType autoType,
      @NotNull List<TypeAndVariance> typesFromSuper,
      @NotNull TypeUsage howThisTypeIsUsed) {
    boolean someSupersNotCovariantNullable = false;
    boolean someSupersCovariantNullable = false;
    boolean someSupersNotNull = false;
    for (TypeAndVariance typeFromSuper : typesFromSuper) {
      if (!typeFromSuper.type.isNullable()) {
        someSupersNotNull = true;
      } else {
        if (typeFromSuper.varianceOfPosition == Variance.OUT_VARIANCE) {
          someSupersCovariantNullable = true;
        } else {
          someSupersNotCovariantNullable = true;
        }
      }
    }

    if (someSupersNotNull && someSupersNotCovariantNullable) {
      reportError("Incompatible types in superclasses: " + typesFromSuper);
      return autoType.isNullable();
    } else if (someSupersNotNull) {
      return false;
    } else if (someSupersNotCovariantNullable || someSupersCovariantNullable) {
      boolean annotatedAsNotNull = howThisTypeIsUsed != TYPE_ARGUMENT && !autoType.isNullable();

      if (annotatedAsNotNull && someSupersNotCovariantNullable) {
        reportError(
            "In superclass type is nullable: "
                + typesFromSuper
                + ", in subclass it is not: "
                + autoType);
        return true;
      }

      return !annotatedAsNotNull;
    }
    return autoType.isNullable();
  }
Example #17
0
  @NotNull
  private String renderFunctionType(@NotNull JetType type) {
    StringBuilder sb = new StringBuilder();

    JetType receiverType = KotlinBuiltIns.getInstance().getReceiverType(type);
    if (receiverType != null) {
      sb.append(renderType(receiverType));
      sb.append(".");
    }

    sb.append("(");
    appendTypeProjections(
        KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(type), sb);
    sb.append(") " + arrow() + " ");
    sb.append(renderType(KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(type)));

    if (type.isNullable()) {
      return "(" + sb + ")?";
    }
    return sb.toString();
  }
  @NotNull
  private List<TypeProjection> getTypeArgsOfType(
      @NotNull JetType autoType,
      @NotNull ClassifierDescriptor classifier,
      @NotNull List<TypeAndVariance> typesFromSuper) {
    List<TypeProjection> autoArguments = autoType.getArguments();

    if (!(classifier instanceof ClassDescriptor)) {
      assert autoArguments.isEmpty()
          : "Unexpected type arguments when type constructor is not ClassDescriptor, type = "
              + autoType;
      return autoArguments;
    }

    List<List<TypeProjectionAndVariance>> typeArgumentsFromSuper =
        calculateTypeArgumentsFromSuper((ClassDescriptor) classifier, typesFromSuper);

    // Modify type arguments using info from typesFromSuper
    List<TypeProjection> resultArguments = Lists.newArrayList();
    for (TypeParameterDescriptor parameter : classifier.getTypeConstructor().getParameters()) {
      TypeProjection argument = autoArguments.get(parameter.getIndex());

      JetType argumentType = argument.getType();
      List<TypeProjectionAndVariance> projectionsFromSuper =
          typeArgumentsFromSuper.get(parameter.getIndex());
      List<TypeAndVariance> argTypesFromSuper = getTypes(projectionsFromSuper);

      JetType type =
          modifyTypeAccordingToSuperMethods(argumentType, argTypesFromSuper, TYPE_ARGUMENT);
      Variance projectionKind =
          calculateArgumentProjectionKindFromSuper(argument, projectionsFromSuper);

      resultArguments.add(new TypeProjection(projectionKind, type));
    }
    return resultArguments;
  }
 public String toString() {
   return type.toString();
 }
Example #20
0
 public static boolean isUninferredParameter(@Nullable JetType type) {
   return type != null && type.getConstructor() instanceof UninferredParameterTypeConstructor;
 }