diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java index c6ee3681759..334bc8fe4a3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolverUtil.java @@ -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 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 6da1ee60f01..9f032d4c9bc 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -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) { diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java index 109a51ab5a0..7bbff95999a 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.java @@ -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 getParameterToInferredValueMap( @NotNull Map typeParameterBounds, - @Nullable TypeProjection defaultTypeProjection + @NotNull Function1 getDefaultTypeProjection ) { Map substitutionContext = Maps.newHashMap(); for (Map.Entry 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 getDefaultValue) { + return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue)); + } + + private TypeSubstitutor replaceUninferredBy(@NotNull final JetType defaultValue) { + return replaceUninferredBy( + new Function1() { + @Override + public TypeProjection invoke(TypeParameterDescriptor descriptor) { + return new TypeProjectionImpl(defaultValue); + } + } + ); + } + + private TypeSubstitutor replaceUninferredBySpecialErrorType() { + return replaceUninferredBy( + new Function1() { + @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 diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java index d8c5baaa148..314bedf57c7 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/ErrorUtils.java @@ -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() { + @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() {} } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java index 4b76340dd03..47a5f1fcbe8 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -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() { + @Override + public Boolean invoke(JetType type) { + return specialType.equals(type); + } + }); } - private static boolean equalsOrContainsAsArgument(@Nullable JetType type, @NotNull Set possibleArgumentTypes) { + public static boolean containsSpecialType( + @Nullable JetType type, + @NotNull Function1 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; } diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java index 0bd66ed6670..3765eb18c48 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java @@ -66,6 +66,10 @@ public interface DescriptorRenderer extends Renderer { 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); diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererBuilder.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererBuilder.java index d598f4d2b11..319360546f0 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererBuilder.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererBuilder.java @@ -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); } } diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java index e3ebfd9bbff..32db515a746 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java @@ -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 "" + keyword + ""; + } + 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 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 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(" "); } diff --git a/idea/testData/editor/quickDoc/AtTypeParameter.kt b/idea/testData/editor/quickDoc/AtTypeParameter.kt index fe5c5c2bf9b..05aa63998ab 100644 --- a/idea/testData/editor/quickDoc/AtTypeParameter.kt +++ b/idea/testData/editor/quickDoc/AtTypeParameter.kt @@ -2,4 +2,4 @@ trait Base class Some<T: Base> -//INFO: <T : Base> defined in Some \ No newline at end of file +//INFO: <T : Base> defined in Some \ No newline at end of file diff --git a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt b/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt index 33629568b9b..06ec46b74f4 100644 --- a/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt +++ b/idea/testData/editor/quickDoc/JavaClassUsedInKotlin.kt @@ -2,4 +2,4 @@ fun testing() { SomeClass>() } -// INFO: public constructor SomeClass<T : kotlin.List<kotlin.Any?>?>() defined in SomeClass
Java declaration:
[light_idea_test_case] public class SomeClass<T extends java.util.List> extends Object \ No newline at end of file +// INFO: public constructor SomeClass<T : kotlin.List<kotlin.Any?>?>() defined in SomeClass
Java declaration:
[light_idea_test_case] public class SomeClass<T extends java.util.List> extends Object \ No newline at end of file diff --git a/idea/testData/editor/quickDoc/MethodFromStdLib.kt b/idea/testData/editor/quickDoc/MethodFromStdLib.kt index 7947a8099a3..05f97aa117e 100644 --- a/idea/testData/editor/quickDoc/MethodFromStdLib.kt +++ b/idea/testData/editor/quickDoc/MethodFromStdLib.kt @@ -2,4 +2,4 @@ fun test() { listOf(1, 2, 4).filter { it > 0 } } -// INFO: kotlin.inline public fun <T> kotlin.Iterable<T>.filter(predicate: (T) → kotlin.Boolean): kotlin.List<T> defined in kotlin

Returns a list containing all elements matching the given *predicate*

+// INFO: kotlin.inline public fun <T> kotlin.Iterable<T>.filter(predicate: (T) → kotlin.Boolean): kotlin.List<T> defined in kotlin

Returns a list containing all elements matching the given *predicate*