Converted Renderers to kotlin
This commit is contained in:
@@ -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<Renderers>())
|
||||
|
||||
public static final Renderer<Object> TO_STRING = new Renderer<Object>() {
|
||||
@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<Any> = 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> STRING = new Renderer<String>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull String element) {
|
||||
return element;
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<Named> NAME = new Renderer<Named>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull Named element) {
|
||||
return element.getName().asString();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<PsiElement> ELEMENT_TEXT = new Renderer<PsiElement>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull PsiElement element) {
|
||||
return element.getText();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<JetNamedDeclaration> DECLARATION_NAME = new Renderer<JetNamedDeclaration>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull JetNamedDeclaration element) {
|
||||
return element.getNameAsSafeName().asString();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<JetClassOrObject> RENDER_CLASS_OR_OBJECT = new Renderer<JetClassOrObject>() {
|
||||
@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<ClassDescriptor> RENDER_CLASS_OR_OBJECT_NAME = new Renderer<ClassDescriptor>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull ClassDescriptor classifier) {
|
||||
return RenderingPackage.renderKindWithName(classifier);
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<JetType> RENDER_TYPE = new Renderer<JetType>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull JetType type) {
|
||||
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type);
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<Variance> RENDER_POSITION_VARIANCE = new Renderer<Variance>() {
|
||||
@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<Collection<? extends ResolvedCall<?>>> AMBIGUOUS_CALLS =
|
||||
new Renderer<Collection<? extends ResolvedCall<?>>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull Collection<? extends ResolvedCall<?>> 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 <T> Renderer<Collection<? extends T>> commaSeparated(final Renderer<T> itemRenderer) {
|
||||
return new Renderer<Collection<? extends T>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull Collection<? extends T> object) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (Iterator<? extends T> 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<InferenceErrorData> TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER =
|
||||
new Renderer<InferenceErrorData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull InferenceErrorData inferenceErrorData) {
|
||||
return renderConflictingSubstitutionsInferenceError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
|
||||
public val STRING: Renderer<String> = Renderer { it }
|
||||
|
||||
public val NAME: Renderer<Named> = Renderer { it.getName().asString() }
|
||||
|
||||
public val ELEMENT_TEXT: Renderer<PsiElement> = Renderer { it.getText() }
|
||||
|
||||
public val DECLARATION_NAME: Renderer<JetNamedDeclaration> = Renderer { it.getNameAsSafeName().asString() }
|
||||
|
||||
public val RENDER_CLASS_OR_OBJECT: Renderer<JetClassOrObject> = 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<ClassDescriptor> = Renderer { it.renderKindWithName() }
|
||||
|
||||
public val RENDER_TYPE: Renderer<JetType> = Renderer { DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it) }
|
||||
|
||||
public val RENDER_POSITION_VARIANCE: Renderer<Variance> = Renderer {
|
||||
(variance: Variance) ->
|
||||
when (variance) {
|
||||
Variance.INVARIANT -> "invariant"
|
||||
Variance.IN_VARIANCE -> "in"
|
||||
Variance.OUT_VARIANCE -> "out"
|
||||
}
|
||||
}
|
||||
|
||||
public val AMBIGUOUS_CALLS: Renderer<Collection<ResolvedCall<*>>> = Renderer {
|
||||
(argument: Collection<ResolvedCall<*>>) ->
|
||||
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 <T> commaSeparated(itemRenderer: Renderer<T>): Renderer<Collection<T>> = 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<InferenceErrorData> TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER =
|
||||
new Renderer<InferenceErrorData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull InferenceErrorData inferenceErrorData) {
|
||||
return renderTypeConstructorMismatchError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
|
||||
}
|
||||
};
|
||||
public val TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||
renderConflictingSubstitutionsInferenceError(it, TabledDescriptorRenderer.create()).toString()
|
||||
}
|
||||
|
||||
public static final Renderer<InferenceErrorData> TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER =
|
||||
new Renderer<InferenceErrorData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull InferenceErrorData inferenceErrorData) {
|
||||
return renderNoInformationForParameterError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
|
||||
}
|
||||
};
|
||||
public val TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||
renderTypeConstructorMismatchError(it, TabledDescriptorRenderer.create()).toString()
|
||||
}
|
||||
|
||||
public static final Renderer<InferenceErrorData> TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER =
|
||||
new Renderer<InferenceErrorData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull InferenceErrorData inferenceErrorData) {
|
||||
return renderUpperBoundViolatedInferenceError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
|
||||
}
|
||||
};
|
||||
public val TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER: Renderer<InferenceErrorData> = Renderer {
|
||||
renderNoInformationForParameterError(it, TabledDescriptorRenderer.create()).toString()
|
||||
}
|
||||
|
||||
public static final Renderer<InferenceErrorData> TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER =
|
||||
new Renderer<InferenceErrorData>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull InferenceErrorData inferenceErrorData) {
|
||||
return renderCannotCaptureTypeParameterError(inferenceErrorData, TabledDescriptorRenderer.create()).toString();
|
||||
}
|
||||
};
|
||||
public val TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER: Renderer<InferenceErrorData> = 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<InferenceErrorData> = Renderer {
|
||||
renderCannotCaptureTypeParameterError(it, TabledDescriptorRenderer.create()).toString()
|
||||
}
|
||||
|
||||
Collection<CallableDescriptor> substitutedDescriptors = Lists.newArrayList();
|
||||
Collection<TypeSubstitutor> 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<CallableDescriptor>()
|
||||
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<ConstraintPosition> errorPositions = Sets.newHashSet();
|
||||
List<JetType> 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<ConstraintPosition>()
|
||||
val parameterTypes = Lists.newArrayList<JetType>()
|
||||
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<ConstraintPosition> isErrorPosition = new Predicate<ConstraintPosition>() {
|
||||
@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<ConstraintPosition> isErrorPosition = new Predicate<ConstraintPosition>() {
|
||||
@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<JetType> 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<ConstraintError> 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<Collection<ClassDescriptor>> CLASSES_OR_SEPARATED = new Renderer<Collection<ClassDescriptor>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull Collection<ClassDescriptor> 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<Collection<ClassDescriptor>> = 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<Collection<JetType>> RENDER_COLLECTION_OF_TYPES = new Renderer<Collection<JetType>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull Collection<JetType> types) {
|
||||
return StringUtil.join(types, new Function<JetType, String>() {
|
||||
@Override
|
||||
public String fun(JetType type) {
|
||||
return RENDER_TYPE.render(type);
|
||||
}
|
||||
}, ", ");
|
||||
}
|
||||
};
|
||||
|
||||
public static final Renderer<ConstraintSystem> RENDER_CONSTRAINT_SYSTEM = new Renderer<ConstraintSystem>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull ConstraintSystem constraintSystem) {
|
||||
Set<TypeParameterDescriptor> typeVariables = constraintSystem.getTypeVariables();
|
||||
Set<TypeBounds> typeBounds = Sets.newLinkedHashSet();
|
||||
for (TypeParameterDescriptor variable : typeVariables) {
|
||||
typeBounds.add(constraintSystem.getTypeBounds(variable));
|
||||
}
|
||||
Function<TypeBounds, String> 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<TypeBounds> RENDER_TYPE_BOUNDS = new Renderer<TypeBounds>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String render(@NotNull TypeBounds typeBounds) {
|
||||
Function<TypeBoundsImpl.Bound, String> renderBound = new Function<TypeBoundsImpl.Bound, String>() {
|
||||
@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 <T> Function<T, String> rendererToFunction(final @NotNull Renderer<T> renderer) {
|
||||
return new Function<T, String>() {
|
||||
@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<Collection<JetType>> = Renderer {
|
||||
types -> StringUtil.join(types, { RENDER_TYPE.render(it) }, ", ")
|
||||
}
|
||||
|
||||
public val RENDER_CONSTRAINT_SYSTEM: Renderer<ConstraintSystem> = Renderer {
|
||||
(constraintSystem) ->
|
||||
val typeVariables = constraintSystem.getTypeVariables()
|
||||
val typeBounds = Sets.newLinkedHashSet<TypeBounds>()
|
||||
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<TypeBounds> = 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<JetType, String>() {
|
||||
@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()
|
||||
}
|
||||
Reference in New Issue
Block a user