"use strict"; /* * @license * Copyright 2018 Palantir Technologies, Inc. * * 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. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.printLine = exports.parseLine = exports.ZERO_LENGTH_ERROR = exports.EndErrorLine = exports.MultilineErrorLine = exports.ErrorLine = exports.MessageSubstitutionLine = exports.CodeLine = exports.Line = void 0; var tslib_1 = require("tslib"); // Use classes here instead of interfaces because we want runtime type data var Line = /** @class */ (function () { function Line() { } return Line; }()); exports.Line = Line; var CodeLine = /** @class */ (function (_super) { tslib_1.__extends(CodeLine, _super); function CodeLine(contents) { var _this = _super.call(this) || this; _this.contents = contents; return _this; } return CodeLine; }(Line)); exports.CodeLine = CodeLine; var MessageSubstitutionLine = /** @class */ (function (_super) { tslib_1.__extends(MessageSubstitutionLine, _super); function MessageSubstitutionLine(key, message) { var _this = _super.call(this) || this; _this.key = key; _this.message = message; return _this; } return MessageSubstitutionLine; }(Line)); exports.MessageSubstitutionLine = MessageSubstitutionLine; var ErrorLine = /** @class */ (function (_super) { tslib_1.__extends(ErrorLine, _super); function ErrorLine(startCol) { var _this = _super.call(this) || this; _this.startCol = startCol; return _this; } return ErrorLine; }(Line)); exports.ErrorLine = ErrorLine; var MultilineErrorLine = /** @class */ (function (_super) { tslib_1.__extends(MultilineErrorLine, _super); function MultilineErrorLine(startCol) { return _super.call(this, startCol) || this; } return MultilineErrorLine; }(ErrorLine)); exports.MultilineErrorLine = MultilineErrorLine; var EndErrorLine = /** @class */ (function (_super) { tslib_1.__extends(EndErrorLine, _super); function EndErrorLine(startCol, endCol, message) { var _this = _super.call(this, startCol) || this; _this.endCol = endCol; _this.message = message; return _this; } return EndErrorLine; }(ErrorLine)); exports.EndErrorLine = EndErrorLine; // example matches (between the quotes): // " ~~~~~~~~" var multilineErrorRegex = /^\s*(~+|~nil)$/; // " ~~~~~~~~~ [some error message]" var endErrorRegex = /^\s*(~+|~nil)\s*\[(.+)\]\s*$/; // "[shortcut]: full messages goes here!! " var messageSubstitutionRegex = /^\[([-\w]+?)]: \s*(.+?)\s*$/; exports.ZERO_LENGTH_ERROR = "~nil"; /** * Maps a line of text from a .lint file to an appropriate Line object */ function parseLine(text) { var multilineErrorMatch = text.match(multilineErrorRegex); if (multilineErrorMatch !== null) { var startErrorCol = text.indexOf("~"); return new MultilineErrorLine(startErrorCol); } var endErrorMatch = text.match(endErrorRegex); if (endErrorMatch !== null) { var squiggles = endErrorMatch[1], message = endErrorMatch[2]; var startErrorCol = text.indexOf("~"); var zeroLengthError = squiggles === exports.ZERO_LENGTH_ERROR; var endErrorCol = zeroLengthError ? startErrorCol : text.lastIndexOf("~") + 1; return new EndErrorLine(startErrorCol, endErrorCol, message); } var messageSubstitutionMatch = text.match(messageSubstitutionRegex); if (messageSubstitutionMatch !== null) { var key = messageSubstitutionMatch[1], message = messageSubstitutionMatch[2]; return new MessageSubstitutionLine(key, message); } // line doesn't match any syntax for error markup, so it's a line of code to be linted return new CodeLine(text); } exports.parseLine = parseLine; /** * Maps a Line object to a matching line of text that could be in a .lint file. * This is almost the inverse of parseLine. * If you ran `printLine(parseLine(someText), code)`, the whitespace in the result may be different than in someText * @param fileName - File name containing the line and code. * @param line - A Line object to convert to text * @param code - If line represents error markup, this is the line of code preceding the markup. * Otherwise, this parameter is not required. */ function printLine(fileName, line, code) { if (line instanceof ErrorLine) { if (code === undefined) { throw new Error(fileName + ": Must supply argument for code parameter when line is an ErrorLine"); } var leadingSpaces = " ".repeat(line.startCol); if (line instanceof MultilineErrorLine) { // special case for when the line of code is simply a newline. // use "~nil" to indicate the error continues on that line if (code.length === 0 && line.startCol === 0) { return exports.ZERO_LENGTH_ERROR; } var tildes = "~".repeat(code.length - leadingSpaces.length); return "" + leadingSpaces + tildes; } else if (line instanceof EndErrorLine) { var tildes = "~".repeat(line.endCol - line.startCol); if (code.length < line.endCol) { // Better than crashing in String.repeat throw new Error("Bad error marker in " + fileName + " at " + JSON.stringify(line)); } var endSpaces = " ".repeat(code.length - line.endCol); if (tildes.length === 0) { tildes = exports.ZERO_LENGTH_ERROR; // because we add "~nil" we need four less spaces than normal at the end // always make sure we have at least one space though endSpaces = endSpaces.substring(0, Math.max(endSpaces.length - 4, 1)); } return "" + leadingSpaces + tildes + endSpaces + " [" + line.message + "]"; } } else if (line instanceof MessageSubstitutionLine) { return "[" + line.key + "]: " + line.message; } else if (line instanceof CodeLine) { return line.contents; } return undefined; } exports.printLine = printLine;