diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:01:11 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-14 05:02:09 +0200 |
commit | 363723fc84f7b8477592e0105aeb331ec9a017af (patch) | |
tree | 29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/tslint/lib/verify | |
parent | 5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff) |
node_modules
Diffstat (limited to 'node_modules/tslint/lib/verify')
-rw-r--r-- | node_modules/tslint/lib/verify/lines.d.ts | 37 | ||||
-rw-r--r-- | node_modules/tslint/lib/verify/lines.js | 157 | ||||
-rw-r--r-- | node_modules/tslint/lib/verify/lintError.d.ts | 12 | ||||
-rw-r--r-- | node_modules/tslint/lib/verify/lintError.js | 40 | ||||
-rw-r--r-- | node_modules/tslint/lib/verify/parse.d.ts | 13 | ||||
-rw-r--r-- | node_modules/tslint/lib/verify/parse.js | 211 |
6 files changed, 470 insertions, 0 deletions
diff --git a/node_modules/tslint/lib/verify/lines.d.ts b/node_modules/tslint/lib/verify/lines.d.ts new file mode 100644 index 000000000..8d8820db7 --- /dev/null +++ b/node_modules/tslint/lib/verify/lines.d.ts @@ -0,0 +1,37 @@ +export declare class Line { +} +export declare class CodeLine extends Line { + contents: string; + constructor(contents: string); +} +export declare class MessageSubstitutionLine extends Line { + key: string; + message: string; + constructor(key: string, message: string); +} +export declare class ErrorLine extends Line { + startCol: number; + constructor(startCol: number); +} +export declare class MultilineErrorLine extends ErrorLine { + constructor(startCol: number); +} +export declare class EndErrorLine extends ErrorLine { + endCol: number; + message: string; + constructor(startCol: number, endCol: number, message: string); +} +export declare const ZERO_LENGTH_ERROR = "~nil"; +/** + * Maps a line of text from a .lint file to an appropriate Line object + */ +export declare function parseLine(text: string): Line; +/** + * 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 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. + */ +export declare function printLine(line: Line, code?: string): string | undefined; diff --git a/node_modules/tslint/lib/verify/lines.js b/node_modules/tslint/lib/verify/lines.js new file mode 100644 index 000000000..c95fd0f8a --- /dev/null +++ b/node_modules/tslint/lib/verify/lines.js @@ -0,0 +1,157 @@ +"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 tslib_1 = require("tslib"); +// Use classes here instead of interfaces because we want runtime type data +var Line = (function () { + function Line() { + } + return Line; +}()); +exports.Line = Line; +var CodeLine = (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 = (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 = (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 = (function (_super) { + tslib_1.__extends(MultilineErrorLine, _super); + function MultilineErrorLine(startCol) { + return _super.call(this, startCol) || this; + } + return MultilineErrorLine; +}(ErrorLine)); +exports.MultilineErrorLine = MultilineErrorLine; +var EndErrorLine = (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 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(line, code) { + if (line instanceof ErrorLine) { + if (code == null) { + throw new Error("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 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; diff --git a/node_modules/tslint/lib/verify/lintError.d.ts b/node_modules/tslint/lib/verify/lintError.d.ts new file mode 100644 index 000000000..c00b4b535 --- /dev/null +++ b/node_modules/tslint/lib/verify/lintError.d.ts @@ -0,0 +1,12 @@ +import { Error } from "../error"; +export interface PositionInFile { + line: number; + col: number; +} +export interface LintError { + startPos: PositionInFile; + endPos: PositionInFile; + message: string; +} +export declare function errorComparator(err1: LintError, err2: LintError): number; +export declare function lintSyntaxError(message: string): Error; diff --git a/node_modules/tslint/lib/verify/lintError.js b/node_modules/tslint/lib/verify/lintError.js new file mode 100644 index 000000000..d784537c1 --- /dev/null +++ b/node_modules/tslint/lib/verify/lintError.js @@ -0,0 +1,40 @@ +"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 error_1 = require("../error"); +function errorComparator(err1, err2) { + if (err1.startPos.line !== err2.startPos.line) { + return err1.startPos.line - err2.startPos.line; + } + else if (err1.startPos.col !== err2.startPos.col) { + return err1.startPos.col - err2.startPos.col; + } + else if (err1.endPos.line !== err2.endPos.line) { + return err1.endPos.line - err2.endPos.line; + } + else if (err1.endPos.col !== err2.endPos.col) { + return err1.endPos.col - err2.endPos.col; + } + else { + return err1.message.localeCompare(err2.message); + } +} +exports.errorComparator = errorComparator; +function lintSyntaxError(message) { + return new error_1.Error("Lint File Syntax Error: " + message); +} +exports.lintSyntaxError = lintSyntaxError; diff --git a/node_modules/tslint/lib/verify/parse.d.ts b/node_modules/tslint/lib/verify/parse.d.ts new file mode 100644 index 000000000..db31418a1 --- /dev/null +++ b/node_modules/tslint/lib/verify/parse.d.ts @@ -0,0 +1,13 @@ +import { LintError } from "./lintError"; +export declare function getTypescriptVersionRequirement(text: string): string | undefined; +/** + * Takes the full text of a .lint file and returns the contents of the file + * with all error markup removed + */ +export declare function removeErrorMarkup(text: string): string; +/** + * Takes the full text of a .lint file and returns an array of LintErrors + * corresponding to the error markup in the file. + */ +export declare function parseErrorsFromMarkup(text: string): LintError[]; +export declare function createMarkupFromErrors(code: string, lintErrors: LintError[]): string; diff --git a/node_modules/tslint/lib/verify/parse.js b/node_modules/tslint/lib/verify/parse.js new file mode 100644 index 000000000..1d475efd3 --- /dev/null +++ b/node_modules/tslint/lib/verify/parse.js @@ -0,0 +1,211 @@ +"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 utils_1 = require("../utils"); +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)); + } + } + return utils_1.flatMap(codeText, function (line, i) { return [line].concat(utils_1.mapDefined(errorLinesForCodeText[i], function (err) { return lines_1.printLine(err, line); })); }).join("\n"); +} +exports.createMarkupFromErrors = createMarkupFromErrors; +/* tslint:enable:object-literal-sort-keys */ +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; +} |