diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index 1af15b9edf1..8f2f74b2870 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -14,535 +14,378 @@ * limitations under the License. */ -package org.jetbrains.kotlin.diagnostics.rendering; +package org.jetbrains.kotlin.diagnostics.rendering -import com.google.common.base.Predicate; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.util.Function; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.KotlinBuiltIns; -import org.jetbrains.kotlin.descriptors.*; -import org.jetbrains.kotlin.name.Name; -import org.jetbrains.kotlin.psi.JetClass; -import org.jetbrains.kotlin.psi.JetClassOrObject; -import org.jetbrains.kotlin.psi.JetNamedDeclaration; -import org.jetbrains.kotlin.renderer.DescriptorRenderer; -import org.jetbrains.kotlin.renderer.Renderer; -import org.jetbrains.kotlin.resolve.DescriptorUtils; -import org.jetbrains.kotlin.resolve.calls.inference.*; -import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition; -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; -import org.jetbrains.kotlin.types.*; -import org.jetbrains.kotlin.types.checker.JetTypeChecker; +import com.google.common.base.Predicate +import com.google.common.collect.Lists +import com.google.common.collect.Sets +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.psi.JetClass +import org.jetbrains.kotlin.psi.JetClassOrObject +import org.jetbrains.kotlin.psi.JetNamedDeclaration +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.renderer.Renderer +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.calls.inference.* +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPosition +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.checker.JetTypeChecker -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Set; +import org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.* +import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND +import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION +import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION +import kotlin.platform.platformStatic +import org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.Bound -import static org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.*; -import static org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND; -import static org.jetbrains.kotlin.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND; -import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.RECEIVER_POSITION; -import static org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind.VALUE_PARAMETER_POSITION; +public object Renderers { -public class Renderers { - private static final Logger LOG = Logger.getInstance(Renderers.class); + private val LOG = Logger.getInstance(javaClass()) - public static final Renderer TO_STRING = new Renderer() { - @NotNull - @Override - public String render(@NotNull Object element) { - if (element instanceof DeclarationDescriptor) { - LOG.warn("Diagnostic renderer TO_STRING was used to render an instance of DeclarationDescriptor.\n" + - "This is usually a bad idea, because descriptors' toString() includes some debug information, " + - "which should not be seen by the user.\nDescriptor: " + element); - } - return element.toString(); + public val TO_STRING: Renderer = Renderer { + (element) -> + if (element is DeclarationDescriptor) { + LOG.warn("Diagnostic renderer TO_STRING was used to render an instance of DeclarationDescriptor.\n" + + "This is usually a bad idea, because descriptors' toString() includes some debug information, " + + "which should not be seen by the user.\nDescriptor: " + element) } - - @Override - public String toString() { - return "TO_STRING"; - } - }; - - public static final Renderer STRING = new Renderer() { - @NotNull - @Override - public String render(@NotNull String element) { - return element; - } - }; - - public static final Renderer NAME = new Renderer() { - @NotNull - @Override - public String render(@NotNull Named element) { - return element.getName().asString(); - } - }; - - public static final Renderer ELEMENT_TEXT = new Renderer() { - @NotNull - @Override - public String render(@NotNull PsiElement element) { - return element.getText(); - } - }; - - public static final Renderer DECLARATION_NAME = new Renderer() { - @NotNull - @Override - public String render(@NotNull JetNamedDeclaration element) { - return element.getNameAsSafeName().asString(); - } - }; - - public static final Renderer RENDER_CLASS_OR_OBJECT = new Renderer() { - @NotNull - @Override - public String render(@NotNull JetClassOrObject classOrObject) { - String name = classOrObject.getName() != null ? " '" + classOrObject.getName() + "'" : ""; - if (classOrObject instanceof JetClass) { - return "Class" + name; - } - return "Object" + name; - } - }; - - public static final Renderer RENDER_CLASS_OR_OBJECT_NAME = new Renderer() { - @NotNull - @Override - public String render(@NotNull ClassDescriptor classifier) { - return RenderingPackage.renderKindWithName(classifier); - } - }; - - public static final Renderer RENDER_TYPE = new Renderer() { - @NotNull - @Override - public String render(@NotNull JetType type) { - return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type); - } - }; - - public static final Renderer RENDER_POSITION_VARIANCE = new Renderer() { - @NotNull - @Override - public String render(@NotNull Variance variance) { - switch (variance) { - case INVARIANT: return "invariant"; - case IN_VARIANCE: return "in"; - case OUT_VARIANCE: return "out"; - } - throw new IllegalArgumentException("Unknown variance: " + variance); - } - }; - - public static final Renderer>> AMBIGUOUS_CALLS = - new Renderer>>() { - @NotNull - @Override - public String render(@NotNull Collection> argument) { - StringBuilder stringBuilder = new StringBuilder("\n"); - for (ResolvedCall call : argument) { - stringBuilder.append(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(call.getResultingDescriptor())).append("\n"); - } - return stringBuilder.toString(); - } - }; - - public static Renderer> commaSeparated(final Renderer itemRenderer) { - return new Renderer>() { - @NotNull - @Override - public String render(@NotNull Collection object) { - StringBuilder result = new StringBuilder(); - for (Iterator iterator = object.iterator(); iterator.hasNext(); ) { - T next = iterator.next(); - result.append(itemRenderer.render(next)); - if (iterator.hasNext()) { - result.append(", "); - } - } - return result.toString(); - } - }; + element.toString() } - public static final Renderer TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER = - new Renderer() { - @NotNull - @Override - public String render(@NotNull InferenceErrorData inferenceErrorData) { - return renderConflictingSubstitutionsInferenceError(inferenceErrorData, TabledDescriptorRenderer.create()).toString(); + public val STRING: Renderer = Renderer { it } + + public val NAME: Renderer = Renderer { it.getName().asString() } + + public val ELEMENT_TEXT: Renderer = Renderer { it.getText() } + + public val DECLARATION_NAME: Renderer = Renderer { it.getNameAsSafeName().asString() } + + public val RENDER_CLASS_OR_OBJECT: Renderer = Renderer { + (classOrObject: JetClassOrObject) -> + val name = if (classOrObject.getName() != null) " '" + classOrObject.getName() + "'" else "" + if (classOrObject is JetClass) "Class" + name else "Object" + name + } + + public val RENDER_CLASS_OR_OBJECT_NAME: Renderer = Renderer { it.renderKindWithName() } + + public val RENDER_TYPE: Renderer = Renderer { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) } + + public val RENDER_POSITION_VARIANCE: Renderer = Renderer { + (variance: Variance) -> + when (variance) { + Variance.INVARIANT -> "invariant" + Variance.IN_VARIANCE -> "in" + Variance.OUT_VARIANCE -> "out" + } + } + + public val AMBIGUOUS_CALLS: Renderer>> = Renderer { + (argument: Collection>) -> + val stringBuilder = StringBuilder("\n") + for (call in argument) { + stringBuilder.append(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(call.getResultingDescriptor())).append("\n") + } + stringBuilder.toString() + } + + platformStatic + public fun commaSeparated(itemRenderer: Renderer): Renderer> = Renderer { + collection -> + StringBuilder { + val iterator = collection.iterator() + while (iterator.hasNext()) { + val next = iterator.next() + append(itemRenderer.render(next)) + if (iterator.hasNext()) { + append(", ") } - }; + } + }.toString() + } - public static final Renderer TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER = - new Renderer() { - @NotNull - @Override - public String render(@NotNull InferenceErrorData inferenceErrorData) { - return renderTypeConstructorMismatchError(inferenceErrorData, TabledDescriptorRenderer.create()).toString(); - } - }; + public val TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER: Renderer = Renderer { + renderConflictingSubstitutionsInferenceError(it, TabledDescriptorRenderer.create()).toString() + } - public static final Renderer TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER = - new Renderer() { - @NotNull - @Override - public String render(@NotNull InferenceErrorData inferenceErrorData) { - return renderNoInformationForParameterError(inferenceErrorData, TabledDescriptorRenderer.create()).toString(); - } - }; + public val TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER: Renderer = Renderer { + renderTypeConstructorMismatchError(it, TabledDescriptorRenderer.create()).toString() + } - public static final Renderer TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER = - new Renderer() { - @NotNull - @Override - public String render(@NotNull InferenceErrorData inferenceErrorData) { - return renderUpperBoundViolatedInferenceError(inferenceErrorData, TabledDescriptorRenderer.create()).toString(); - } - }; + public val TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER: Renderer = Renderer { + renderNoInformationForParameterError(it, TabledDescriptorRenderer.create()).toString() + } - public static final Renderer TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER = - new Renderer() { - @NotNull - @Override - public String render(@NotNull InferenceErrorData inferenceErrorData) { - return renderCannotCaptureTypeParameterError(inferenceErrorData, TabledDescriptorRenderer.create()).toString(); - } - }; + public val TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER: Renderer = Renderer { + renderUpperBoundViolatedInferenceError(it, TabledDescriptorRenderer.create()).toString() + } - public static TabledDescriptorRenderer renderConflictingSubstitutionsInferenceError(InferenceErrorData inferenceErrorData, - TabledDescriptorRenderer result) { - LOG.assertTrue(inferenceErrorData.constraintSystem.getStatus().hasConflictingConstraints(), renderDebugMessage( - "Conflicting substitutions inference error renderer is applied for incorrect status", inferenceErrorData)); + public val TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER: Renderer = Renderer { + renderCannotCaptureTypeParameterError(it, TabledDescriptorRenderer.create()).toString() + } - Collection substitutedDescriptors = Lists.newArrayList(); - Collection substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters( - inferenceErrorData.constraintSystem); - for (TypeSubstitutor substitutor : substitutors) { - CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor); - substitutedDescriptors.add(substitutedDescriptor); + platformStatic + public fun renderConflictingSubstitutionsInferenceError( + inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer + ): TabledDescriptorRenderer { + LOG.assertTrue(inferenceErrorData.constraintSystem.getStatus().hasConflictingConstraints(), + renderDebugMessage("Conflicting substitutions inference error renderer is applied for incorrect status", inferenceErrorData)) + + val substitutedDescriptors = Lists.newArrayList() + val substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters(inferenceErrorData.constraintSystem) + for (substitutor in substitutors) { + val substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor) + substitutedDescriptors.add(substitutedDescriptor) } - TypeParameterDescriptor firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintSystem); + val firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintSystem) if (firstConflictingParameter == null) { - LOG.error(renderDebugMessage("There is no conflicting parameter for 'conflicting constraints' error.", inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("There is no conflicting parameter for 'conflicting constraints' error.", inferenceErrorData)) + return result } result.text(newText() .normal("Cannot infer type parameter ") .strong(firstConflictingParameter.getName()) - .normal(" in ")); - //String type = strong(firstConflictingParameter.getName()); - TableRenderer table = newTable(); - result.table(table); - table.descriptor(inferenceErrorData.descriptor) - .text("None of the following substitutions"); + .normal(" in ")) + val table = newTable() + result.table(table) + table.descriptor(inferenceErrorData.descriptor).text("None of the following substitutions") - for (CallableDescriptor substitutedDescriptor : substitutedDescriptors) { - JetType receiverType = DescriptorUtils.getReceiverParameterType(substitutedDescriptor.getExtensionReceiverParameter()); + for (substitutedDescriptor in substitutedDescriptors) { + val receiverType = DescriptorUtils.getReceiverParameterType(substitutedDescriptor.getExtensionReceiverParameter()) - final Collection errorPositions = Sets.newHashSet(); - List parameterTypes = Lists.newArrayList(); - for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) { - parameterTypes.add(valueParameterDescriptor.getType()); - if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue; - JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()); + val errorPositions = Sets.newHashSet() + val parameterTypes = Lists.newArrayList() + for (valueParameterDescriptor in substitutedDescriptor.getValueParameters()) { + parameterTypes.add(valueParameterDescriptor.getType()) + if (valueParameterDescriptor.getIndex() >= inferenceErrorData.valueArgumentsTypes.size()) continue + val actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()) if (!JetTypeChecker.DEFAULT.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { - errorPositions.add(VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex())); + errorPositions.add(VALUE_PARAMETER_POSITION.position(valueParameterDescriptor.getIndex())) } } - if (receiverType != null && inferenceErrorData.receiverArgumentType != null && - !JetTypeChecker.DEFAULT.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { - errorPositions.add(RECEIVER_POSITION.position()); + if (receiverType != null && inferenceErrorData.receiverArgumentType != null + && !JetTypeChecker.DEFAULT.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { + errorPositions.add(RECEIVER_POSITION.position()) } - Predicate isErrorPosition = new Predicate() { - @Override - public boolean apply(@Nullable ConstraintPosition constraintPosition) { - return errorPositions.contains(constraintPosition); - } - }; - table.functionArgumentTypeList(receiverType, parameterTypes, isErrorPosition); + table.functionArgumentTypeList(receiverType, parameterTypes, { errorPositions.contains(it) }) } - table.text("can be applied to") - .functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes); + table.text("can be applied to").functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes) - return result; + return result } - @NotNull - public static TabledDescriptorRenderer renderTypeConstructorMismatchError( - final @NotNull InferenceErrorData inferenceErrorData, - @NotNull TabledDescriptorRenderer renderer - ) { - Predicate isErrorPosition = new Predicate() { - @Override - public boolean apply(ConstraintPosition constraintPosition) { - return inferenceErrorData.constraintSystem.getStatus().hasTypeConstructorMismatchAt(constraintPosition); - } - }; - return renderer.table(TabledDescriptorRenderer.newTable() - .descriptor(inferenceErrorData.descriptor) - .text("cannot be applied to") - .functionArgumentTypeList( - inferenceErrorData.receiverArgumentType, - inferenceErrorData.valueArgumentsTypes, - isErrorPosition)); + platformStatic + public fun renderTypeConstructorMismatchError( + inferenceErrorData: InferenceErrorData, renderer: TabledDescriptorRenderer + ): TabledDescriptorRenderer { + val isErrorPosition = Predicate { + (constraintPosition: ConstraintPosition) -> + inferenceErrorData.constraintSystem.getStatus().hasTypeConstructorMismatchAt(constraintPosition) + } + return renderer.table( + TabledDescriptorRenderer + .newTable() + .descriptor(inferenceErrorData.descriptor) + .text("cannot be applied to") + .functionArgumentTypeList(inferenceErrorData.receiverArgumentType, + inferenceErrorData.valueArgumentsTypes, + isErrorPosition)) } - @NotNull - public static TabledDescriptorRenderer renderNoInformationForParameterError( - @NotNull InferenceErrorData inferenceErrorData, - @NotNull TabledDescriptorRenderer result - ) { - TypeParameterDescriptor firstUnknownParameter = null; - for (TypeParameterDescriptor typeParameter : inferenceErrorData.constraintSystem.getTypeVariables()) { + + platformStatic + public fun renderNoInformationForParameterError( + inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer + ): TabledDescriptorRenderer { + var firstUnknownParameter: TypeParameterDescriptor? = null + for (typeParameter in inferenceErrorData.constraintSystem.getTypeVariables()) { if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).isEmpty()) { - firstUnknownParameter = typeParameter; - break; + firstUnknownParameter = typeParameter + break } } if (firstUnknownParameter == null) { - LOG.error(renderDebugMessage("There is no unknown parameter for 'no information for parameter error'.", inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("There is no unknown parameter for 'no information for parameter error'.", inferenceErrorData)) + return result } return result .text(newText().normal("Not enough information to infer parameter ") - .strong(firstUnknownParameter.getName()) + .strong(firstUnknownParameter!!.getName()) .normal(" in ")) .table(newTable() .descriptor(inferenceErrorData.descriptor) - .text("Please specify it explicitly.")); + .text("Please specify it explicitly.")) } - @NotNull - public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(InferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) { - TypeParameterDescriptor typeParameterDescriptor = null; - ConstraintSystemImpl constraintSystem = (ConstraintSystemImpl) inferenceErrorData.constraintSystem; - ConstraintSystemStatus status = constraintSystem.getStatus(); - LOG.assertTrue(status.hasViolatedUpperBound(), renderDebugMessage( - "Upper bound violated renderer is applied for incorrect status", inferenceErrorData)); + platformStatic + public fun renderUpperBoundViolatedInferenceError( + inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer + ): TabledDescriptorRenderer { + val constraintSystem = inferenceErrorData.constraintSystem as ConstraintSystemImpl + val status = constraintSystem.getStatus() + LOG.assertTrue(status.hasViolatedUpperBound(), + renderDebugMessage("Upper bound violated renderer is applied for incorrect status", inferenceErrorData)) - ConstraintSystem systemWithoutWeakConstraints = constraintSystem.getSystemWithoutWeakConstraints(); - for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) { - if (!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, typeParameter, true)) { - typeParameterDescriptor = typeParameter; - } + val systemWithoutWeakConstraints = constraintSystem.getSystemWithoutWeakConstraints() + val typeParameterDescriptor = inferenceErrorData.descriptor.getTypeParameters().firstOrNull { + !ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, it, true) } if (typeParameterDescriptor == null && status.hasConflictingConstraints()) { - return renderConflictingSubstitutionsInferenceError(inferenceErrorData, result); + return renderConflictingSubstitutionsInferenceError(inferenceErrorData, result) } if (typeParameterDescriptor == null) { - LOG.error(renderDebugMessage("There is no type parameter with violated upper bound for 'upper bound violated' error", - inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("There is no type parameter with violated upper bound for 'upper bound violated' error", inferenceErrorData)) + return result } - JetType inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeParameterDescriptor).getValue(); + val inferredValueForTypeParameter = systemWithoutWeakConstraints.getTypeBounds(typeParameterDescriptor).getValue() if (inferredValueForTypeParameter == null) { - LOG.error(renderDebugMessage("System without weak constraints is not successful, there is no value for type parameter " + - typeParameterDescriptor.getName() + "\n: " + systemWithoutWeakConstraints, inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("System without weak constraints is not successful, there is no value for type parameter " + + typeParameterDescriptor.getName() + "\n: " + systemWithoutWeakConstraints, inferenceErrorData)) + return result } - result.text(newText().normal("Type parameter bound for ").strong(typeParameterDescriptor.getName()).normal(" in ")) - .table(newTable(). - descriptor(inferenceErrorData.descriptor)); + result.text(newText() + .normal("Type parameter bound for ") + .strong(typeParameterDescriptor.getName()) + .normal(" in ")) + .table(newTable() + .descriptor(inferenceErrorData.descriptor)) - JetType violatedUpperBound = null; - for (JetType upperBound : typeParameterDescriptor.getUpperBounds()) { - JetType upperBoundWithSubstitutedInferredTypes = - systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT); - if (upperBoundWithSubstitutedInferredTypes != null && - !JetTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) { - violatedUpperBound = upperBoundWithSubstitutedInferredTypes; - break; + var violatedUpperBound: JetType? = null + for (upperBound in typeParameterDescriptor.getUpperBounds()) { + val upperBoundWithSubstitutedInferredTypes = systemWithoutWeakConstraints.getResultingSubstitutor().substitute(upperBound, Variance.INVARIANT) + if (upperBoundWithSubstitutedInferredTypes != null + && !JetTypeChecker.DEFAULT.isSubtypeOf(inferredValueForTypeParameter, upperBoundWithSubstitutedInferredTypes)) { + violatedUpperBound = upperBoundWithSubstitutedInferredTypes + break } } if (violatedUpperBound == null) { - LOG.error(renderDebugMessage("Type parameter (chosen as violating its upper bound)" + typeParameterDescriptor.getName() + - " violates no bounds after substitution", inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("Type parameter (chosen as violating its upper bound)" + + typeParameterDescriptor.getName() + " violates no bounds after substitution", inferenceErrorData)) + return result } - Renderer typeRenderer = result.getTypeRenderer(); + val typeRenderer = result.getTypeRenderer() result.text(newText() .normal(" is not satisfied: inferred type ") .error(typeRenderer.render(inferredValueForTypeParameter)) .normal(" is not a subtype of ") - .strong(typeRenderer.render(violatedUpperBound))); - return result; + .strong(typeRenderer.render(violatedUpperBound))) + return result } - @NotNull - public static TabledDescriptorRenderer renderCannotCaptureTypeParameterError( - @NotNull InferenceErrorData inferenceErrorData, - @NotNull TabledDescriptorRenderer result - ) { - ConstraintSystemImpl constraintSystem = (ConstraintSystemImpl) inferenceErrorData.constraintSystem; - List errors = constraintSystem.getConstraintErrors(); - TypeParameterDescriptor typeParameterWithCapturedConstraint = null; - for (ConstraintError error : errors) { - if (error instanceof CannotCapture) { - typeParameterWithCapturedConstraint = ((CannotCapture) error).getTypeVariable(); - } - } + platformStatic + public fun renderCannotCaptureTypeParameterError( + inferenceErrorData: InferenceErrorData, result: TabledDescriptorRenderer + ): TabledDescriptorRenderer { + val constraintSystem = inferenceErrorData.constraintSystem as ConstraintSystemImpl + val errors = constraintSystem.constraintErrors + val typeParameterWithCapturedConstraint = (errors.firstOrNull { it is CannotCapture } as? CannotCapture)?.typeVariable if (typeParameterWithCapturedConstraint == null) { - LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("An error 'cannot capture type parameter' is not found in errors", inferenceErrorData)) + return result } - CapturedTypeConstructor capturedTypeConstructor = null; - TypeBounds typeBounds = constraintSystem.getTypeBounds(typeParameterWithCapturedConstraint); - for (TypeBounds.Bound bound : typeBounds.getBounds()) { - TypeConstructor constructor = bound.getConstrainingType().getConstructor(); - if (constructor instanceof CapturedTypeConstructor) { - capturedTypeConstructor = (CapturedTypeConstructor) constructor; - } - } + val typeBounds = constraintSystem.getTypeBounds(typeParameterWithCapturedConstraint) + val boundWithCapturedType = typeBounds.bounds.firstOrNull { it.constrainingType.isCaptured() } + val capturedTypeConstructor = boundWithCapturedType?.constrainingType?.getConstructor() as? CapturedTypeConstructor if (capturedTypeConstructor == null) { - LOG.error(renderDebugMessage("There is no captured type in bounds, but there is an error 'cannot capture type parameter'", - inferenceErrorData)); - return result; + LOG.error(renderDebugMessage("There is no captured type in bounds, but there is an error 'cannot capture type parameter'", inferenceErrorData)) + return result } - String explanation; - JetType upperBound = typeParameterWithCapturedConstraint.getUpperBoundsAsType(); - if (!KotlinBuiltIns.isNullableAny(upperBound) - && capturedTypeConstructor.getTypeProjection().getProjectionKind() == Variance.IN_VARIANCE) { + val explanation: String + val upperBound = typeParameterWithCapturedConstraint.getUpperBoundsAsType() + if (!KotlinBuiltIns.isNullableAny(upperBound) && capturedTypeConstructor.typeProjection.getProjectionKind() == Variance.IN_VARIANCE) { explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" + - " that cannot be satisfied capturing 'in' projection"; + " that cannot be satisfied capturing 'in' projection" } else { - explanation = "Only top-level type projections can be captured"; + explanation = "Only top-level type projections can be captured" } result.text(newText().normal("'" + typeParameterWithCapturedConstraint.getName() + "'" + " cannot capture " + - "'" + capturedTypeConstructor.getTypeProjection() + "'. " + - explanation)); - return result; + "'" + capturedTypeConstructor.typeProjection + "'. " + + explanation)) + return result } - public static final Renderer> CLASSES_OR_SEPARATED = new Renderer>() { - @NotNull - @Override - public String render(@NotNull Collection descriptors) { - StringBuilder sb = new StringBuilder(); - int index = 0; - for (ClassDescriptor descriptor : descriptors) { - sb.append(DescriptorUtils.getFqName(descriptor).asString()); - index++; + public val CLASSES_OR_SEPARATED: Renderer> = Renderer { + descriptors -> + StringBuilder { + var index = 0 + for (descriptor in descriptors) { + append(DescriptorUtils.getFqName(descriptor).asString()) + index++ if (index <= descriptors.size() - 2) { - sb.append(", "); + append(", ") } else if (index == descriptors.size() - 1) { - sb.append(" or "); + append(" or ") } } - return sb.toString(); - } - }; - - public static final Renderer> RENDER_COLLECTION_OF_TYPES = new Renderer>() { - @NotNull - @Override - public String render(@NotNull Collection types) { - return StringUtil.join(types, new Function() { - @Override - public String fun(JetType type) { - return RENDER_TYPE.render(type); - } - }, ", "); - } - }; - - public static final Renderer RENDER_CONSTRAINT_SYSTEM = new Renderer() { - @NotNull - @Override - public String render(@NotNull ConstraintSystem constraintSystem) { - Set typeVariables = constraintSystem.getTypeVariables(); - Set typeBounds = Sets.newLinkedHashSet(); - for (TypeParameterDescriptor variable : typeVariables) { - typeBounds.add(constraintSystem.getTypeBounds(variable)); - } - Function renderTypeBounds = rendererToFunction(RENDER_TYPE_BOUNDS); - return "type parameter bounds:\n" + StringUtil.join(typeBounds, renderTypeBounds, "\n") + "\n" + - "status:\n" + ConstraintsUtil.getDebugMessageForStatus(constraintSystem.getStatus()); - } - }; - - public static final Renderer RENDER_TYPE_BOUNDS = new Renderer() { - @NotNull - @Override - public String render(@NotNull TypeBounds typeBounds) { - Function renderBound = new Function() { - @Override - public String fun(TypeBoundsImpl.Bound bound) { - String arrow = bound.getKind() == LOWER_BOUND ? ">: " : bound.getKind() == UPPER_BOUND ? "<: " : ":= "; - return arrow + RENDER_TYPE.render(bound.getConstrainingType()) + '(' + bound.getPosition() + ')'; - } - }; - Name typeVariableName = typeBounds.getTypeVariable().getName(); - if (typeBounds.isEmpty()) { - return typeVariableName.asString(); - } - return typeVariableName + " " + StringUtil.join(typeBounds.getBounds(), renderBound, ", "); - } - }; - - @NotNull - public static Function rendererToFunction(final @NotNull Renderer renderer) { - return new Function() { - @Override - public String fun(T t) { - return renderer.render(t); - } - }; + }.toString() } - @NotNull - private static String renderDebugMessage(String message, InferenceErrorData inferenceErrorData) { - StringBuilder result = new StringBuilder(); - result.append(message); - result.append("\nConstraint system: \n"); - result.append(RENDER_CONSTRAINT_SYSTEM.render(inferenceErrorData.constraintSystem)); - result.append("\nDescriptor:\n"); - result.append(inferenceErrorData.descriptor); - result.append("\nExpected type:\n"); + public val RENDER_COLLECTION_OF_TYPES: Renderer> = Renderer { + types -> StringUtil.join(types, { RENDER_TYPE.render(it) }, ", ") + } + + public val RENDER_CONSTRAINT_SYSTEM: Renderer = Renderer { + (constraintSystem) -> + val typeVariables = constraintSystem.getTypeVariables() + val typeBounds = Sets.newLinkedHashSet() + for (variable in typeVariables) { + typeBounds.add(constraintSystem.getTypeBounds(variable)) + } + "type parameter bounds:\n" + StringUtil.join(typeBounds, { RENDER_TYPE_BOUNDS.render(it) }, "\n") + "\n" + "status:\n" + + ConstraintsUtil.getDebugMessageForStatus(constraintSystem.getStatus()) + } + + public val RENDER_TYPE_BOUNDS: Renderer = Renderer { + typeBounds -> + val renderBound = { (bound: Bound) -> + val arrow = if (bound.kind == LOWER_BOUND) ">: " else if (bound.kind == UPPER_BOUND) "<: " else ":= " + arrow + RENDER_TYPE.render(bound.constrainingType) + '(' + bound.position + ')' + } + val typeVariableName = typeBounds.typeVariable.getName() + if (typeBounds.isEmpty()) { + typeVariableName.asString() + } + else + "$typeVariableName ${StringUtil.join(typeBounds.bounds, renderBound, ", ")}" + } + + private fun renderDebugMessage(message: String, inferenceErrorData: InferenceErrorData) = StringBuilder { + append(message) + append("\nConstraint system: \n") + append(RENDER_CONSTRAINT_SYSTEM.render(inferenceErrorData.constraintSystem)) + append("\nDescriptor:\n") + append(inferenceErrorData.descriptor) + append("\nExpected type:\n") if (TypeUtils.noExpectedType(inferenceErrorData.expectedType)) { - result.append(inferenceErrorData.expectedType); + append(inferenceErrorData.expectedType) } else { - result.append(RENDER_TYPE.render(inferenceErrorData.expectedType)); + append(RENDER_TYPE.render(inferenceErrorData.expectedType)) } - result.append("\nArgument types:\n"); + append("\nArgument types:\n") if (inferenceErrorData.receiverArgumentType != null) { - result.append(RENDER_TYPE.render(inferenceErrorData.receiverArgumentType)).append("."); + append(RENDER_TYPE.render(inferenceErrorData.receiverArgumentType)).append(".") } - result.append("(").append(StringUtil.join(inferenceErrorData.valueArgumentsTypes, new Function() { - @Override - public String fun(JetType type) { - return RENDER_TYPE.render(type); - } - }, ", ")).append(")"); - return result.toString(); - } - - private Renderers() { - } -} + append("(").append(StringUtil.join(inferenceErrorData.valueArgumentsTypes, { RENDER_TYPE.render(it) }, ", ")).append(")") + }.toString() +} \ No newline at end of file