/* * Copyright 2010-2016 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.kotlin.idea.highlighter; import com.intellij.icons.AllIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.diagnostics.TypeMismatchDueToTypeProjectionsData; import org.jetbrains.kotlin.diagnostics.rendering.*; import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs; import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallDataHtmlRenderer; import java.net.URL; import static org.jetbrains.kotlin.diagnostics.Errors.*; import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_CLASS_OR_OBJECT; import static org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING; import static org.jetbrains.kotlin.diagnostics.rendering.TabledDescriptorRenderer.TextElementType; import static org.jetbrains.kotlin.idea.highlighter.HtmlTabledDescriptorRenderer.tableForTypes; import static org.jetbrains.kotlin.idea.highlighter.IdeRenderers.*; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.ACCIDENTAL_OVERRIDE; import static org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.CONFLICTING_JVM_DECLARATIONS; /** * @see DefaultErrorMessages */ public class IdeErrorMessages { private static final DiagnosticFactoryToRendererMap MAP = new DiagnosticFactoryToRendererMap("IDE"); @NotNull public static String render(@NotNull Diagnostic diagnostic) { DiagnosticRenderer renderer = MAP.get(diagnostic.getFactory()); if (renderer != null) { //noinspection unchecked return renderer.render(diagnostic); } return DefaultErrorMessages.render(diagnostic); } @TestOnly public static boolean hasIdeSpecificMessage(@NotNull Diagnostic diagnostic) { return MAP.get(diagnostic.getFactory()) != null; } static { MAP.put(TYPE_MISMATCH, "<html>Type mismatch.<table><tr><td>Required:</td><td>{0}</td></tr><tr><td>Found:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(TYPE_MISMATCH_DUE_TO_TYPE_PROJECTIONS, "<html>Type mismatch.<table><tr><td>Required:</td><td>{0}</td></tr><tr><td>Found:</td><td>{1}</td></tr></table><br />\n" + "Projected type {2} restricts use of <br />\n{3}\n</html>", new MultiRenderer<TypeMismatchDueToTypeProjectionsData>() { @NotNull @Override public String[] render(@NotNull TypeMismatchDueToTypeProjectionsData object) { RenderingContext context = RenderingContext .of(object.getExpectedType(), object.getExpressionType(), object.getReceiverType(), object.getCallableDescriptor()); return new String[] { HTML_RENDER_TYPE.render(object.getExpectedType(), context), HTML_RENDER_TYPE.render(object.getExpressionType(), context), HTML_RENDER_TYPE.render(object.getReceiverType(), context), HTML.render(object.getCallableDescriptor(), context) }; } }); MAP.put(ASSIGN_OPERATOR_AMBIGUITY, "<html>Assignment operators ambiguity. All these functions match.<ul>{0}</ul></table></html>", HTML_AMBIGUOUS_CALLS); MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "<html>Type inference failed: {0}</html>", HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER); MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "<html>Type inference failed: {0}</html>", HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); MAP.put(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR, "<html>Type inference failed: {0}</html>", HTML_TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER); MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, tableForTypes("Type inference failed. Expected type mismatch: ", "required: ", TextElementType.STRONG, "found: ", TextElementType.ERROR), HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "<html>{0}</html>", HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(WRONG_SETTER_PARAMETER_TYPE, "<html>Setter parameter type must be equal to the type of the property." + "<table><tr><td>Expected:</td><td>{0}</td></tr>" + "<tr><td>Found:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(WRONG_GETTER_RETURN_TYPE, "<html>Getter return type must be equal to the type of the property." + "<table><tr><td>Expected:</td><td>{0}</td></tr>" + "<tr><td>Found:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(ITERATOR_AMBIGUITY, "<html>Method ''iterator()'' is ambiguous for this expression.<ul>{0}</ul></html>", HTML_AMBIGUOUS_CALLS); MAP.put(UPPER_BOUND_VIOLATED, "<html>Type argument is not within its bounds." + "<table><tr><td>Expected:</td><td>{0}</td></tr>" + "<tr><td>Found:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(TYPE_MISMATCH_IN_FOR_LOOP, "<html>Loop parameter type mismatch." + "<table><tr><td>Iterated values:</td><td>{0}</td></tr>" + "<tr><td>Parameter:</td><td>{1}</td></tr></table></html>", HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(RETURN_TYPE_MISMATCH_ON_OVERRIDE, "<html>Return type is ''{0}'', which is not a subtype of overridden<br/>" + "{1}</html>", HTML_RENDER_RETURN_TYPE, HTML); MAP.put(RETURN_TYPE_MISMATCH_ON_INHERITANCE, "<html>Return types of inherited members are incompatible:<br/>{0},<br/>{1}</html>", HTML, HTML); MAP.put(PROPERTY_TYPE_MISMATCH_ON_OVERRIDE, "<html>Property type is ''{0}'', which is not a subtype type of overridden<br/>" + "{1}</html>", HTML_RENDER_RETURN_TYPE, HTML); MAP.put(VAR_TYPE_MISMATCH_ON_OVERRIDE, "<html>Var-property type is ''{0}'', which is not a type of overridden<br/>" + "{1}</html>", HTML_RENDER_RETURN_TYPE, HTML); MAP.put(PROPERTY_TYPE_MISMATCH_ON_INHERITANCE, "<html>Types of inherited properties are incompatible:<br/>{0},<br/>{1}</html>", HTML, HTML); MAP.put(VAR_TYPE_MISMATCH_ON_INHERITANCE, "<html>Types of inherited var-properties do not match:<br/>{0},<br/>{1}</html>", HTML, HTML); MAP.put(VAR_OVERRIDDEN_BY_VAL, "<html>Val-property cannot override var-property<br />" + "{1}</html>", HTML, HTML); MAP.put(VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, "<html>Val-property cannot override var-property<br />" + "{1}</html>", HTML, HTML); MAP.put(ABSTRACT_MEMBER_NOT_IMPLEMENTED, "<html>{0} must be declared abstract or implement abstract member<br/>" + "{1}</html>", RENDER_CLASS_OR_OBJECT, HTML); MAP.put(MANY_IMPL_MEMBER_NOT_IMPLEMENTED, "<html>{0} must override {1}<br />because it inherits many implementations of it</html>", RENDER_CLASS_OR_OBJECT, HTML); MAP.put(RESULT_TYPE_MISMATCH, "<html>Function return type mismatch." + "<table><tr><td>Expected:</td><td>{1}</td></tr>" + "<tr><td>Found:</td><td>{2}</td></tr></table></html>", STRING, HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(OVERLOAD_RESOLUTION_AMBIGUITY, "<html>Overload resolution ambiguity. All these functions match. <ul>{0}</ul></html>", HTML_AMBIGUOUS_CALLS); MAP.put(NONE_APPLICABLE, "<html>None of the following functions can be called with the arguments supplied. <ul>{0}</ul></html>", HTML_NONE_APPLICABLE_CALLS); MAP.put(CANNOT_COMPLETE_RESOLVE, "<html>Cannot choose among the following candidates without completing type inference: <ul>{0}</ul></html>", HTML_AMBIGUOUS_CALLS); MAP.put(UNRESOLVED_REFERENCE_WRONG_RECEIVER, "<html>Unresolved reference. <br/> None of the following candidates is applicable because of receiver type mismatch: <ul>{0}</ul></html>", HTML_AMBIGUOUS_CALLS); MAP.put(DELEGATE_SPECIAL_FUNCTION_AMBIGUITY, "<html>Overload resolution ambiguity on method ''{0}''. All these functions match. <ul>{1}</ul></html>", STRING, HTML_AMBIGUOUS_CALLS); MAP.put(DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, "<html>Property delegate must have a ''{0}'' method. None of the following functions is suitable. <ul>{1}</ul></html>", STRING, HTML_NONE_APPLICABLE_CALLS); MAP.put(DELEGATE_PD_METHOD_NONE_APPLICABLE, "<html>''{0}'' method may be missing. None of the following functions will be called: <ul>{1}</ul></html>", STRING, HTML_NONE_APPLICABLE_CALLS); MAP.put(CONFLICTING_JVM_DECLARATIONS, "<html>Platform declaration clash: {0}</html>", HTML_CONFLICTING_JVM_DECLARATIONS_DATA); MAP.put(ACCIDENTAL_OVERRIDE, "<html>Accidental override: {0}</html>", HTML_CONFLICTING_JVM_DECLARATIONS_DATA); URL errorIconUrl = AllIcons.class.getResource("/general/error.png"); MAP.put(EXCEPTION_FROM_ANALYZER, "<html>Internal Error occurred while analyzing this expression <br/>" + "<table cellspacing=\"0\" cellpadding=\"0\">" + "<tr>" + "<td>(<strong>Please use the \"</strong></td>" + "<td><img src=\"" + errorIconUrl + "\"/></td>" + "<td><strong>\" icon in the bottom-right corner to report this error</strong>):</td>" + "</tr>" + "</table>" + "<br/>" + "<pre>{0}</pre>" + "</html>", HTML_THROWABLE); MAP.put(ErrorsJs.JSCODE_ERROR, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE); MAP.put(ErrorsJs.JSCODE_WARNING, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE); MAP.put(UNSUPPORTED_FEATURE, "<html>{0}</html>", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.UNSUPPORTED, true)); MAP.put(EXPERIMENTAL_FEATURE_WARNING, "<html>{0}</html>", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.WARNING, true)); MAP.put(EXPERIMENTAL_FEATURE_ERROR, "<html>{0}</html>", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR, true)); MAP.setImmutable(); } private IdeErrorMessages() { } }