lines.js 6.2KB

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