aboutsummaryrefslogtreecommitdiff
path: root/node_modules/tslint/lib/rules/indentRule.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-08-14 05:01:11 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-08-14 05:02:09 +0200
commit363723fc84f7b8477592e0105aeb331ec9a017af (patch)
tree29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/tslint/lib/rules/indentRule.js
parent5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff)
node_modules
Diffstat (limited to 'node_modules/tslint/lib/rules/indentRule.js')
-rw-r--r--node_modules/tslint/lib/rules/indentRule.js223
1 files changed, 84 insertions, 139 deletions
diff --git a/node_modules/tslint/lib/rules/indentRule.js b/node_modules/tslint/lib/rules/indentRule.js
index 7d133a13b..7aa3459ba 100644
--- a/node_modules/tslint/lib/rules/indentRule.js
+++ b/node_modules/tslint/lib/rules/indentRule.js
@@ -17,6 +17,7 @@
*/
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
+var tsutils_1 = require("tsutils");
var ts = require("typescript");
var Lint = require("../index");
var OPTION_USE_TABS = "tabs";
@@ -28,152 +29,96 @@ var Rule = (function (_super) {
function Rule() {
return _super !== null && _super.apply(this, arguments) || this;
}
+ /* tslint:enable:object-literal-sort-keys */
+ Rule.FAILURE_STRING = function (expected) {
+ return expected + " indentation expected";
+ };
Rule.prototype.apply = function (sourceFile) {
- return this.applyWithWalker(new IndentWalker(sourceFile, this.getOptions()));
+ var options = parseOptions(this.ruleArguments);
+ return options === undefined ? [] : this.applyWithFunction(sourceFile, walk, options);
+ };
+ /* tslint:disable:object-literal-sort-keys */
+ Rule.metadata = {
+ ruleName: "indent",
+ description: "Enforces indentation with tabs or spaces.",
+ rationale: (_a = ["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation."], _a.raw = ["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation."], Lint.Utils.dedent(_a)),
+ optionsDescription: (_b = ["\n One of the following arguments must be provided:\n\n * `", "` enforces consistent spaces.\n * `", "` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * `", "` enforces 2 space indentation.\n * `", "` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n "], _b.raw = ["\n One of the following arguments must be provided:\n\n * \\`", "\\` enforces consistent spaces.\n * \\`", "\\` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * \\`", "\\` enforces 2 space indentation.\n * \\`", "\\` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n "], Lint.Utils.dedent(_b, OPTION_USE_SPACES, OPTION_USE_TABS, OPTION_INDENT_SIZE_2.toString(), OPTION_INDENT_SIZE_4.toString())),
+ options: {
+ type: "array",
+ items: [
+ {
+ type: "string",
+ enum: [OPTION_USE_TABS, OPTION_USE_SPACES],
+ },
+ {
+ type: "number",
+ enum: [OPTION_INDENT_SIZE_2, OPTION_INDENT_SIZE_4],
+ },
+ ],
+ minLength: 0,
+ maxLength: 5,
+ },
+ optionExamples: [
+ [true, OPTION_USE_SPACES],
+ [true, OPTION_USE_SPACES, OPTION_INDENT_SIZE_4],
+ [true, OPTION_USE_TABS, OPTION_INDENT_SIZE_2],
+ ],
+ type: "maintainability",
+ typescriptOnly: false,
};
return Rule;
}(Lint.Rules.AbstractRule));
-/* tslint:disable:object-literal-sort-keys */
-Rule.metadata = {
- ruleName: "indent",
- description: "Enforces indentation with tabs or spaces.",
- rationale: (_a = ["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation."], _a.raw = ["\n Using only one of tabs or spaces for indentation leads to more consistent editor behavior,\n cleaner diffs in version control, and easier programmatic manipulation."], Lint.Utils.dedent(_a)),
- optionsDescription: (_b = ["\n One of the following arguments must be provided:\n\n * `", "` enforces consistent spaces.\n * `", "` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * `", "` enforces 2 space indentation.\n * `", "` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n "], _b.raw = ["\n One of the following arguments must be provided:\n\n * \\`", "\\` enforces consistent spaces.\n * \\`", "\\` enforces consistent tabs.\n\n A second optional argument specifies indentation size:\n\n * \\`", "\\` enforces 2 space indentation.\n * \\`", "\\` enforces 4 space indentation.\n\n Indentation size is required for auto-fixing, but not for rule checking.\n "], Lint.Utils.dedent(_b, OPTION_USE_SPACES, OPTION_USE_TABS, OPTION_INDENT_SIZE_2.toString(), OPTION_INDENT_SIZE_4.toString())),
- options: {
- type: "array",
- items: [
- {
- type: "string",
- enum: [OPTION_USE_TABS, OPTION_USE_SPACES],
- },
- {
- type: "number",
- enum: [OPTION_INDENT_SIZE_2, OPTION_INDENT_SIZE_4],
- },
- ],
- minLength: 0,
- maxLength: 5,
- },
- optionExamples: [
- [true, OPTION_USE_SPACES],
- [true, OPTION_USE_SPACES, OPTION_INDENT_SIZE_4],
- [true, OPTION_USE_TABS, OPTION_INDENT_SIZE_2],
- ],
- type: "maintainability",
- typescriptOnly: false,
-};
-/* tslint:enable:object-literal-sort-keys */
-Rule.FAILURE_STRING_TABS = "tab indentation expected";
-Rule.FAILURE_STRING_SPACES = "space indentation expected";
exports.Rule = Rule;
-// visit every token and enforce that only the right character is used for indentation
-var IndentWalker = (function (_super) {
- tslib_1.__extends(IndentWalker, _super);
- function IndentWalker(sourceFile, options) {
- var _this = _super.call(this, sourceFile, options) || this;
- // fixer is only provided with the indent size arg
- if (_this.getOptions().length === 2 && typeof _this.getOptions()[1] === "number"
- && (_this.getOptions()[1] === OPTION_INDENT_SIZE_2 || _this.getOptions()[1] === OPTION_INDENT_SIZE_4)) {
- // tslint:disable-next-line:no-unsafe-any
- var size_1 = _this.getOptions()[1];
- var replaceRegExp_1;
- var replaceIndent_1;
- if (_this.hasOption(OPTION_USE_TABS)) {
- _this.regExp = new RegExp(" ".repeat(size_1));
- _this.failureString = Rule.FAILURE_STRING_TABS;
- // we want to find every group of `size` spaces, plus up to one 'incomplete' group
- replaceRegExp_1 = new RegExp("^( {" + size_1 + "})+( {1," + (size_1 - 1) + "})?", "g");
- replaceIndent_1 = "\t";
- }
- else if (_this.hasOption(OPTION_USE_SPACES)) {
- _this.regExp = new RegExp("\t");
- _this.failureString = size_1 + " " + Rule.FAILURE_STRING_SPACES;
- replaceRegExp_1 = new RegExp("\t", "g");
- replaceIndent_1 = " ".repeat(size_1);
- }
- _this.replacementFactory = function (lineStart, fullLeadingWhitespace) {
- return new Lint.Replacement(lineStart, fullLeadingWhitespace.length, fullLeadingWhitespace.replace(replaceRegExp_1, function (match) { return replaceIndent_1.repeat(Math.ceil(match.length / size_1)); }));
- };
+function parseOptions(ruleArguments) {
+ var type = ruleArguments[0];
+ if (type !== OPTION_USE_TABS && type !== OPTION_USE_SPACES) {
+ return undefined;
+ }
+ var size = ruleArguments[1];
+ return {
+ size: size === OPTION_INDENT_SIZE_2 || size === OPTION_INDENT_SIZE_4 ? size : undefined,
+ tabs: type === OPTION_USE_TABS,
+ };
+}
+function walk(ctx) {
+ var sourceFile = ctx.sourceFile, _a = ctx.options, tabs = _a.tabs, size = _a.size;
+ var regExp = tabs ? new RegExp(" ".repeat(size === undefined ? 1 : size)) : /\t/;
+ var failure = Rule.FAILURE_STRING(tabs ? "tab" : size === undefined ? "space" : size + " space");
+ for (var _i = 0, _b = tsutils_1.getLineRanges(sourceFile); _i < _b.length; _i++) {
+ var _c = _b[_i], pos = _c.pos, contentLength = _c.contentLength;
+ if (contentLength === 0) {
+ continue;
}
- else {
- if (_this.hasOption(OPTION_USE_TABS)) {
- _this.regExp = new RegExp(" ");
- _this.failureString = Rule.FAILURE_STRING_TABS;
- }
- else if (_this.hasOption(OPTION_USE_SPACES)) {
- _this.regExp = new RegExp("\t");
- _this.failureString = Rule.FAILURE_STRING_SPACES;
- }
- _this.replacementFactory = function () { return undefined; };
+ var line = sourceFile.text.substr(pos, contentLength);
+ var indentEnd = line.search(/\S/);
+ if (indentEnd === 0) {
+ continue;
}
- return _this;
- }
- IndentWalker.prototype.visitSourceFile = function (node) {
- if (!this.hasOption(OPTION_USE_TABS) && !this.hasOption(OPTION_USE_SPACES)) {
- // if we don't have either option, no need to check anything, and no need to call super, so just return
- return;
+ if (indentEnd === -1) {
+ indentEnd = contentLength;
}
- var endOfComment = -1;
- var endOfTemplateString = -1;
- var scanner = ts.createScanner(ts.ScriptTarget.ES5, false, ts.LanguageVariant.Standard, node.text);
- for (var _i = 0, _a = node.getLineStarts(); _i < _a.length; _i++) {
- var lineStart = _a[_i];
- if (lineStart < endOfComment || lineStart < endOfTemplateString) {
- // skip checking lines inside multi-line comments or template strings
- continue;
- }
- scanner.setTextPos(lineStart);
- var currentScannedType = scanner.scan();
- var fullLeadingWhitespace = "";
- var lastStartPos = -1;
- while (currentScannedType === ts.SyntaxKind.WhitespaceTrivia) {
- var startPos = scanner.getStartPos();
- if (startPos === lastStartPos) {
- break;
- }
- lastStartPos = startPos;
- fullLeadingWhitespace += scanner.getTokenText();
- currentScannedType = scanner.scan();
- }
- var commentRanges = ts.getTrailingCommentRanges(node.text, lineStart);
- if (commentRanges !== undefined) {
- endOfComment = commentRanges[commentRanges.length - 1].end;
- }
- else {
- var scanType = currentScannedType;
- // scan until we reach end of line, skipping over template strings
- while (scanType !== ts.SyntaxKind.NewLineTrivia && scanType !== ts.SyntaxKind.EndOfFileToken) {
- if (scanType === ts.SyntaxKind.NoSubstitutionTemplateLiteral) {
- // template string without expressions - skip past it
- endOfTemplateString = scanner.getStartPos() + scanner.getTokenText().length;
- }
- else if (scanType === ts.SyntaxKind.TemplateHead) {
- // find end of template string containing expressions...
- while (scanType !== ts.SyntaxKind.TemplateTail && scanType !== ts.SyntaxKind.EndOfFileToken) {
- scanType = scanner.scan();
- if (scanType === ts.SyntaxKind.CloseBraceToken) {
- scanType = scanner.reScanTemplateToken();
- }
- }
- // ... and skip past it
- endOfTemplateString = scanner.getStartPos() + scanner.getTokenText().length;
- }
- scanType = scanner.scan();
- }
- }
- switch (currentScannedType) {
- case ts.SyntaxKind.SingleLineCommentTrivia:
- case ts.SyntaxKind.MultiLineCommentTrivia:
- case ts.SyntaxKind.NewLineTrivia:
- // ignore lines that have comments before the first token
- continue;
- }
- if (this.regExp.test(fullLeadingWhitespace)) {
- this.addFailureAt(lineStart, fullLeadingWhitespace.length, this.failureString, this.replacementFactory(lineStart, fullLeadingWhitespace));
- }
+ var whitespace = line.slice(0, indentEnd);
+ if (!regExp.test(whitespace)) {
+ continue;
}
- // no need to call super to visit the rest of the nodes, so don't call super here
- };
- return IndentWalker;
-}(Lint.RuleWalker));
+ var token = tsutils_1.getTokenAtPosition(sourceFile, pos);
+ if (token.kind !== ts.SyntaxKind.JsxText &&
+ (pos >= token.getStart(sourceFile) || tsutils_1.isPositionInComment(sourceFile, pos, token))) {
+ continue;
+ }
+ ctx.addFailureAt(pos, indentEnd, failure, createFix(pos, whitespace, tabs, size));
+ }
+}
+function createFix(lineStart, fullLeadingWhitespace, tabs, size) {
+ if (size === undefined) {
+ return undefined;
+ }
+ var replaceRegExp = tabs
+ ? new RegExp("^( {" + size + "})+( {1," + (size - 1) + "})?", "g")
+ : /\t/g;
+ var replacement = fullLeadingWhitespace.replace(replaceRegExp, function (match) {
+ return (tabs ? "\t" : " ".repeat(size)).repeat(Math.ceil(match.length / size));
+ });
+ return new Lint.Replacement(lineStart, fullLeadingWhitespace.length, replacement);
+}
var _a, _b;