4 * Copyright 2018 Palantir Technologies, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 // Use classes here instead of interfaces because we want runtime type data
21 var Line = /** @class */ (function () {
27 var CodeLine = /** @class */ (function (_super) {
28 tslib_1.__extends(CodeLine, _super);
29 function CodeLine(contents) {
30 var _this = _super.call(this) || this;
31 _this.contents = contents;
36 exports.CodeLine = CodeLine;
37 var MessageSubstitutionLine = /** @class */ (function (_super) {
38 tslib_1.__extends(MessageSubstitutionLine, _super);
39 function MessageSubstitutionLine(key, message) {
40 var _this = _super.call(this) || this;
42 _this.message = message;
45 return MessageSubstitutionLine;
47 exports.MessageSubstitutionLine = MessageSubstitutionLine;
48 var ErrorLine = /** @class */ (function (_super) {
49 tslib_1.__extends(ErrorLine, _super);
50 function ErrorLine(startCol) {
51 var _this = _super.call(this) || this;
52 _this.startCol = startCol;
57 exports.ErrorLine = ErrorLine;
58 var MultilineErrorLine = /** @class */ (function (_super) {
59 tslib_1.__extends(MultilineErrorLine, _super);
60 function MultilineErrorLine(startCol) {
61 return _super.call(this, startCol) || this;
63 return MultilineErrorLine;
65 exports.MultilineErrorLine = MultilineErrorLine;
66 var EndErrorLine = /** @class */ (function (_super) {
67 tslib_1.__extends(EndErrorLine, _super);
68 function EndErrorLine(startCol, endCol, message) {
69 var _this = _super.call(this, startCol) || this;
70 _this.endCol = endCol;
71 _this.message = message;
76 exports.EndErrorLine = EndErrorLine;
77 // example matches (between the quotes):
79 var multilineErrorRegex = /^\s*(~+|~nil)$/;
80 // " ~~~~~~~~~ [some error message]"
81 var endErrorRegex = /^\s*(~+|~nil)\s*\[(.+)\]\s*$/;
82 // "[shortcut]: full messages goes here!! "
83 var messageSubstitutionRegex = /^\[([-\w]+?)]: \s*(.+?)\s*$/;
84 exports.ZERO_LENGTH_ERROR = "~nil";
86 * Maps a line of text from a .lint file to an appropriate Line object
88 function parseLine(text) {
89 var multilineErrorMatch = text.match(multilineErrorRegex);
90 if (multilineErrorMatch !== null) {
91 var startErrorCol = text.indexOf("~");
92 return new MultilineErrorLine(startErrorCol);
94 var endErrorMatch = text.match(endErrorRegex);
95 if (endErrorMatch !== null) {
96 var squiggles = endErrorMatch[1], message = endErrorMatch[2];
97 var startErrorCol = text.indexOf("~");
98 var zeroLengthError = squiggles === exports.ZERO_LENGTH_ERROR;
99 var endErrorCol = zeroLengthError ? startErrorCol : text.lastIndexOf("~") + 1;
100 return new EndErrorLine(startErrorCol, endErrorCol, message);
102 var messageSubstitutionMatch = text.match(messageSubstitutionRegex);
103 if (messageSubstitutionMatch !== null) {
104 var key = messageSubstitutionMatch[1], message = messageSubstitutionMatch[2];
105 return new MessageSubstitutionLine(key, message);
107 // line doesn't match any syntax for error markup, so it's a line of code to be linted
108 return new CodeLine(text);
110 exports.parseLine = parseLine;
112 * Maps a Line object to a matching line of text that could be in a .lint file.
113 * This is almost the inverse of parseLine.
114 * If you ran `printLine(parseLine(someText), code)`, the whitespace in the result may be different than in someText
115 * @param fileName - File name containing the line and code.
116 * @param line - A Line object to convert to text
117 * @param code - If line represents error markup, this is the line of code preceding the markup.
118 * Otherwise, this parameter is not required.
120 function printLine(fileName, line, code) {
121 if (line instanceof ErrorLine) {
122 if (code === undefined) {
123 throw new Error(fileName + ": Must supply argument for code parameter when line is an ErrorLine");
125 var leadingSpaces = " ".repeat(line.startCol);
126 if (line instanceof MultilineErrorLine) {
127 // special case for when the line of code is simply a newline.
128 // use "~nil" to indicate the error continues on that line
129 if (code.length === 0 && line.startCol === 0) {
130 return exports.ZERO_LENGTH_ERROR;
132 var tildes = "~".repeat(code.length - leadingSpaces.length);
133 return "" + leadingSpaces + tildes;
135 else if (line instanceof EndErrorLine) {
136 var tildes = "~".repeat(line.endCol - line.startCol);
137 if (code.length < line.endCol) {
138 // Better than crashing in String.repeat
139 throw new Error("Bad error marker in " + fileName + " at " + JSON.stringify(line));
141 var endSpaces = " ".repeat(code.length - line.endCol);
142 if (tildes.length === 0) {
143 tildes = exports.ZERO_LENGTH_ERROR;
144 // because we add "~nil" we need four less spaces than normal at the end
145 // always make sure we have at least one space though
146 endSpaces = endSpaces.substring(0, Math.max(endSpaces.length - 4, 1));
148 return "" + leadingSpaces + tildes + endSpaces + " [" + line.message + "]";
151 else if (line instanceof MessageSubstitutionLine) {
152 return "[" + line.key + "]: " + line.message;
154 else if (line instanceof CodeLine) {
155 return line.contents;
159 exports.printLine = printLine;