CLI: improve diagnostic message format

- render the whole line where the error/warning points to, if any, and another
  line with '^', like other compilers do
- lowercase diagnostic severity
- decapitalize the message if it doesn't start with a proper name
This commit is contained in:
Alexander Udalov
2015-06-13 03:43:20 +03:00
parent 46515afb22
commit 54dfd626ab
49 changed files with 316 additions and 134 deletions
@@ -21,15 +21,21 @@ import kotlin.platform.platformStatic
public data class CompilerMessageLocation private constructor(
public val path: String?,
public val line: Int,
public val column: Int
public val column: Int,
public val lineContent: String?
) {
override fun toString(): String =
path + (if (line != -1 || column != -1) " (" + line + ":" + column + ")" else "")
companion object {
public platformStatic val NO_LOCATION: CompilerMessageLocation = CompilerMessageLocation(null, -1, -1)
public platformStatic val NO_LOCATION: CompilerMessageLocation = CompilerMessageLocation(null, -1, -1, null)
public platformStatic fun create(path: String?, line: Int, column: Int): CompilerMessageLocation =
if (path == null) NO_LOCATION else CompilerMessageLocation(path, line, column)
public platformStatic fun create(
path: String?,
line: Int,
column: Int,
lineContent: String?
): CompilerMessageLocation =
if (path == null) NO_LOCATION else CompilerMessageLocation(path, line, column, lineContent)
}
}
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.cli.common.messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.LineSeparator;
import kotlin.KotlinPackage;
import kotlin.io.IoPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -78,6 +80,8 @@ public interface MessageRenderer {
};
abstract class PlainText implements MessageRenderer {
private static final String LINE_SEPARATOR = LineSeparator.getSystemLineSeparator().getSeparatorString();
@Override
public String renderPreamble() {
return "";
@@ -88,24 +92,56 @@ public interface MessageRenderer {
@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location
) {
StringBuilder result = new StringBuilder();
result.append(severity).append(": ");
int line = location.getLine();
int column = location.getColumn();
String lineContent = location.getLineContent();
String path = getPath(location);
if (path != null) {
result.append(path);
result.append(": ");
if (location.getLine() > 0 && location.getColumn() > 0) {
result.append("(");
result.append(location.getLine()).append(", ").append(location.getColumn());
result.append(") ");
result.append(":");
if (line > 0) {
result.append(line).append(":");
if (column > 0) {
result.append(column).append(":");
}
}
result.append(" ");
}
result.append(message);
result.append(severity.name().toLowerCase());
result.append(": ");
result.append(decapitalizeIfNeeded(message));
if (lineContent != null && 1 <= column && column <= lineContent.length() + 1) {
result.append(LINE_SEPARATOR);
result.append(lineContent);
result.append(LINE_SEPARATOR);
result.append(KotlinPackage.repeat(" ", column - 1));
result.append("^");
}
return result.toString();
}
@NotNull
private static String decapitalizeIfNeeded(@NotNull String message) {
// TODO: invent something more clever
// An ad-hoc heuristic to prevent decapitalization of some names
if (message.startsWith("Java") || message.startsWith("Kotlin")) {
return message;
}
// For abbreviations and capitalized text
if (message.length() >= 2 && Character.isUpperCase(message.charAt(0)) && Character.isUpperCase(message.charAt(1))) {
return message;
}
return KotlinPackage.decapitalize(message);
}
@Nullable
protected abstract String getPath(@NotNull CompilerMessageLocation location);