JS: underline js() errors for non-string-literal constants
This commit is contained in:
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallDataHtmlRenderer;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
@@ -125,7 +127,8 @@ public class IdeErrorMessages {
|
||||
|
||||
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);
|
||||
|
||||
MAP.put(ErrorsJs.JSCODE_ERROR, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE$);
|
||||
MAP.put(ErrorsJs.JSCODE_WARNING, "<html>JavaScript: {0}</html>", JsCallDataHtmlRenderer.INSTANCE$);
|
||||
MAP.setImmutable();
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -31,9 +31,9 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by Delegates.lazy {
|
||||
put(ErrorsJs.NATIVE_GETTER_RETURN_TYPE_SHOULD_BE_NULLABLE, "Native getter''s return type should be nullable")
|
||||
put(ErrorsJs.NATIVE_SETTER_WRONG_RETURN_TYPE, "Native setter''s return type should be ''Unit'' or a supertype of the second parameter''s type")
|
||||
put(ErrorsJs.NATIVE_INDEXER_WRONG_PARAMETER_COUNT, "Expected {0} parameters for native {1}", Renderers.TO_STRING, Renderers.STRING)
|
||||
put(ErrorsJs.JSCODE_ERROR, "JavaScript: {0}", Renderers.TO_STRING, Renderers.TO_STRING)
|
||||
put(ErrorsJs.JSCODE_WARNING, "JavaScript: {0}", Renderers.TO_STRING, Renderers.TO_STRING)
|
||||
put(ErrorsJs.JSCODE_ARGUMENT_SHOULD_BE_LITERAL, "Argument must be string literal")
|
||||
put(ErrorsJs.JSCODE_ERROR, "JavaScript: {0}", JsCallDataTextRenderer)
|
||||
put(ErrorsJs.JSCODE_WARNING, "JavaScript: {0}", JsCallDataTextRenderer)
|
||||
put(ErrorsJs.JSCODE_ARGUMENT_SHOULD_BE_CONSTANT, "Argument must be string constant")
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.renderer.Renderer
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.JsCallData
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.JsCallDataWithCode
|
||||
import com.google.gwt.dev.js.rhino.Utils.isEndOfLine
|
||||
|
||||
abstract class JsCallDataRenderer : Renderer<JsCallData> {
|
||||
protected abstract fun format(data: JsCallDataWithCode): String
|
||||
|
||||
override fun render(data: JsCallData?): String =
|
||||
when (data) {
|
||||
is JsCallDataWithCode -> format(data)
|
||||
is JsCallData -> data.message
|
||||
else -> throw AssertionError("Cannot render null data")
|
||||
}
|
||||
}
|
||||
|
||||
object JsCallDataTextRenderer : JsCallDataRenderer() {
|
||||
override fun format(data: JsCallDataWithCode): String {
|
||||
val codeRange = data.codeRange
|
||||
val code = data.code.underlineAsText(codeRange.getStartOffset(), codeRange.getEndOffset())
|
||||
return "${data.message} in code:\n${code}"
|
||||
}
|
||||
}
|
||||
|
||||
public object JsCallDataHtmlRenderer : JsCallDataRenderer() {
|
||||
override fun format(data: JsCallDataWithCode): String {
|
||||
val codeRange = data.codeRange
|
||||
val code = data.code.underlineAsHtml(codeRange.getStartOffset(), codeRange.getEndOffset())
|
||||
return "${data.message} in code:<br><pre>${code}</pre>"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Underlines string in given rage.
|
||||
*
|
||||
* For example:
|
||||
* var = 10;
|
||||
* ^^^^
|
||||
*/
|
||||
public fun String.underlineAsText(from: Int, to: Int): String {
|
||||
val lines = StringBuilder()
|
||||
var marks = StringBuilder()
|
||||
var lineWasMarked = false
|
||||
|
||||
for (i in indices) {
|
||||
val c = charAt(i)
|
||||
val mark: Char
|
||||
|
||||
mark = when (i) {
|
||||
in from..to -> '^'
|
||||
else -> ' '
|
||||
}
|
||||
|
||||
lines.append(c)
|
||||
marks.append(mark)
|
||||
lineWasMarked = lineWasMarked || mark != ' '
|
||||
|
||||
if (isEndOfLine(c.toInt())) {
|
||||
if (lineWasMarked) {
|
||||
lines.appendln(marks.toString().trimTrailing())
|
||||
lineWasMarked = false
|
||||
}
|
||||
|
||||
marks = StringBuilder()
|
||||
}
|
||||
}
|
||||
|
||||
if (lineWasMarked) {
|
||||
lines.appendln()
|
||||
lines.append(marks.toString())
|
||||
}
|
||||
|
||||
return lines.toString()
|
||||
}
|
||||
|
||||
public fun String.underlineAsHtml(from: Int, to: Int): String {
|
||||
val lines = StringBuilder()
|
||||
var openMarker = false
|
||||
val underlineStart = "<u>"
|
||||
val underlineEnd = "</u>"
|
||||
|
||||
for (i in indices) {
|
||||
val c = charAt(i)
|
||||
|
||||
val mark = when (i) {
|
||||
from -> {
|
||||
openMarker = true
|
||||
underlineStart
|
||||
}
|
||||
to -> {
|
||||
openMarker = false
|
||||
underlineEnd
|
||||
}
|
||||
else -> ""
|
||||
}
|
||||
|
||||
lines.append(mark)
|
||||
|
||||
if (isEndOfLine(c.toInt()) && openMarker) {
|
||||
lines.append(underlineEnd + c + underlineStart)
|
||||
} else {
|
||||
lines.append(c)
|
||||
}
|
||||
}
|
||||
|
||||
return lines.toString()
|
||||
}
|
||||
Reference in New Issue
Block a user