diff options
Diffstat (limited to 'node_modules/tslint/lib/test/parse.js')
-rw-r--r-- | node_modules/tslint/lib/test/parse.js | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/node_modules/tslint/lib/test/parse.js b/node_modules/tslint/lib/test/parse.js new file mode 100644 index 000000000..5242878c4 --- /dev/null +++ b/node_modules/tslint/lib/test/parse.js @@ -0,0 +1,219 @@ +"use strict"; +/* + * Copyright 2016 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 }); +var ts = require("typescript"); +var util_1 = require("util"); +var lines_1 = require("./lines"); +var lintError_1 = require("./lintError"); +var scanner; +function getTypescriptVersionRequirement(text) { + var lines = text.split(/\r?\n/); + var firstLine = lines_1.parseLine(lines[0]); + if (firstLine instanceof lines_1.MessageSubstitutionLine && firstLine.key === "typescript") { + return firstLine.message; + } + return undefined; +} +exports.getTypescriptVersionRequirement = getTypescriptVersionRequirement; +/** + * Takes the full text of a .lint file and returns the contents of the file + * with all error markup removed + */ +function removeErrorMarkup(text) { + var textWithMarkup = text.split("\n"); + var lines = textWithMarkup.map(lines_1.parseLine); + var codeText = lines.filter(function (line) { return (line instanceof lines_1.CodeLine); }).map(function (line) { return line.contents; }); + return codeText.join("\n"); +} +exports.removeErrorMarkup = removeErrorMarkup; +/* tslint:disable:object-literal-sort-keys */ +/** + * Takes the full text of a .lint file and returns an array of LintErrors + * corresponding to the error markup in the file. + */ +function parseErrorsFromMarkup(text) { + var textWithMarkup = text.split("\n"); + var lines = textWithMarkup.map(lines_1.parseLine); + if (lines.length > 0 && !(lines[0] instanceof lines_1.CodeLine)) { + throw lintError_1.lintSyntaxError("text cannot start with an error mark line."); + } + var messageSubstitutionLines = lines.filter(function (l) { return l instanceof lines_1.MessageSubstitutionLine; }); + var messageSubstitutions = new Map(); + for (var _i = 0, messageSubstitutionLines_1 = messageSubstitutionLines; _i < messageSubstitutionLines_1.length; _i++) { + var _a = messageSubstitutionLines_1[_i], key = _a.key, message = _a.message; + messageSubstitutions.set(key, formatMessage(messageSubstitutions, message)); + } + // errorLineForCodeLine[5] contains all the ErrorLine objects associated with the 5th line of code, for example + var errorLinesForCodeLines = createCodeLineNoToErrorsMap(lines); + var lintErrors = []; + function addError(errorLine, errorStartPos, lineNo) { + lintErrors.push({ + startPos: errorStartPos, + endPos: { line: lineNo, col: errorLine.endCol }, + message: substituteMessage(messageSubstitutions, errorLine.message), + }); + } + // for each line of code... + errorLinesForCodeLines.forEach(function (errorLinesForLineOfCode, lineNo) { + // for each error marking on that line... + while (errorLinesForLineOfCode.length > 0) { + var errorLine = errorLinesForLineOfCode.shift(); + var errorStartPos = { line: lineNo, col: errorLine.startCol }; + // if the error starts and ends on this line, add it now to list of errors + if (errorLine instanceof lines_1.EndErrorLine) { + addError(errorLine, errorStartPos, lineNo); + // if the error is the start of a multiline error + } + else if (errorLine instanceof lines_1.MultilineErrorLine) { + // iterate through the MultilineErrorLines until we get to an EndErrorLine + for (var nextLineNo = lineNo + 1;; ++nextLineNo) { + if (!isValidErrorMarkupContinuation(errorLinesForCodeLines, nextLineNo)) { + throw lintError_1.lintSyntaxError("Error mark starting at " + errorStartPos.line + ":" + errorStartPos.col + " does not end correctly."); + } + else { + var nextErrorLine = errorLinesForCodeLines[nextLineNo].shift(); + // if end of multiline error, add it it list of errors + if (nextErrorLine instanceof lines_1.EndErrorLine) { + addError(nextErrorLine, errorStartPos, nextLineNo); + break; + } + } + } + } + } + }); + lintErrors.sort(lintError_1.errorComparator); + return lintErrors; +} +exports.parseErrorsFromMarkup = parseErrorsFromMarkup; +/** + * Process `message` as follows: + * - search `substitutions` for an exact match and return the substitution + * - try to format the message when it looks like: name % ('substitution1' [, "substitution2" [, ...]]) + * - or return it unchanged + */ +function substituteMessage(templates, message) { + var substitution = templates.get(message); + if (substitution !== undefined) { + return substitution; + } + return formatMessage(templates, message); +} +/** + * Tries to format the message when it has the correct format or returns it unchanged: name % ('substitution1' [, "substitution2" [, ...]]) + * Where `name` is the name of a message substitution that is used as template. + * If `name` is not found in `templates`, `message` is returned unchanged. + */ +function formatMessage(templates, message) { + var formatMatch = /^([-\w]+) % \((.+)\)$/.exec(message); + if (formatMatch !== null) { + var template = templates.get(formatMatch[1]); + if (template !== undefined) { + var formatArgs = parseFormatArguments(formatMatch[2]); + if (formatArgs !== undefined) { + message = util_1.format.apply(void 0, [template].concat(formatArgs)); + } + } + } + return message; +} +/** + * Parse a list of comma separated string literals. + * This function bails out if it sees something unexpected. + * Whitespace between tokens is ignored. + * Trailing comma is allowed. + */ +function parseFormatArguments(text) { + if (scanner === undefined) { + // once the scanner is created, it is cached for subsequent calls + scanner = ts.createScanner(ts.ScriptTarget.Latest, false); + } + scanner.setText(text); + var result = []; + var expectValue = true; + for (var token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) { + if (token === ts.SyntaxKind.StringLiteral) { + if (!expectValue) { + return undefined; + } + result.push(scanner.getTokenValue()); + expectValue = false; + } + else if (token === ts.SyntaxKind.CommaToken) { + if (expectValue) { + return undefined; + } + expectValue = true; + } + else if (token !== ts.SyntaxKind.WhitespaceTrivia) { + // only ignore whitespace, other trivia like comments makes this function bail out + return undefined; + } + } + return result.length === 0 ? undefined : result; +} +function createMarkupFromErrors(code, lintErrors) { + lintErrors.sort(lintError_1.errorComparator); + var codeText = code.split("\n"); + var errorLinesForCodeText = codeText.map(function () { return []; }); + for (var _i = 0, lintErrors_1 = lintErrors; _i < lintErrors_1.length; _i++) { + var error = lintErrors_1[_i]; + var startPos = error.startPos, endPos = error.endPos, message = error.message; + if (startPos.line === endPos.line) { + // single line error + errorLinesForCodeText[startPos.line].push(new lines_1.EndErrorLine(startPos.col, endPos.col, message)); + } + else { + // multiline error + errorLinesForCodeText[startPos.line].push(new lines_1.MultilineErrorLine(startPos.col)); + for (var lineNo = startPos.line + 1; lineNo < endPos.line; ++lineNo) { + errorLinesForCodeText[lineNo].push(new lines_1.MultilineErrorLine(0)); + } + errorLinesForCodeText[endPos.line].push(new lines_1.EndErrorLine(0, endPos.col, message)); + } + } + var finalText = combineCodeTextAndErrorLines(codeText, errorLinesForCodeText); + return finalText.join("\n"); +} +exports.createMarkupFromErrors = createMarkupFromErrors; +/* tslint:enable:object-literal-sort-keys */ +function combineCodeTextAndErrorLines(codeText, errorLinesForCodeText) { + return codeText.reduce(function (resultText, code, i) { + resultText.push(code); + var errorPrintLines = errorLinesForCodeText[i].map(function (line) { return lines_1.printLine(line, code); }).filter(function (line) { return line !== null; }); + resultText.push.apply(resultText, errorPrintLines); + return resultText; + }, []); +} +function createCodeLineNoToErrorsMap(lines) { + var errorLinesForCodeLine = []; + for (var _i = 0, lines_2 = lines; _i < lines_2.length; _i++) { + var line = lines_2[_i]; + if (line instanceof lines_1.CodeLine) { + errorLinesForCodeLine.push([]); + } + else if (line instanceof lines_1.ErrorLine) { + errorLinesForCodeLine[errorLinesForCodeLine.length - 1].push(line); + } + } + return errorLinesForCodeLine; +} +function isValidErrorMarkupContinuation(errorLinesForCodeLines, lineNo) { + return lineNo < errorLinesForCodeLines.length + && errorLinesForCodeLines[lineNo].length !== 0 + && errorLinesForCodeLines[lineNo][0].startCol === 0; +} |