package com.google.jstestdriver.idea.common; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; public class JsErrorMessage { private static final String UNCAUGHT_PREFIX = "Uncaught "; private final File myFileWithError; private int myLineNumber; private final Integer myColumnNumber; private final boolean myErrorNameWithUncaughtPrefix; private final String myParsedErrorName; private final int myHyperlinkStartInclusiveInd; private final int myHyperlinkEndExclusiveInd; public JsErrorMessage(@NotNull File fileWithError, int lineNumber, @Nullable Integer columnNumber, boolean errorNameWithUncaughtPrefix, @Nullable String parsedErrorName, int hyperlinkStartInclusiveInd, int hyperlinkEndExclusiveInd) { myFileWithError = fileWithError; myLineNumber = lineNumber; myColumnNumber = columnNumber; myErrorNameWithUncaughtPrefix = errorNameWithUncaughtPrefix; myParsedErrorName = parsedErrorName; myHyperlinkStartInclusiveInd = hyperlinkStartInclusiveInd; myHyperlinkEndExclusiveInd = hyperlinkEndExclusiveInd; } @NotNull public String getErrorName() { String errorName = myParsedErrorName; if (errorName != null && errorName.contains(" ")) { errorName = null; } if (errorName != null && !errorName.endsWith("Error")) { errorName = null; } if (errorName == null) { errorName = "Error"; } if (myErrorNameWithUncaughtPrefix) { errorName = UNCAUGHT_PREFIX + errorName; } return errorName; } @NotNull public File getFileWithError() { return myFileWithError; } public int getLineNumber() { return myLineNumber; } @Nullable public Integer getColumnNumber() { return myColumnNumber; } public int getHyperlinkStartInclusiveInd() { return myHyperlinkStartInclusiveInd; } public int getHyperlinkEndExclusiveInd() { return myHyperlinkEndExclusiveInd; } @Nullable public static JsErrorMessage parseFromText(@NotNull String text, @NotNull File basePath) { String prefix = "error loading file: "; if (!text.startsWith(prefix)) { return null; } String pathAndOther = text.substring(prefix.length()); int filePathEndInd = findFilePathEndColonIndex(pathAndOther, basePath); if (filePathEndInd < 0) { return null; } String filePath = pathAndOther.substring(0, filePathEndInd); File file = resolveFile(filePath, basePath); if (file == null) { return null; } int lineNumberEndInd = pathAndOther.indexOf(':', filePathEndInd + 1); if (lineNumberEndInd < 0) { return null; } String lineNumberStr = pathAndOther.substring(filePathEndInd + 1, lineNumberEndInd); Integer lineNumber = toInteger(lineNumberStr); if (lineNumber == null) { return null; } int columnNumberEndInd = pathAndOther.indexOf(':', lineNumberEndInd + 1); int textMessageStartInd = lineNumberEndInd + 1; Integer columnNumber = null; if (columnNumberEndInd > 0) { String columnNumberStr = pathAndOther.substring(lineNumberEndInd + 1, columnNumberEndInd); columnNumber = toInteger(columnNumberStr); if (columnNumber != null) { textMessageStartInd = columnNumberEndInd + 1; } } String errorNameAndOther = pathAndOther.substring(textMessageStartInd).trim(); boolean uncaughtTextPresented = false; if (errorNameAndOther.startsWith(UNCAUGHT_PREFIX)) { errorNameAndOther = errorNameAndOther.substring(UNCAUGHT_PREFIX.length()).trim(); uncaughtTextPresented = true; } String exceptionStr = "exception:"; if (errorNameAndOther.startsWith(exceptionStr)) { errorNameAndOther = errorNameAndOther.substring(exceptionStr.length()).trim(); } int detailsStartInd = errorNameAndOther.indexOf(':'); if (detailsStartInd > 0) { errorNameAndOther = errorNameAndOther.substring(0, detailsStartInd); } return new JsErrorMessage(file, lineNumber, columnNumber, uncaughtTextPresented, errorNameAndOther, prefix.length(), prefix.length() + textMessageStartInd - 1); } private static int findFilePathEndColonIndex(@NotNull String str, @NotNull File basePath) { int index = 0; int lastValidIndex = -1; while (true) { index = str.indexOf(':', index + 1); if (index < 0) { break; } File resolvedFile = resolveFile(str.substring(0, index), basePath); if (resolvedFile != null) { lastValidIndex = index; } } return lastValidIndex; } @Nullable private static Integer toInteger(String s) { try { return Integer.parseInt(s); } catch (Exception e) { return null; } } @Nullable private static File resolveFile(@NotNull String testAndFilePath, @NotNull File basePath) { String prefix = "/test/"; if (testAndFilePath.startsWith(prefix)) { String filePath = testAndFilePath.substring(prefix.length()); if (filePath.isEmpty()) { return null; } File absoluteFile = new File(filePath); if (absoluteFile.isAbsolute() && absoluteFile.isFile()) { return absoluteFile; } File file = new File(basePath, filePath); if (file.isFile()) { return file; } } return null; } }