diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index 6161de94b5c..c15fd9dd371 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -395,11 +395,10 @@ public class DefaultErrorMessages { MAP.put(CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, "Cannot create an instance of an abstract class"); - //todo - MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", TO_STRING); - MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", TO_STRING); - MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", TO_STRING); - MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "Type parameter bound is not satisfied: {0} is not a subtype of {1}", TO_STRING); + MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER); + MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); + MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER); + MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(WRONG_NUMBER_OF_TYPE_ARGUMENTS, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type argument} expected", null); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index d7ea01c0d99..5b562284d21 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -16,18 +16,32 @@ package org.jetbrains.jet.lang.diagnostics.rendering; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.Named; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.JetClass; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; +import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData; +import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.resolve.DescriptorRenderer; +import static org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.*; + import java.util.Collection; import java.util.Iterator; +import java.util.List; +import java.util.Map; /** * @author svtk @@ -117,6 +131,151 @@ public class Renderers { }; } + 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) { + assert inferenceErrorData.constraintSystem.hasConflictingParameters(); + + Collection substitutedDescriptors = Lists.newArrayList(); + Collection substitutors = inferenceErrorData.constraintSystem.getSubstitutors(); + for (TypeSubstitutor substitutor : substitutors) { + CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor); + substitutedDescriptors.add(substitutedDescriptor); + } + + TypeParameterDescriptor firstConflictingParameter = inferenceErrorData.constraintSystem.getFirstConflictingParameter(); + assert firstConflictingParameter != null; + + 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 = substitutedDescriptor.getReceiverParameter().exists() ? substitutedDescriptor.getReceiverParameter().getType() : null; + + Collection errorPositions = Sets.newHashSet(); + List valueArgumentTypes = Lists.newArrayList(); + for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) { + valueArgumentTypes.add(valueParameterDescriptor.getType()); + JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()); + if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { + errorPositions.add(ConstraintPosition.valueParameterPosition(valueParameterDescriptor.getIndex())); + } + } + + if (receiverType != null && inferenceErrorData.receiverArgumentType != null && + !JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { + errorPositions.add(ConstraintPosition.RECEIVER_POSITION); + } + + table.functionArgumentTypeList(receiverType, valueArgumentTypes, errorPositions); + } + + table.text("can be applied to") + .functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes); + + return result; + } + + public static TabledDescriptorRenderer renderTypeConstructorMismatchError(InferenceErrorData inferenceErrorData, + TabledDescriptorRenderer renderer) { + return renderer.table(TabledDescriptorRenderer.newTable() + .descriptor(inferenceErrorData.descriptor) + .text("cannot be applied to") + .functionArgumentTypeList( + inferenceErrorData.receiverArgumentType, + inferenceErrorData.valueArgumentsTypes, + inferenceErrorData.constraintSystem + .getErrorConstraintPositions())); + } + + public static TabledDescriptorRenderer renderNoInformationForParameterError(InferenceErrorData inferenceErrorData, + TabledDescriptorRenderer renderer) { + TypeParameterDescriptor firstUnknownParameter = null; + for (Map.Entry entry : inferenceErrorData.constraintSystem.getTypeBoundsMap().entrySet()) { + if (entry.getValue().isEmpty()) { + firstUnknownParameter = entry.getKey(); + break; + } + } + assert firstUnknownParameter != null; + + return renderer + .text(TabledDescriptorRenderer.newText().normal("Not enough information to infer parameter ") + .strong(firstUnknownParameter.getName()) + .normal(" in ")) + .table(TabledDescriptorRenderer.newTable() + .descriptor(inferenceErrorData.descriptor) + .text("Please specify it explicitly.")); + } + + public static TabledDescriptorRenderer renderUpperBoundViolatedInferenceError(InferenceErrorData inferenceErrorData, TabledDescriptorRenderer result) { + TypeParameterDescriptor typeParameterDescriptor = null; + for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) { + if (!inferenceErrorData.constraintSystem.checkUpperBound(typeParameter)) { + typeParameterDescriptor = typeParameter; + break; + } + } + assert typeParameterDescriptor != null; + + result.text(newText().normal("Type parameter bound for ").strong(typeParameterDescriptor.getName()).normal(" in ")) + .table(newTable(). + descriptor(inferenceErrorData.descriptor)); + + JetType type = inferenceErrorData.constraintSystem.getValue(typeParameterDescriptor); + JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType(); + JetType substitute = inferenceErrorData.constraintSystem.getSubstitutor().substitute(upperBound, Variance.INVARIANT); + + result.text(newText() + .normal(" is not satisfied: inferred type ") + .error(type) + .normal(" is not a subtype of ") + .strong(substitute)); + return result; + } + private Renderers() { } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java new file mode 100644 index 00000000000..9e35a2d5884 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java @@ -0,0 +1,249 @@ +/* + * Copyright 2010-2012 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.collect.Lists; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.resolve.DescriptorRenderer; + +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.*; +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TextRenderer.*; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +/** + * @author svtk + */ +public class TabledDescriptorRenderer { + public interface TableOrTextRenderer {} + + public static class TableRenderer implements TableOrTextRenderer{ + public interface TableRow { + } + + public static class DescriptorRow implements TableRow { + public final CallableDescriptor descriptor; + + public DescriptorRow(CallableDescriptor descriptor) { + this.descriptor = descriptor; + } + } + + public static class FunctionArgumentsRow implements TableRow { + public final JetType receiverType; + public final List argumentTypes; + public final Collection errorPositions; + + public FunctionArgumentsRow(JetType receiverType, List argumentTypes, Collection errorPositions) { + this.receiverType = receiverType; + this.argumentTypes = argumentTypes; + this.errorPositions = errorPositions; + } + } + + + public final List rows = Lists.newArrayList(); + + public TableRenderer descriptor(CallableDescriptor descriptor) { + rows.add(new DescriptorRow(descriptor)); + return this; + } + + public TableRenderer functionArgumentTypeList(@Nullable JetType receiverType, @NotNull List argumentTypes) { + return functionArgumentTypeList(receiverType, argumentTypes, Collections.emptyList()); + } + + public TableRenderer functionArgumentTypeList(@Nullable JetType receiverType, + @NotNull List argumentTypes, + Collection errorPositions) { + rows.add(new FunctionArgumentsRow(receiverType, argumentTypes, errorPositions)); + return this; + } + + public TableRenderer text(@NotNull String text) { + rows.add(newText().normal(text)); + return this; + } + + public TableRenderer text(@NotNull TextRenderer textRenderer) { + rows.add(textRenderer); + return this; + } + } + + public static class TextRenderer implements TableOrTextRenderer, TableRow { + public static enum TextElementType {STRONG, ERROR, DEFAULT} + public static class TextElement { + + public TextElementType type; + public String text; + + public TextElement(@NotNull TextElementType type, @NotNull String text) { + this.type = type; + this.text = text; + } + } + + public final List elements = Lists.newArrayList(); + + public TextRenderer normal(@NotNull Object text) { + elements.add(new TextElement(TextElementType.DEFAULT, text.toString())); + return this; + } + + public TextRenderer error(@NotNull Object text) { + elements.add(new TextElement(TextElementType.ERROR, text.toString())); + return this; + } + + public TextRenderer strong(@NotNull Object text) { + elements.add(new TextElement(TextElementType.STRONG, text.toString())); + return this; + } + } + + protected final List renderers = Lists.newArrayList(); + + public TabledDescriptorRenderer text(@NotNull TextRenderer textRenderer) { + renderers.add(textRenderer); + return this; + } + + public TabledDescriptorRenderer table(@NotNull TableRenderer tableRenderer) { + renderers.add(tableRenderer); + return this; + } + + public static TextRenderer newText() { + return new TextRenderer(); + } + + public static TableRenderer newTable() { + return new TableRenderer(); + } + + + //protected final List previousTables = Lists.newArrayList(); + //private TextRow currentFirstText; + //private List currentRows; + // + //public TabledDescriptorRenderer newElement() { + // previousTables.add(new TableRenderer(currentFirstText, currentRows)); + // currentFirstText = null; + // currentRows = Lists.newArrayList(); + // return this; + //} + // + //public TabledDescriptorRenderer text(String text) { + // if (currentRows.isEmpty()) { + // currentFirstText = new TextRow(text); + // return this; + // } + // currentRows.add(new TextRow(text)); + // return this; + //} + // + //public TabledDescriptorRenderer text(String text, Object... args) { + // return text(String.format(text, args)); + //} + + + + + //private TabledDescriptorRenderer(@Nullable TextRow firstText, @NotNull List rows) { + // this.currentFirstText = firstText; + // this.currentRows = rows; + //} + // + //protected TabledDescriptorRenderer() { + // this(null, Lists.newArrayList()); + //} + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + for (TableOrTextRenderer tableOrTextRenderer : renderers) { + if (tableOrTextRenderer instanceof TableRenderer) { + renderTable((TableRenderer)tableOrTextRenderer, result); + } + else { + renderText((TextRenderer)tableOrTextRenderer, result); + } + } + return result.toString(); + } + + protected void renderText(TextRenderer textRenderer, StringBuilder result) { + for (TextElement element : textRenderer.elements) { + result.append(element.text); + } + } + + protected void renderTable(TableRenderer table, StringBuilder result) { + if (table.rows.isEmpty()) return; + for (TableRow row : table.rows) { + if (row instanceof TextRenderer) { + renderText((TextRenderer) row, result); + } + if (row instanceof DescriptorRow) { + result.append(DescriptorRenderer.COMPACT.render(((DescriptorRow) row).descriptor)); + } + if (row instanceof FunctionArgumentsRow) { + FunctionArgumentsRow functionArgumentsRow = (FunctionArgumentsRow) row; + renderFunctionArguments(functionArgumentsRow.receiverType, functionArgumentsRow.argumentTypes, result); + } + result.append("\n"); + } + } + + private void renderFunctionArguments(@Nullable JetType receiverType, @NotNull List argumentTypes, StringBuilder result) { + boolean hasReceiver = receiverType != null; + if (hasReceiver) { + result.append("receiver: "); + result.append(Renderers.RENDER_TYPE.render(receiverType)); + result.append(" arguments: "); + } + if (argumentTypes.isEmpty()) { + result.append("()"); + return; + } + + result.append("("); + for (Iterator iterator = argumentTypes.iterator(); iterator.hasNext(); ) { + JetType argumentType = iterator.next(); + String renderedArgument = Renderers.RENDER_TYPE.render(argumentType); + + result.append(renderedArgument); + if (iterator.hasNext()) { + result.append(","); + } + } + result.append(")"); + } + + public static TabledDescriptorRenderer create() { + return new TabledDescriptorRenderer(); + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/TablesRenderer.java b/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java similarity index 63% rename from idea/src/org/jetbrains/jet/plugin/highlighter/TablesRenderer.java rename to idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java index 11c6a838fb1..1d6daf54414 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/TablesRenderer.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java @@ -16,119 +16,43 @@ package org.jetbrains.jet.plugin.highlighter; -import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.resolve.DescriptorRenderer; + import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.*; +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.*; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; /** * @author svtk */ -public class TablesRenderer { - public static class Table { - public final TextRow firstText; - public final List rows; +public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { - public Table(TextRow firstText, List rows) { - this.firstText = firstText; - this.rows = rows; + protected void renderText(TextRenderer textRenderer, StringBuilder result) { + for (TextRenderer.TextElement element : textRenderer.elements) { + if (element.type == TextRenderer.TextElementType.DEFAULT) { + result.append(element.text); + } + else if (element.type == TextRenderer.TextElementType.ERROR) { + result.append(error(element.text)); + } + else if (element.type == TextRenderer.TextElementType.STRONG) { + result.append(strong(element.text)); + } } } - public interface TableRow { - } - - public static class TextRow implements TableRow { - public final String text; - - public TextRow(String text) { - this.text = text; - } - } - - public static class DescriptorRow implements TableRow { - public final CallableDescriptor descriptor; - - public DescriptorRow(CallableDescriptor descriptor) { - this.descriptor = descriptor; - } - } - - public static class FunctionArgumentsRow implements TableRow { - public final JetType receiverType; - public final List argumentTypes; - public final Collection errorPositions; - - public FunctionArgumentsRow(JetType receiverType, List argumentTypes, Collection errorPositions) { - this.receiverType = receiverType; - this.argumentTypes = argumentTypes; - this.errorPositions = errorPositions; - } - } - - private final List previousTables = Lists.newArrayList(); - private TextRow currentFirstText; - private List currentRows; - - public TablesRenderer newElement() { - previousTables.add(new Table(currentFirstText, currentRows)); - currentFirstText = null; - currentRows = Lists.newArrayList(); - return this; - } - - public TablesRenderer text(String text) { - if (currentRows.isEmpty()) { - currentFirstText = new TextRow(text); - return this; - } - currentRows.add(new TextRow(text)); - return this; - } - - public TablesRenderer text(String text, Object... args) { - return text(String.format(text, args)); - } - - public TablesRenderer descriptor(CallableDescriptor descriptor) { - currentRows.add(new DescriptorRow(descriptor)); - return this; - } - - public TablesRenderer functionArgumentTypeList(@Nullable JetType receiverType, @NotNull List argumentTypes) { - return functionArgumentTypeList(receiverType, argumentTypes, Collections.emptyList()); - } - - public TablesRenderer functionArgumentTypeList(@Nullable JetType receiverType, - @NotNull List argumentTypes, - Collection errorPositions) { - currentRows.add(new FunctionArgumentsRow(receiverType, argumentTypes, errorPositions)); - return this; - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - newElement(); - for (Table table : previousTables) { - renderTable(table, result); - } - return result.toString(); - } - - private static int countRowsNumber(Table table) { + private int countRowsNumber(TableRenderer table) { int argumentsNumber = 0; for (TableRow row : table.rows) { if (row instanceof DescriptorRow) { @@ -149,21 +73,19 @@ public class TablesRenderer { return argumentsNumber + 6; } - - - private static void renderTable(Table table, StringBuilder result) { - if (table.firstText == null && table.rows.isEmpty()) return; - if (table.firstText != null) { - result.append(table.firstText.text); - } + @Override + protected void renderTable(TableRenderer table, StringBuilder result) { + if (table.rows.isEmpty()) return; int rowsNumber = countRowsNumber(table); result.append("
"); for (TableRow row : table.rows) { result.append(""); - if (row instanceof TextRow) { - tdColspan(result, ((TextRow) row).text, rowsNumber); + if (row instanceof TextRenderer) { + StringBuilder rowText = new StringBuilder(); + renderText((TextRenderer) row, rowText); + tdColspan(result, rowText.toString(), rowsNumber); } if (row instanceof DescriptorRow) { result.append(DESCRIPTOR_IN_TABLE.render(((DescriptorRow) row).descriptor)); @@ -179,7 +101,7 @@ public class TablesRenderer { result.append("
"); } - private static void renderFunctionArguments(@Nullable JetType receiverType, @NotNull List argumentTypes, Collection errorPositions, StringBuilder result) { + private void renderFunctionArguments(@Nullable JetType receiverType, @NotNull List argumentTypes, Collection errorPositions, StringBuilder result) { boolean hasReceiver = receiverType != null; tdSpace(result); String receiver = ""; @@ -213,20 +135,25 @@ public class TablesRenderer { td(result, strong(")")); } - public static TablesRenderer create() { - return new TablesRenderer(); + public static HtmlTabledDescriptorRenderer create() { + return new HtmlTabledDescriptorRenderer(); } - TablesRenderer(@Nullable TextRow firstText, @NotNull List rows) { - this.currentFirstText = firstText; - this.currentRows = rows; + protected HtmlTabledDescriptorRenderer() { + super(); } - TablesRenderer() { - this(null, Lists.newArrayList()); - } + public static final DescriptorRenderer DESCRIPTOR_IN_TABLE = new DescriptorRenderer.HtmlDescriptorRenderer() { + @Override + protected boolean shouldRenderDefinedIn() { + return false; + } + + @Override + protected boolean shouldRenderModifiers() { + return false; + } - public static final DescriptorRenderer DESCRIPTOR_IN_TABLE = new DescriptorRenderer.HtmlDescriptorRenderer(false, false) { @NotNull @Override public String render(@NotNull DeclarationDescriptor declarationDescriptor) { diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java index 4bab828d301..c38fe48838f 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java @@ -44,10 +44,10 @@ public class IdeErrorMessages { MAP.put(ASSIGN_OPERATOR_AMBIGUITY, "Assignment operators ambiguity. All these functions match.
    {0}
