.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / verify / parse.js
1 "use strict";
2 /*
3  * @license
4  * Copyright 2018 Palantir Technologies, Inc.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var semver = require("semver");
20 var ts = require("typescript");
21 var util_1 = require("util");
22 var utils_1 = require("../utils");
23 var lines_1 = require("./lines");
24 var lintError_1 = require("./lintError");
25 var scanner;
26 function getTypescriptVersionRequirement(text) {
27     var lines = text.split(/\r?\n/);
28     var firstLine = lines_1.parseLine(lines[0]);
29     if (firstLine instanceof lines_1.MessageSubstitutionLine && firstLine.key === "typescript") {
30         return firstLine.message;
31     }
32     return undefined;
33 }
34 exports.getTypescriptVersionRequirement = getTypescriptVersionRequirement;
35 function getNormalizedTypescriptVersion() {
36     var tsVersion = new semver.SemVer(ts.version);
37     // remove prerelease suffix when matching to allow testing with nightly builds
38     return tsVersion.major + "." + tsVersion.minor + "." + tsVersion.patch;
39 }
40 exports.getNormalizedTypescriptVersion = getNormalizedTypescriptVersion;
41 function preprocessDirectives(text) {
42     if (!/^#(?:if|else|endif)\b/m.test(text)) {
43         return text; // If there are no directives, just return the input unchanged
44     }
45     var tsVersion = getNormalizedTypescriptVersion();
46     var lines = text.split(/\n/);
47     var result = [];
48     var collecting = true;
49     var state = 0 /* Initial */;
50     for (var _i = 0, lines_2 = lines; _i < lines_2.length; _i++) {
51         var line = lines_2[_i];
52         if (line.startsWith("#if typescript")) {
53             if (state !== 0 /* Initial */) {
54                 throw lintError_1.lintSyntaxError("#if directives cannot be nested");
55             }
56             state = 1 /* If */;
57             collecting = semver.satisfies(tsVersion, line.slice("#if typescript".length).trim());
58         }
59         else if (/^#else\s*$/.test(line)) {
60             if (state !== 1 /* If */) {
61                 throw lintError_1.lintSyntaxError("unexpected #else");
62             }
63             state = 2 /* Else */;
64             collecting = !collecting;
65         }
66         else if (/^#endif\s*$/.test(line)) {
67             if (state === 0 /* Initial */) {
68                 throw lintError_1.lintSyntaxError("unexpected #endif");
69             }
70             state = 0 /* Initial */;
71             collecting = true;
72         }
73         else if (collecting) {
74             result.push(line);
75         }
76     }
77     if (state !== 0 /* Initial */) {
78         throw lintError_1.lintSyntaxError("expected #endif");
79     }
80     return result.join("\n");
81 }
82 exports.preprocessDirectives = preprocessDirectives;
83 /**
84  * Takes the full text of a .lint file and returns the contents of the file
85  * with all error markup removed
86  */
87 function removeErrorMarkup(text) {
88     var textWithMarkup = text.split("\n");
89     var lines = textWithMarkup.map(lines_1.parseLine);
90     var codeText = lines
91         .filter(function (line) { return line instanceof lines_1.CodeLine; })
92         .map(function (line) { return line.contents; });
93     return codeText.join("\n");
94 }
95 exports.removeErrorMarkup = removeErrorMarkup;
96 /* tslint:disable:object-literal-sort-keys */
97 /**
98  * Takes the full text of a .lint file and returns an array of LintErrors
99  * corresponding to the error markup in the file.
100  */
101 function parseErrorsFromMarkup(text) {
102     var textWithMarkup = text.split("\n");
103     var lines = textWithMarkup.map(lines_1.parseLine);
104     if (lines.length > 0 && !(lines[0] instanceof lines_1.CodeLine)) {
105         throw lintError_1.lintSyntaxError("text cannot start with an error mark line.");
106     }
107     var messageSubstitutionLines = lines.filter(function (l) { return l instanceof lines_1.MessageSubstitutionLine; });
108     var messageSubstitutions = new Map();
109     for (var _i = 0, messageSubstitutionLines_1 = messageSubstitutionLines; _i < messageSubstitutionLines_1.length; _i++) {
110         var _a = messageSubstitutionLines_1[_i], key = _a.key, message = _a.message;
111         messageSubstitutions.set(key, formatMessage(messageSubstitutions, message));
112     }
113     // errorLineForCodeLine[5] contains all the ErrorLine objects associated with the 5th line of code, for example
114     var errorLinesForCodeLines = createCodeLineNoToErrorsMap(lines);
115     var lintErrors = [];
116     function addError(errorLine, errorStartPos, lineNo) {
117         lintErrors.push({
118             startPos: errorStartPos,
119             endPos: { line: lineNo, col: errorLine.endCol },
120             message: substituteMessage(messageSubstitutions, errorLine.message),
121         });
122     }
123     // for each line of code...
124     errorLinesForCodeLines.forEach(function (errorLinesForLineOfCode, lineNo) {
125         // for each error marking on that line...
126         while (errorLinesForLineOfCode.length > 0) {
127             var errorLine = errorLinesForLineOfCode.shift();
128             var errorStartPos = { line: lineNo, col: errorLine.startCol };
129             // if the error starts and ends on this line, add it now to list of errors
130             if (errorLine instanceof lines_1.EndErrorLine) {
131                 addError(errorLine, errorStartPos, lineNo);
132                 // if the error is the start of a multiline error
133             }
134             else if (errorLine instanceof lines_1.MultilineErrorLine) {
135                 // iterate through the MultilineErrorLines until we get to an EndErrorLine
136                 for (var nextLineNo = lineNo + 1;; ++nextLineNo) {
137                     if (!isValidErrorMarkupContinuation(errorLinesForCodeLines, nextLineNo)) {
138                         throw lintError_1.lintSyntaxError("Error mark starting at " + errorStartPos.line + ":" + errorStartPos.col + " does not end correctly.");
139                     }
140                     else {
141                         var nextErrorLine = errorLinesForCodeLines[nextLineNo].shift();
142                         // if end of multiline error, add it it list of errors
143                         if (nextErrorLine instanceof lines_1.EndErrorLine) {
144                             addError(nextErrorLine, errorStartPos, nextLineNo);
145                             break;
146                         }
147                     }
148                 }
149             }
150         }
151     });
152     lintErrors.sort(lintError_1.errorComparator);
153     return lintErrors;
154 }
155 exports.parseErrorsFromMarkup = parseErrorsFromMarkup;
156 /**
157  * Process `message` as follows:
158  * - search `substitutions` for an exact match and return the substitution
159  * - try to format the message when it looks like: name % ('substitution1' [, "substitution2" [, ...]])
160  * - or return it unchanged
161  */
162 function substituteMessage(templates, message) {
163     var substitution = templates.get(message);
164     if (substitution !== undefined) {
165         return substitution;
166     }
167     return formatMessage(templates, message);
168 }
169 /**
170  * Tries to format the message when it has the correct format or returns it unchanged:  name % ('substitution1' [, "substitution2" [, ...]])
171  * Where `name` is the name of a message substitution that is used as template.
172  * If `name` is not found in `templates`, `message` is returned unchanged.
173  */
174 function formatMessage(templates, message) {
175     var formatMatch = /^([-\w]+) % \((.+)\)$/.exec(message);
176     if (formatMatch !== null) {
177         var template = templates.get(formatMatch[1]);
178         if (template !== undefined) {
179             var formatArgs = parseFormatArguments(formatMatch[2]);
180             if (formatArgs !== undefined) {
181                 message = util_1.format.apply(void 0, [template].concat(formatArgs));
182             }
183         }
184     }
185     return message;
186 }
187 /**
188  * Parse a list of comma separated string literals.
189  * This function bails out if it sees something unexpected.
190  * Whitespace between tokens is ignored.
191  * Trailing comma is allowed.
192  */
193 function parseFormatArguments(text) {
194     if (scanner === undefined) {
195         // once the scanner is created, it is cached for subsequent calls
196         scanner = ts.createScanner(ts.ScriptTarget.Latest, false);
197     }
198     scanner.setText(text);
199     var result = [];
200     var expectValue = true;
201     for (var token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) {
202         if (token === ts.SyntaxKind.StringLiteral) {
203             if (!expectValue) {
204                 return undefined;
205             }
206             result.push(scanner.getTokenValue());
207             expectValue = false;
208         }
209         else if (token === ts.SyntaxKind.CommaToken) {
210             if (expectValue) {
211                 return undefined;
212             }
213             expectValue = true;
214         }
215         else if (token !== ts.SyntaxKind.WhitespaceTrivia) {
216             // only ignore whitespace, other trivia like comments makes this function bail out
217             return undefined;
218         }
219     }
220     return result.length === 0 ? undefined : result;
221 }
222 function createMarkupFromErrors(fileName, code, lintErrors) {
223     lintErrors.sort(lintError_1.errorComparator);
224     var codeText = code.split("\n");
225     var errorLinesForCodeText = codeText.map(function () { return []; });
226     for (var _i = 0, lintErrors_1 = lintErrors; _i < lintErrors_1.length; _i++) {
227         var error = lintErrors_1[_i];
228         var startPos = error.startPos, endPos = error.endPos, message = error.message;
229         if (startPos.line === endPos.line) {
230             // single line error
231             errorLinesForCodeText[startPos.line].push(new lines_1.EndErrorLine(startPos.col, endPos.col, message));
232         }
233         else {
234             // multiline error
235             errorLinesForCodeText[startPos.line].push(new lines_1.MultilineErrorLine(startPos.col));
236             for (var lineNo = startPos.line + 1; lineNo < endPos.line; ++lineNo) {
237                 errorLinesForCodeText[lineNo].push(new lines_1.MultilineErrorLine(0));
238             }
239             errorLinesForCodeText[endPos.line].push(new lines_1.EndErrorLine(0, endPos.col, message));
240         }
241     }
242     return utils_1.flatMap(codeText, function (line, i) { return [
243         line
244     ].concat(utils_1.mapDefined(errorLinesForCodeText[i], function (err) { return lines_1.printLine(fileName, err, line); })); }).join("\n");
245 }
246 exports.createMarkupFromErrors = createMarkupFromErrors;
247 /* tslint:enable:object-literal-sort-keys */
248 function createCodeLineNoToErrorsMap(lines) {
249     var errorLinesForCodeLine = [];
250     for (var _i = 0, lines_3 = lines; _i < lines_3.length; _i++) {
251         var line = lines_3[_i];
252         if (line instanceof lines_1.CodeLine) {
253             errorLinesForCodeLine.push([]);
254         }
255         else if (line instanceof lines_1.ErrorLine) {
256             errorLinesForCodeLine[errorLinesForCodeLine.length - 1].push(line);
257         }
258     }
259     return errorLinesForCodeLine;
260 }
261 function isValidErrorMarkupContinuation(errorLinesForCodeLines, lineNo) {
262     return (lineNo < errorLinesForCodeLines.length &&
263         errorLinesForCodeLines[lineNo].length !== 0 &&
264         errorLinesForCodeLines[lineNo][0].startCol === 0);
265 }