Substituted special error type for not inferred parameter

Rendered it as T (of red color) in the renderer HTML_FOR_NOT_INFERRED_TYPE_PARAMETERS
 instead of '???' without information about type parameter
This commit is contained in:
Svetlana Isakova
2014-04-22 09:57:24 +04:00
parent 4a8255a606
commit e59fa2083e
11 changed files with 145 additions and 56 deletions
@@ -33,7 +33,6 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.types.TypeUtils.CANT_INFER_TYPE_PARAMETER;
import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;
public class CallResolverUtil {
@@ -51,7 +50,8 @@ public class CallResolverUtil {
// last argument is return type of function type
List<TypeProjection> functionParameters = arguments.subList(0, arguments.size() - 1);
for (TypeProjection functionParameter : functionParameters) {
if (TypeUtils.equalsOrContainsAsArgument(functionParameter.getType(), CANT_INFER_TYPE_PARAMETER, DONT_CARE)) {
if (TypeUtils.containsSpecialType(functionParameter.getType(), DONT_CARE)
|| ErrorUtils.containsUninferredParameter(functionParameter.getType())) {
return true;
}
}
@@ -73,7 +73,7 @@ public class CallResolverUtil {
return new JetTypeImpl(type.getAnnotations(), type.getConstructor(), type.isNullable(), newArguments, type.getMemberScope());
}
private static boolean hasReturnTypeDependentOnNotInferredParams(
private static boolean hasReturnTypeDependentOnUninferredParams(
@NotNull CallableDescriptor candidateDescriptor,
@NotNull ConstraintSystem constraintSystem
) {
@@ -95,7 +95,7 @@ public class CallResolverUtil {
@NotNull CallableDescriptor candidateDescriptor,
@NotNull ConstraintSystem constraintSystem
) {
if (hasReturnTypeDependentOnNotInferredParams(candidateDescriptor, constraintSystem)) return false;
if (hasReturnTypeDependentOnUninferredParams(candidateDescriptor, constraintSystem)) return false;
// Expected type mismatch was reported before as 'TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH'
if (constraintSystem.getStatus().hasOnlyErrorsFromPosition(ConstraintPosition.EXPECTED_TYPE_POSITION)) return false;
@@ -31,10 +31,7 @@ import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.name.LabelName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.CommonSupertypes;
import org.jetbrains.jet.lang.types.DeferredType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeInfo;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
@@ -276,7 +273,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
}
}
else {
if (expectedType == null || expectedType == DONT_CARE || expectedType == CANT_INFER_TYPE_PARAMETER) {
if (expectedType == null || expectedType == DONT_CARE || ErrorUtils.isUninferredParameter(expectedType)) {
context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter));
}
if (expectedType != null) {
@@ -24,6 +24,7 @@ import com.google.common.collect.Sets;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.util.containers.ContainerUtil;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
@@ -40,9 +41,8 @@ import java.util.Set;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL;
import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.Bound;
import static org.jetbrains.jet.lang.types.TypeUtils.CANT_INFER_TYPE_PARAMETER;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*;
import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE;
public class ConstraintSystemImpl implements ConstraintSystem {
@@ -125,7 +125,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
private static Map<TypeParameterDescriptor, TypeProjection> getParameterToInferredValueMap(
@NotNull Map<TypeParameterDescriptor, TypeBoundsImpl> typeParameterBounds,
@Nullable TypeProjection defaultTypeProjection
@NotNull Function1<TypeParameterDescriptor, TypeProjection> getDefaultTypeProjection
) {
Map<TypeParameterDescriptor, TypeProjection> substitutionContext = Maps.newHashMap();
for (Map.Entry<TypeParameterDescriptor, TypeBoundsImpl> entry : typeParameterBounds.entrySet()) {
@@ -134,20 +134,41 @@ public class ConstraintSystemImpl implements ConstraintSystem {
TypeProjection typeProjection;
JetType value = typeBounds.getValue();
if (value != null && !TypeUtils.equalsOrContainsAsArgument(value, TypeUtils.DONT_CARE)) {
if (value != null && !TypeUtils.containsSpecialType(value, TypeUtils.DONT_CARE)) {
typeProjection = new TypeProjectionImpl(value);
}
else {
typeProjection = defaultTypeProjection;
typeProjection = getDefaultTypeProjection.invoke(typeParameter);
}
substitutionContext.put(typeParameter, typeProjection);
}
return substitutionContext;
}
private TypeSubstitutor createTypeSubstitutorWithDefaultForUnknownTypeParameter(@NotNull JetType defaultType) {
return TypeUtils.makeSubstitutorForTypeParametersMap(
getParameterToInferredValueMap(typeParameterBounds, new TypeProjectionImpl(defaultType)));
private TypeSubstitutor replaceUninferredBy(@NotNull Function1<TypeParameterDescriptor, TypeProjection> getDefaultValue) {
return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue));
}
private TypeSubstitutor replaceUninferredBy(@NotNull final JetType defaultValue) {
return replaceUninferredBy(
new Function1<TypeParameterDescriptor, TypeProjection>() {
@Override
public TypeProjection invoke(TypeParameterDescriptor descriptor) {
return new TypeProjectionImpl(defaultValue);
}
}
);
}
private TypeSubstitutor replaceUninferredBySpecialErrorType() {
return replaceUninferredBy(
new Function1<TypeParameterDescriptor, TypeProjection>() {
@Override
public TypeProjection invoke(TypeParameterDescriptor descriptor) {
return new TypeProjectionImpl(ErrorUtils.createUninferredParameterType(descriptor));
}
}
);
}
@NotNull
@@ -323,7 +344,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
}
private boolean isErrorOrSpecialType(@Nullable JetType type) {
if (type == DONT_CARE || type == CANT_INFER_TYPE_PARAMETER) {
if (type == DONT_CARE || ErrorUtils.isUninferredParameter(type)) {
return true;
}
@@ -474,13 +495,13 @@ public class ConstraintSystemImpl implements ConstraintSystem {
@NotNull
@Override
public TypeSubstitutor getResultingSubstitutor() {
return createTypeSubstitutorWithDefaultForUnknownTypeParameter(TypeUtils.CANT_INFER_TYPE_PARAMETER);
return replaceUninferredBySpecialErrorType();
}
@NotNull
@Override
public TypeSubstitutor getCurrentSubstitutor() {
return createTypeSubstitutorWithDefaultForUnknownTypeParameter(TypeUtils.DONT_CARE);
return replaceUninferredBy(TypeUtils.DONT_CARE);
}
@NotNull
@@ -16,6 +16,7 @@
package org.jetbrains.jet.lang.types;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
@@ -392,5 +393,39 @@ public class ErrorUtils {
return ERROR_MODULE;
}
public static boolean isUninferredParameter(@Nullable JetType type) {
return type instanceof UninferredParameterType;
}
public static boolean containsUninferredParameter(@Nullable JetType type) {
return TypeUtils.containsSpecialType(type, new Function1<JetType, Boolean>() {
@Override
public Boolean invoke(JetType argumentType) {
return isUninferredParameter(argumentType);
}
});
}
public static UninferredParameterType createUninferredParameterType(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
return new UninferredParameterType(typeParameterDescriptor);
}
public static class UninferredParameterType extends ErrorTypeImpl {
private final TypeParameterDescriptor typeParameterDescriptor;
private UninferredParameterType(
@NotNull TypeParameterDescriptor descriptor
) {
super(createErrorTypeConstructorWithCustomDebugName("CANT_INFER_TYPE_PARAMETER: " + descriptor.getName()),
createErrorScope("Scope for error type for not inferred parameter: " + descriptor.getName()));
typeParameterDescriptor = descriptor;
}
@NotNull
public TypeParameterDescriptor getTypeParameterDescriptor() {
return typeParameterDescriptor;
}
}
private ErrorUtils() {}
}
@@ -45,7 +45,6 @@ import java.util.*;
public class TypeUtils {
public static final JetType DONT_CARE = ErrorUtils.createErrorTypeWithCustomDebugName("DONT_CARE");
public static final JetType CANT_INFER_TYPE_PARAMETER = ErrorUtils.createErrorTypeWithCustomDebugName("CANT_INFER_TYPE_PARAMETER");
public static final JetType PLACEHOLDER_FUNCTION_TYPE = ErrorUtils.createErrorTypeWithCustomDebugName("PLACEHOLDER_FUNCTION_TYPE");
public static final JetType CANT_INFER_LAMBDA_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
@@ -494,16 +493,24 @@ public class TypeUtils {
return false;
}
public static boolean equalsOrContainsAsArgument(@Nullable JetType type, @NotNull JetType... possibleArgumentTypes) {
return equalsOrContainsAsArgument(type, Sets.newHashSet(possibleArgumentTypes));
public static boolean containsSpecialType(@Nullable JetType type, @NotNull final JetType specialType) {
return containsSpecialType(type, new Function1<JetType, Boolean>() {
@Override
public Boolean invoke(JetType type) {
return specialType.equals(type);
}
});
}
private static boolean equalsOrContainsAsArgument(@Nullable JetType type, @NotNull Set<JetType> possibleArgumentTypes) {
public static boolean containsSpecialType(
@Nullable JetType type,
@NotNull Function1<JetType, Boolean> isSpecialType
) {
if (type == null) return false;
if (possibleArgumentTypes.contains(type)) return true;
if (isSpecialType.invoke(type)) return true;
if (type instanceof PackageType) return false;
for (TypeProjection projection : type.getArguments()) {
if (equalsOrContainsAsArgument(projection.getType(), possibleArgumentTypes)) return true;
if (containsSpecialType(projection.getType(), isSpecialType)) return true;
}
return false;
}
@@ -66,6 +66,10 @@ public interface DescriptorRenderer extends Renderer<DeclarationDescriptor> {
DescriptorRenderer HTML = new DescriptorRendererBuilder().setTextFormat(TextFormat.HTML).build();
DescriptorRenderer HTML_FOR_UNINFERRED_TYPE_PARAMS = new DescriptorRendererBuilder()
.setUninferredTypeParameterAsName(true)
.setTextFormat(TextFormat.HTML).build();
@NotNull
String renderType(@NotNull JetType type);
@@ -36,6 +36,7 @@ public class DescriptorRendererBuilder {
private boolean normalizedVisibilities = false;
private boolean showInternalKeyword = true;
private boolean prettyFunctionTypes = true;
private boolean uninferredTypeParameterAsName = false;
private boolean includePropertyConstant = false;
@NotNull
private DescriptorRenderer.OverrideRenderingPolicy overrideRenderingPolicy = DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN;
@@ -144,6 +145,12 @@ public class DescriptorRendererBuilder {
return this;
}
@NotNull
public DescriptorRendererBuilder setUninferredTypeParameterAsName(boolean uninferredTypeParameterAsName) {
this.uninferredTypeParameterAsName = uninferredTypeParameterAsName;
return this;
}
public DescriptorRendererBuilder setIncludePropertyConstant(boolean includePropertyConstant) {
this.includePropertyConstant = includePropertyConstant;
return this;
@@ -151,10 +158,10 @@ public class DescriptorRendererBuilder {
@NotNull
public DescriptorRenderer build() {
return new DescriptorRendererImpl(shortNames, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor,
verbose, unitReturnType, normalizedVisibilities, showInternalKeyword, prettyFunctionTypes,
overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses,
includePropertyConstant);
return new DescriptorRendererImpl(
shortNames, withDefinedIn, modifiers, startFromName, debugMode, classWithPrimaryConstructor, verbose, unitReturnType,
normalizedVisibilities, showInternalKeyword, prettyFunctionTypes, uninferredTypeParameterAsName,
overrideRenderingPolicy, valueParametersHandler, textFormat, excludedAnnotationClasses, includePropertyConstant);
}
}
@@ -41,6 +41,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.*;
import static org.jetbrains.jet.lang.types.ErrorUtils.UninferredParameterType;
import static org.jetbrains.jet.lang.types.TypeUtils.*;
public class DescriptorRendererImpl implements DescriptorRenderer {
@@ -55,6 +56,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
private final boolean normalizedVisibilities;
private final boolean showInternalKeyword;
private final boolean prettyFunctionTypes;
private final boolean uninferredTypeParameterAsName;
@NotNull
private final OverrideRenderingPolicy overrideRenderingPolicy;
@@ -78,6 +80,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
boolean normalizedVisibilities,
boolean showInternalKeyword,
boolean prettyFunctionTypes,
boolean uninferredTypeParameterAsName,
@NotNull OverrideRenderingPolicy overrideRenderingPolicy,
@NotNull ValueParametersHandler handler,
@NotNull TextFormat textFormat,
@@ -100,6 +103,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
this.includePropertyConstant = includePropertyConstant;
this.excludedAnnotationClasses = Sets.newHashSet(excludedAnnotationClasses);
this.prettyFunctionTypes = prettyFunctionTypes;
this.uninferredTypeParameterAsName = uninferredTypeParameterAsName;
}
/* FORMATTING */
@@ -114,6 +118,17 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
throw new IllegalStateException("Unexpected textFormat: " + textFormat);
}
@NotNull
private String renderError(@NotNull String keyword) {
switch (textFormat) {
case PLAIN:
return keyword;
case HTML:
return "<font color=red><b>" + keyword + "</b></font>";
}
throw new IllegalStateException("Unexpected textFormat: " + textFormat);
}
@NotNull
private String escape(@NotNull String string) {
switch (textFormat) {
@@ -130,6 +145,11 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
return escape("<");
}
@NotNull
private String gt() {
return escape(">");
}
@NotNull
private String arrow() {
switch (textFormat) {
@@ -213,22 +233,13 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
@NotNull
@Override
public String renderType(@NotNull JetType type) {
return escape(renderTypeWithoutEscape(type));
}
@NotNull
@Override
public String renderTypeArguments(@NotNull List<TypeProjection> typeArguments) {
if (typeArguments.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
sb.append("<");
appendTypeProjections(typeArguments, sb);
sb.append(">");
return sb.toString();
}
private String renderTypeWithoutEscape(@NotNull JetType type) {
if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == CANT_INFER_TYPE_PARAMETER || type == DONT_CARE) {
if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == DONT_CARE) {
return "???";
}
if (ErrorUtils.isUninferredParameter(type)) {
if (uninferredTypeParameterAsName) {
return renderError(((UninferredParameterType) type).getTypeParameterDescriptor().getName().toString());
}
return "???";
}
if (type instanceof LazyType && debugMode) {
@@ -243,6 +254,17 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
return renderDefaultType(type);
}
@NotNull
@Override
public String renderTypeArguments(@NotNull List<TypeProjection> typeArguments) {
if (typeArguments.isEmpty()) return "";
StringBuilder sb = new StringBuilder();
sb.append(lt());
appendTypeProjections(typeArguments, sb);
sb.append(gt());
return sb.toString();
}
@NotNull
private String renderDefaultType(@NotNull JetType type) {
StringBuilder sb = new StringBuilder();
@@ -253,11 +275,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
else {
sb.append(renderTypeName(type.getConstructor()));
}
if (!type.getArguments().isEmpty()) {
sb.append("<");
appendTypeProjections(type.getArguments(), sb);
sb.append(">");
}
sb.append(renderTypeArguments(type.getArguments()));
if (type.isNullable()) {
sb.append("?");
}
@@ -520,7 +538,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
}
if (topLevel) {
builder.append(">");
builder.append(gt());
}
}
@@ -538,7 +556,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
builder.append(", ");
}
}
builder.append(">");
builder.append(gt());
if (withSpace) {
builder.append(" ");
}
@@ -2,4 +2,4 @@ trait Base
class Some<<caret>T: Base>
//INFO: &lt;T : Base> <i>defined in</i> Some
//INFO: &lt;T : Base&gt; <i>defined in</i> Some
@@ -2,4 +2,4 @@ fun testing() {
<caret>SomeClass<List<String>>()
}
// INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : kotlin.List&lt;kotlin.Any?&gt;?>() <i>defined in</i> SomeClass<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
// INFO: <b>public</b> <b>constructor</b> SomeClass&lt;T : kotlin.List&lt;kotlin.Any?&gt;?&gt;() <i>defined in</i> SomeClass<br/>Java declaration:<br/>[light_idea_test_case] public class SomeClass&lt;T extends java.util.List&gt; extends Object
@@ -2,4 +2,4 @@ fun test() {
listOf(1, 2, 4).<caret>filter { it > 0 }
}
// INFO: kotlin.inline <b>public</b> <b>fun</b> &lt;T> kotlin.Iterable&lt;T&gt;.filter(predicate: (T) &rarr; kotlin.Boolean): kotlin.List&lt;T&gt; <i>defined in</i> kotlin<br/><p>Returns a list containing all elements matching the given *predicate*<br/></p>
// INFO: kotlin.inline <b>public</b> <b>fun</b> &lt;T&gt; kotlin.Iterable&lt;T&gt;.filter(predicate: (T) &rarr; kotlin.Boolean): kotlin.List&lt;T&gt; <i>defined in</i> kotlin<br/><p>Returns a list containing all elements matching the given *predicate*<br/></p>