Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.jet.lang.diagnostics.rendering.Renderers Maven / Gradle / Ivy
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.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.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.inference.*;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.renderer.Renderer;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.*;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND;
import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.UPPER_BOUND;
public class Renderers {
private static final Logger LOG = Logger.getInstance(Renderers.class);
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();
}
@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_TYPE = new Renderer() {
@NotNull
@Override
public String render(@NotNull JetType type) {
return DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(type);
}
};
public static final Renderer>> AMBIGUOUS_CALLS =
new Renderer>>() {
@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 Renderer> commaSeparated(final Renderer itemRenderer) {
return new Renderer>() {
@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();
}
};
}
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 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 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 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 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));
Collection substitutedDescriptors = Lists.newArrayList();
Collection substitutors = ConstraintsUtil.getSubstitutorsForConflictingParameters(
inferenceErrorData.constraintSystem);
for (TypeSubstitutor substitutor : substitutors) {
CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor);
substitutedDescriptors.add(substitutedDescriptor);
}
TypeParameterDescriptor firstConflictingParameter = ConstraintsUtil.getFirstConflictingParameter(inferenceErrorData.constraintSystem);
if (firstConflictingParameter == null) {
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");
for (CallableDescriptor substitutedDescriptor : substitutedDescriptors) {
JetType receiverType = DescriptorUtils.getReceiverParameterType(substitutedDescriptor.getReceiverParameter());
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());
if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) {
errorPositions.add(ConstraintPosition.getValueParameterPosition(valueParameterDescriptor.getIndex()));
}
}
if (receiverType != null && inferenceErrorData.receiverArgumentType != null &&
!JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) {
errorPositions.add(ConstraintPosition.RECEIVER_POSITION);
}
Predicate isErrorPosition = new Predicate() {
@Override
public boolean apply(@Nullable ConstraintPosition constraintPosition) {
return errorPositions.contains(constraintPosition);
}
};
table.functionArgumentTypeList(receiverType, parameterTypes, isErrorPosition);
}
table.text("can be applied to")
.functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes);
return result;
}
public static TabledDescriptorRenderer renderTypeConstructorMismatchError(final InferenceErrorData inferenceErrorData,
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));
}
public static TabledDescriptorRenderer renderNoInformationForParameterError(InferenceErrorData inferenceErrorData,
TabledDescriptorRenderer result) {
TypeParameterDescriptor firstUnknownParameter = null;
for (TypeParameterDescriptor typeParameter : inferenceErrorData.constraintSystem.getTypeVariables()) {
if (inferenceErrorData.constraintSystem.getTypeBounds(typeParameter).isEmpty()) {
firstUnknownParameter = typeParameter;
break;
}
}
if (firstUnknownParameter == null) {
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())
.normal(" in "))
.table(newTable()
.descriptor(inferenceErrorData.descriptor)
.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));
ConstraintSystem systemWithoutWeakConstraints = constraintSystem.getSystemWithoutWeakConstraints();
for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) {
if (!ConstraintsUtil.checkUpperBoundIsSatisfied(systemWithoutWeakConstraints, typeParameter, true)) {
typeParameterDescriptor = typeParameter;
}
}
if (typeParameterDescriptor == null && status.hasConflictingConstraints()) {
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;
}
JetType 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;
}
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.INSTANCE.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;
}
Renderer 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;
}
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++;
if (index <= descriptors.size() - 2) {
sb.append(", ");
}
else if (index == descriptors.size() - 1) {
sb.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.kind == LOWER_BOUND ? ">: " : bound.kind == UPPER_BOUND ? "<: " : ":= ";
return arrow + RENDER_TYPE.render(bound.type) + '(' + bound.position + ')';
}
};
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);
}
};
}
@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");
if (TypeUtils.noExpectedType(inferenceErrorData.expectedType)) {
result.append(inferenceErrorData.expectedType);
}
else {
result.append(RENDER_TYPE.render(inferenceErrorData.expectedType));
}
result.append("\nArgument types:\n");
if (inferenceErrorData.receiverArgumentType != null) {
result.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() {
}
}