package com.intellij.lang.javascript.linter.tslint.execution;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.intellij.lang.javascript.linter.tslint.config.TsLintConfiguration;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.SemVer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import static com.intellij.lang.javascript.linter.tslint.highlight.TsLintFixInfo.createTsLintFixInfo;
public final class TsLintOutputJsonParser {
private static final Logger LOG = Logger.getInstance(TsLintConfiguration.LOG_CATEGORY);
public static final String FIX_PROPERTY = "fix";
@Nullable
private final String myPath;
private final boolean myMyZeroBasedRowCol;
@NotNull
private final List<TsLinterError> myErrors;
public TsLintOutputJsonParser(@Nullable String path, final JsonElement root, boolean zeroBasedRowCol) {
myPath = path;
myMyZeroBasedRowCol = zeroBasedRowCol;
if (root instanceof JsonNull || !root.isJsonArray()) {
logError("root element is not array");
myErrors = ContainerUtil.emptyList();
}
else {
final JsonArray array = root.getAsJsonArray();
final int size = array.size();
ArrayList<TsLinterError> errors = ContainerUtil.newArrayList();
for (int i = 0; i < size; i++) {
final JsonElement element = array.get(i);
if (!element.isJsonObject()) {
logError("element under root is not object");
}
else {
final JsonObject object = element.getAsJsonObject();
errors.addAll(processError(object));
}
}
myErrors = errors;
}
}
private List<TsLinterError> processError(JsonObject object) {
List<TsLinterError> result = ContainerUtil.newArrayList();
final JsonElement name = object.get("name");
if (name == null) {
logError("no name for error object");
return result;
}
final JsonElement failure = object.get("failure");
if (failure == null || !(failure.isJsonPrimitive() && failure.getAsJsonPrimitive().isString())) {
logError("no failure for error object");
return result;
}
final JsonElement startPosition = object.get("startPosition");
if (startPosition == null || !startPosition.isJsonObject()) {
logError("no startPosition for error object");
return result;
}
final JsonElement endPosition = object.get("endPosition");
if (endPosition == null || !endPosition.isJsonObject()) {
logError("no endPosition for error object");
return result;
}
final JsonElement ruleName = object.get("ruleName");
if (ruleName == null || !(ruleName.isJsonPrimitive() && ruleName.getAsJsonPrimitive().isString())) {
logError("no rule name for error object");
return result;
}
final Pair<Integer, Integer> start = parseLineColumn(startPosition.getAsJsonObject());
final Pair<Integer, Integer> end = parseLineColumn(endPosition.getAsJsonObject());
if (start == null || end == null) return result;
JsonElement element = object.get(FIX_PROPERTY);
String filePath = name.getAsString();
result.add(new TsLinterError(StringUtil.isEmpty(filePath) ? myPath : filePath,
start.getFirst(),
start.getSecond(),
end.getFirst(),
end.getSecond(),
failure.getAsString(),
ruleName.getAsString(),
createTsLintFixInfo(element)));
return result;
}
private Pair<Integer, Integer> parseLineColumn(JsonObject position) {
final JsonElement line = position.get("line");
if (line == null || !(line.isJsonPrimitive() && line.getAsJsonPrimitive().isNumber())) {
logError("no line for position");
return null;
}
final JsonElement character = position.get("character");
if (character == null || !(character.isJsonPrimitive() && character.getAsJsonPrimitive().isNumber())) {
logError("no character for position");
return null;
}
if (myMyZeroBasedRowCol) return Pair.create(line.getAsJsonPrimitive().getAsInt(), character.getAsJsonPrimitive().getAsInt());
return Pair.create(line.getAsJsonPrimitive().getAsInt() + 1, character.getAsJsonPrimitive().getAsInt() + 1);
}
@NotNull
public List<TsLinterError> getErrors() {
return myErrors;
}
private static void logError(String s) {
LOG.info("TSLint result parsing: " + s);
}
public static boolean isVersionZeroBased(SemVer tsLintVersion) {
return tsLintVersion != null && (tsLintVersion.getMajor() < 2 ||
tsLintVersion.getMajor() == 2 && tsLintVersion.getMinor() <= 1);
}
}