", HTML_AMBIGUOUS_CALLS); - MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", HTML_INFERENCE_ERROR_CONFLICTING_SUBSTITUTIONS); - MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", HTML_INFERENCE_NO_INFORMATION_FOR_PARAMETER); - MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", HTML_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH); - MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", HTML_INFERENCE_UPPER_BOUND_VIOLATED); + MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER); + MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); + MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", HTML_TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER); + MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(WRONG_SETTER_PARAMETER_TYPE, "Setter parameter type must be equal to the type of the property." + "" + diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeRenderers.java b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeRenderers.java index 484e7129b64..874d586f382 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeRenderers.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeRenderers.java @@ -16,15 +16,12 @@ package org.jetbrains.jet.plugin.highlighter; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; @@ -36,19 +33,19 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl; import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument; -import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData; -import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeSubstitutor; -import org.jetbrains.jet.lang.types.Variance; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.resolve.DescriptorRenderer; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.*; /** * @author svtk @@ -181,115 +178,40 @@ public class IdeRenderers { } } - public static final Renderer HTML_INFERENCE_ERROR_CONFLICTING_SUBSTITUTIONS = + public static final Renderer HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER = new Renderer() { @NotNull @Override public String render(@NotNull InferenceErrorData inferenceErrorData) { - Collection substitutedDescriptors = Lists.newArrayList(); - Collection substitutors = inferenceErrorData.constraintSystem.getSubstitutors(); - for (TypeSubstitutor substitutor : substitutors) { - CallableDescriptor substitutedDescriptor = inferenceErrorData.descriptor.substitute(substitutor); - substitutedDescriptors.add(substitutedDescriptor); - } - - String type = strong(inferenceErrorData.constraintSystem.getFirstConflictingParameter().getName()); - TablesRenderer table = TablesRenderer.create(); - table.text("Cannot infer type parameter %s in", type) - .descriptor(inferenceErrorData.descriptor) - .text("None of the following substitutions"); - - for (CallableDescriptor substitutedDescriptor : substitutedDescriptors) { - JetType receiverType = substitutedDescriptor.getReceiverParameter().exists() ? substitutedDescriptor.getReceiverParameter().getType() : null; - - Collection errorPositions = Sets.newHashSet(); - List valueArgumentTypes = Lists.newArrayList(); - for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) { - valueArgumentTypes.add(valueParameterDescriptor.getType()); - JetType actualType = inferenceErrorData.valueArgumentsTypes.get(valueParameterDescriptor.getIndex()); - if (!JetTypeChecker.INSTANCE.isSubtypeOf(actualType, valueParameterDescriptor.getType())) { - errorPositions.add(ConstraintPosition.valueParameterPosition(valueParameterDescriptor.getIndex())); - } - } - - if (receiverType != null && inferenceErrorData.receiverArgumentType != null && - !JetTypeChecker.INSTANCE.isSubtypeOf(inferenceErrorData.receiverArgumentType, receiverType)) { - errorPositions.add(ConstraintPosition.RECEIVER_POSITION); - } - - table.functionArgumentTypeList(receiverType, valueArgumentTypes, errorPositions); - } - - table.text("can be applied to") - .functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes); - return table.toString(); + return renderConflictingSubstitutionsInferenceError(inferenceErrorData, HtmlTabledDescriptorRenderer.create()).toString(); } }; - - public static final Renderer HTML_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH = + public static final Renderer HTML_TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER = new Renderer() { @NotNull @Override public String render(@NotNull InferenceErrorData inferenceErrorData) { - return TablesRenderer.create() - .descriptor(inferenceErrorData.descriptor) - .text("cannot be applied to") - .functionArgumentTypeList(inferenceErrorData.receiverArgumentType, inferenceErrorData.valueArgumentsTypes, - inferenceErrorData.constraintSystem.getErrorConstraintPositions()) - .toString(); + return renderTypeConstructorMismatchError(inferenceErrorData, HtmlTabledDescriptorRenderer.create()).toString(); } }; - public static final Renderer HTML_INFERENCE_NO_INFORMATION_FOR_PARAMETER = + public static final Renderer HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER = new Renderer() { @NotNull @Override public String render(@NotNull InferenceErrorData inferenceErrorData) { - TypeParameterDescriptor firstUnknownParameter = null; - for (Map.Entry entry : inferenceErrorData.constraintSystem.getTypeBoundsMap().entrySet()) { - if (entry.getValue().isEmpty()) { - firstUnknownParameter = entry.getKey(); - break; - } - } - assert firstUnknownParameter != null; - String firstUnknownParameterName = String.format(STRONG_TEMPLATE, firstUnknownParameter.getName()); - - return TablesRenderer.create() - .text("Not enough information to infer parameter %s in", firstUnknownParameterName) - .descriptor(inferenceErrorData.descriptor) - .text("Please specify it explicitly.") - .toString(); + return renderNoInformationForParameterError(inferenceErrorData, HtmlTabledDescriptorRenderer.create()).toString(); } }; - public static final Renderer HTML_INFERENCE_UPPER_BOUND_VIOLATED = + public static final Renderer HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER = new Renderer() { @NotNull @Override public String render(@NotNull InferenceErrorData inferenceErrorData) { - - TypeParameterDescriptor typeParameterDescriptor = null; - for (TypeParameterDescriptor typeParameter : inferenceErrorData.descriptor.getTypeParameters()) { - if (!inferenceErrorData.constraintSystem.checkUpperBound(typeParameter)) { - typeParameterDescriptor = typeParameter; - break; - } - } - assert typeParameterDescriptor != null; - - TablesRenderer table = TablesRenderer.create(); - table.text("Type parameter bound for %s in", strong(typeParameterDescriptor.getName())). - descriptor(inferenceErrorData.descriptor); - - JetType type = inferenceErrorData.constraintSystem.getValue(typeParameterDescriptor); - JetType upperBound = typeParameterDescriptor.getUpperBoundsAsType(); - JetType substitute = inferenceErrorData.constraintSystem.getSubstitutor().substitute(upperBound, Variance.INVARIANT); - - table.newElement() - .text("is not satisfied: inferred type %s is not a subtype of %s.", error(type), strong(substitute)); - return table.toString(); + return renderUpperBoundViolatedInferenceError(inferenceErrorData, HtmlTabledDescriptorRenderer.create()).toString(); } }; + }
Expected:{0}