diff options
Diffstat (limited to 'node_modules/tslint/lib/rules/memberOrderingRule.js')
-rw-r--r-- | node_modules/tslint/lib/rules/memberOrderingRule.js | 615 |
1 files changed, 0 insertions, 615 deletions
diff --git a/node_modules/tslint/lib/rules/memberOrderingRule.js b/node_modules/tslint/lib/rules/memberOrderingRule.js deleted file mode 100644 index a9752e3a4..000000000 --- a/node_modules/tslint/lib/rules/memberOrderingRule.js +++ /dev/null @@ -1,615 +0,0 @@ -"use strict"; -/** - * @license - * Copyright 2013 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"); -var tsutils_1 = require("tsutils"); -var ts = require("typescript"); -var error_1 = require("../error"); -var Lint = require("../index"); -var utils_1 = require("../utils"); -var OPTION_ORDER = "order"; -var OPTION_ALPHABETIZE = "alphabetize"; -var MemberKind; -(function (MemberKind) { - MemberKind[MemberKind["publicStaticField"] = 0] = "publicStaticField"; - MemberKind[MemberKind["publicStaticMethod"] = 1] = "publicStaticMethod"; - MemberKind[MemberKind["protectedStaticField"] = 2] = "protectedStaticField"; - MemberKind[MemberKind["protectedStaticMethod"] = 3] = "protectedStaticMethod"; - MemberKind[MemberKind["privateStaticField"] = 4] = "privateStaticField"; - MemberKind[MemberKind["privateStaticMethod"] = 5] = "privateStaticMethod"; - MemberKind[MemberKind["publicInstanceField"] = 6] = "publicInstanceField"; - MemberKind[MemberKind["protectedInstanceField"] = 7] = "protectedInstanceField"; - MemberKind[MemberKind["privateInstanceField"] = 8] = "privateInstanceField"; - MemberKind[MemberKind["publicConstructor"] = 9] = "publicConstructor"; - MemberKind[MemberKind["protectedConstructor"] = 10] = "protectedConstructor"; - MemberKind[MemberKind["privateConstructor"] = 11] = "privateConstructor"; - MemberKind[MemberKind["publicInstanceMethod"] = 12] = "publicInstanceMethod"; - MemberKind[MemberKind["protectedInstanceMethod"] = 13] = "protectedInstanceMethod"; - MemberKind[MemberKind["privateInstanceMethod"] = 14] = "privateInstanceMethod"; -})(MemberKind || (MemberKind = {})); -var PRESETS = new Map([ - ["fields-first", [ - "public-static-field", - "protected-static-field", - "private-static-field", - "public-instance-field", - "protected-instance-field", - "private-instance-field", - "constructor", - "public-static-method", - "protected-static-method", - "private-static-method", - "public-instance-method", - "protected-instance-method", - "private-instance-method", - ]], - ["instance-sandwich", [ - "public-static-field", - "protected-static-field", - "private-static-field", - "public-instance-field", - "protected-instance-field", - "private-instance-field", - "constructor", - "public-instance-method", - "protected-instance-method", - "private-instance-method", - "public-static-method", - "protected-static-method", - "private-static-method", - ]], - ["statics-first", [ - "public-static-field", - "public-static-method", - "protected-static-field", - "protected-static-method", - "private-static-field", - "private-static-method", - "public-instance-field", - "protected-instance-field", - "private-instance-field", - "constructor", - "public-instance-method", - "protected-instance-method", - "private-instance-method", - ]], -]); -var PRESET_NAMES = Array.from(PRESETS.keys()); -var allMemberKindNames = utils_1.mapDefined(Object.keys(MemberKind), function (key) { - var mk = MemberKind[key]; - return typeof mk === "number" ? MemberKind[mk].replace(/[A-Z]/g, function (cap) { return "-" + cap.toLowerCase(); }) : undefined; -}); -function namesMarkdown(names) { - return names.map(function (name) { return "* `" + name + "`"; }).join("\n "); -} -var optionsDescription = Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n One argument, which is an object, must be provided. It should contain an `order` property.\n The `order` property should have a value of one of the following strings:\n\n ", "\n\n Alternatively, the value for `order` maybe be an array consisting of the following strings:\n\n ", "\n\n You can also omit the access modifier to refer to \"public-\", \"protected-\", and \"private-\" all at once; for example, \"static-field\".\n\n You can also make your own categories by using an object instead of a string:\n\n {\n \"name\": \"static non-private\",\n \"kinds\": [\n \"public-static-field\",\n \"protected-static-field\",\n \"public-static-method\",\n \"protected-static-method\"\n ]\n }\n\n The '", "' option will enforce that members within the same category should be alphabetically sorted by name."], ["\n One argument, which is an object, must be provided. It should contain an \\`order\\` property.\n The \\`order\\` property should have a value of one of the following strings:\n\n ", "\n\n Alternatively, the value for \\`order\\` maybe be an array consisting of the following strings:\n\n ", "\n\n You can also omit the access modifier to refer to \"public-\", \"protected-\", and \"private-\" all at once; for example, \"static-field\".\n\n You can also make your own categories by using an object instead of a string:\n\n {\n \"name\": \"static non-private\",\n \"kinds\": [\n \"public-static-field\",\n \"protected-static-field\",\n \"public-static-method\",\n \"protected-static-method\"\n ]\n }\n\n The '", "' option will enforce that members within the same category should be alphabetically sorted by name."])), namesMarkdown(PRESET_NAMES), namesMarkdown(allMemberKindNames), OPTION_ALPHABETIZE); -var Rule = /** @class */ (function (_super) { - tslib_1.__extends(Rule, _super); - function Rule() { - return _super !== null && _super.apply(this, arguments) || this; - } - Rule.FAILURE_STRING_ALPHABETIZE = function (prevName, curName) { - return show(curName) + " should come alphabetically before " + show(prevName); - function show(s) { - return s === "" ? "Computed property" : "'" + s + "'"; - } - }; - /* tslint:enable:object-literal-sort-keys */ - Rule.prototype.apply = function (sourceFile) { - var options; - try { - options = parseOptions(this.ruleArguments); - } - catch (e) { - error_1.showWarningOnce("Warning: " + this.ruleName + " - " + e.message); - return []; - } - return this.applyWithWalker(new MemberOrderingWalker(sourceFile, this.ruleName, options)); - }; - /* tslint:disable:object-literal-sort-keys */ - Rule.metadata = { - ruleName: "member-ordering", - description: "Enforces member ordering.", - hasFix: true, - rationale: Lint.Utils.dedent(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n A consistent ordering for class members can make classes easier to read, navigate, and edit.\n\n A common opposite practice to `member-ordering` is to keep related groups of classes together.\n Instead of creating classes with multiple separate groups, consider splitting class responsibilities\n apart across multiple single-responsibility classes.\n "], ["\n A consistent ordering for class members can make classes easier to read, navigate, and edit.\n\n A common opposite practice to \\`member-ordering\\` is to keep related groups of classes together.\n Instead of creating classes with multiple separate groups, consider splitting class responsibilities\n apart across multiple single-responsibility classes.\n "]))), - optionsDescription: optionsDescription, - options: { - type: "object", - properties: { - order: { - oneOf: [ - { - type: "string", - enum: PRESET_NAMES, - }, - { - type: "array", - items: { - type: "string", - enum: allMemberKindNames, - }, - maxLength: 13, - }, - ], - }, - }, - additionalProperties: false, - }, - optionExamples: [ - [true, { order: "fields-first" }], - [true, { - order: [ - "public-static-field", - "public-instance-field", - "public-constructor", - "private-static-field", - "private-instance-field", - "private-constructor", - "public-instance-method", - "protected-instance-method", - "private-instance-method", - ], - }], - [true, { - order: [ - { - name: "static non-private", - kinds: [ - "public-static-field", - "protected-static-field", - "public-static-method", - "protected-static-method", - ], - }, - "constructor", - ], - }], - ], - type: "typescript", - typescriptOnly: false, - }; - return Rule; -}(Lint.Rules.AbstractRule)); -exports.Rule = Rule; -var MemberOrderingWalker = /** @class */ (function (_super) { - tslib_1.__extends(MemberOrderingWalker, _super); - function MemberOrderingWalker() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.fixes = []; - return _this; - } - MemberOrderingWalker.prototype.walk = function (sourceFile) { - var _this = this; - var cb = function (node) { - // NB: iterate through children first! - ts.forEachChild(node, cb); - switch (node.kind) { - case ts.SyntaxKind.ClassDeclaration: - case ts.SyntaxKind.ClassExpression: - case ts.SyntaxKind.InterfaceDeclaration: - case ts.SyntaxKind.TypeLiteral: - _this.checkMembers(node.members); - } - }; - ts.forEachChild(sourceFile, cb); - // assign Replacements which have not been merged into surrounding ones to their RuleFailures. - this.fixes.forEach(function (_a) { - var failure = _a[0], replacement = _a[1]; - failure.getFix().push(replacement); - }); - }; - /** - * Check wether the passed members adhere to the configured order. If not, RuleFailures are generated and a single - * Lint.Replacement is generated, which replaces the entire NodeArray with a correctly sorted one. The Replacement - * is not immediately added to a RuleFailure, as incorrectly sorted nodes can be nested (e.g. a class declaration - * in a method implementation), but instead temporarily stored in `this.fixes`. Nested Replacements are manually - * merged, as TSLint doesn't handle overlapping ones. For this reason it is important that the recursion happens - * before the checkMembers call in this.walk(). - */ - MemberOrderingWalker.prototype.checkMembers = function (members) { - var _this = this; - var prevRank = -1; - var prevName; - var failureExists = false; - for (var _i = 0, members_1 = members; _i < members_1.length; _i++) { - var member = members_1[_i]; - var rank = this.memberRank(member); - if (rank === -1) { - // no explicit ordering for this kind of node specified, so continue - continue; - } - if (rank < prevRank) { - var nodeType = this.rankName(rank); - var prevNodeType = this.rankName(prevRank); - var lowerRank = this.findLowerRank(members, rank); - var locationHint = lowerRank !== -1 - ? "after " + this.rankName(lowerRank) + "s" - : "at the beginning of the class/interface"; - var errorLine1 = "Declaration of " + nodeType + " not allowed after declaration of " + prevNodeType + ". " + - ("Instead, this should come " + locationHint + "."); - // add empty array as fix so we can add a replacement later. (fix itself is readonly) - this.addFailureAtNode(member, errorLine1, []); - failureExists = true; - } - else { - if (this.options.alphabetize && member.name !== undefined) { - if (rank !== prevRank) { - // No alphabetical ordering between different ranks - prevName = undefined; - } - var curName = nameString(member.name); - if (prevName !== undefined && caseInsensitiveLess(curName, prevName)) { - this.addFailureAtNode(member.name, Rule.FAILURE_STRING_ALPHABETIZE(this.findLowerName(members, rank, curName), curName), []); - failureExists = true; - } - else { - prevName = curName; - } - } - // keep track of last good node - prevRank = rank; - } - } - if (failureExists) { - var sortedMemberIndexes = members.map(function (_, i) { return i; }).sort(function (ai, bi) { - var a = members[ai]; - var b = members[bi]; - // first, sort by member rank - var rankDiff = _this.memberRank(a) - _this.memberRank(b); - if (rankDiff !== 0) { - return rankDiff; - } - // then lexicographically if alphabetize == true - if (_this.options.alphabetize && a.name !== undefined && b.name !== undefined) { - var aName = nameString(a.name); - var bName = nameString(b.name); - var nameDiff = aName.localeCompare(bName); - if (nameDiff !== 0) { - return nameDiff; - } - } - // finally, sort by position in original NodeArray so the sort remains stable. - return ai - bi; - }); - var splits_1 = getSplitIndexes(members, this.sourceFile.text); - var sortedMembersText = sortedMemberIndexes.map(function (i) { - var start = splits_1[i]; - var end = splits_1[i + 1]; - var nodeText = _this.sourceFile.text.substring(start, end); - while (true) { - // check if there are previous fixes which we need to merge into this one - // if yes, remove it from the list so that we do not return overlapping Replacements - var fixIndex = arrayFindLastIndex(_this.fixes, function (_a) { - var r = _a[1]; - return r.start >= start && r.start + r.length <= end; - }); - if (fixIndex === -1) { - break; - } - var fix = _this.fixes.splice(fixIndex, 1)[0]; - var replacement = fix[1]; - nodeText = applyReplacementOffset(nodeText, replacement, start); - } - return nodeText; - }); - // instead of assigning the fix immediately to the last failure, we temporarily store it in `this.fixes`, - // in case a containing node needs to be fixed too. We only "add" the fix to the last failure, although - // it fixes all failures in this NodeArray, as TSLint doesn't handle duplicate Replacements. - this.fixes.push([ - arrayLast(this.failures), - Lint.Replacement.replaceFromTo(splits_1[0], arrayLast(splits_1), sortedMembersText.join("")), - ]); - } - }; - /** Finds the lowest name higher than 'targetName'. */ - MemberOrderingWalker.prototype.findLowerName = function (members, targetRank, targetName) { - for (var _i = 0, members_2 = members; _i < members_2.length; _i++) { - var member = members_2[_i]; - if (member.name === undefined || this.memberRank(member) !== targetRank) { - continue; - } - var name = nameString(member.name); - if (caseInsensitiveLess(targetName, name)) { - return name; - } - } - throw new Error("Expected to find a name"); - }; - /** Finds the highest existing rank lower than `targetRank`. */ - MemberOrderingWalker.prototype.findLowerRank = function (members, targetRank) { - var max = -1; - for (var _i = 0, members_3 = members; _i < members_3.length; _i++) { - var member = members_3[_i]; - var rank = this.memberRank(member); - if (rank !== -1 && rank < targetRank) { - max = Math.max(max, rank); - } - } - return max; - }; - MemberOrderingWalker.prototype.memberRank = function (member) { - var optionName = getMemberKind(member); - if (optionName === undefined) { - return -1; - } - return this.options.order.findIndex(function (category) { return category.has(optionName); }); - }; - MemberOrderingWalker.prototype.rankName = function (rank) { - return this.options.order[rank].name; - }; - return MemberOrderingWalker; -}(Lint.AbstractWalker)); -function caseInsensitiveLess(a, b) { - return a.toLowerCase() < b.toLowerCase(); -} -function memberKindForConstructor(access) { - return MemberKind[access + "Constructor"]; -} -function memberKindForMethodOrField(access, membership, kind) { - return MemberKind[access + membership + kind]; -} -var allAccess = ["public", "protected", "private"]; -function memberKindFromName(name) { - var kind = MemberKind[Lint.Utils.camelize(name)]; - return typeof kind === "number" ? [kind] : allAccess.map(addModifier); - function addModifier(modifier) { - var modifiedKind = MemberKind[Lint.Utils.camelize(modifier + "-" + name)]; - if (typeof modifiedKind !== "number") { - throw new Error("Bad member kind: " + name); - } - return modifiedKind; - } -} -function getMemberKind(member) { - var accessLevel = tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.PrivateKeyword) ? "private" - : tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.ProtectedKeyword) ? "protected" - : "public"; - switch (member.kind) { - case ts.SyntaxKind.Constructor: - case ts.SyntaxKind.ConstructSignature: - return memberKindForConstructor(accessLevel); - case ts.SyntaxKind.PropertyDeclaration: - case ts.SyntaxKind.PropertySignature: - return methodOrField(isFunctionLiteral(member.initializer)); - case ts.SyntaxKind.MethodDeclaration: - case ts.SyntaxKind.MethodSignature: - return methodOrField(true); - default: - return undefined; - } - function methodOrField(isMethod) { - var membership = tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword) ? "Static" : "Instance"; - return memberKindForMethodOrField(accessLevel, membership, isMethod ? "Method" : "Field"); - } -} -var MemberCategory = /** @class */ (function () { - function MemberCategory(name, kinds) { - this.name = name; - this.kinds = kinds; - } - MemberCategory.prototype.has = function (kind) { return this.kinds.has(kind); }; - return MemberCategory; -}()); -function parseOptions(options) { - var _a = getOptionsJson(options), orderJson = _a.order, alphabetize = _a.alphabetize; - var order = orderJson.map(function (cat) { return typeof cat === "string" - ? new MemberCategory(cat.replace(/-/g, " "), new Set(memberKindFromName(cat))) - : new MemberCategory(cat.name, new Set(utils_1.flatMap(cat.kinds, memberKindFromName))); }); - return { order: order, alphabetize: alphabetize }; -} -function getOptionsJson(allOptions) { - if (allOptions == undefined || allOptions.length === 0 || allOptions[0] == undefined) { - throw new Error("Got empty options"); - } - var firstOption = allOptions[0]; - if (typeof firstOption !== "object") { - // Undocumented direct string option. Deprecate eventually. - return { order: convertFromOldStyleOptions(allOptions), alphabetize: false }; // presume allOptions to be string[] - } - return { order: categoryFromOption(firstOption[OPTION_ORDER]), alphabetize: firstOption[OPTION_ALPHABETIZE] === true }; -} -function categoryFromOption(orderOption) { - if (Array.isArray(orderOption)) { - return orderOption; - } - var preset = PRESETS.get(orderOption); - if (preset === undefined) { - throw new Error("Bad order: " + JSON.stringify(orderOption)); - } - return preset; -} -/** - * Convert from undocumented old-style options. - * This is designed to mimic the old behavior and should be removed eventually. - */ -function convertFromOldStyleOptions(options) { - var categories = [{ name: "member", kinds: allMemberKindNames }]; - if (hasOption("variables-before-functions")) { - categories = splitOldStyleOptions(categories, function (kind) { return kind.includes("field"); }, "field", "method"); - } - if (hasOption("static-before-instance")) { - categories = splitOldStyleOptions(categories, function (kind) { return kind.includes("static"); }, "static", "instance"); - } - if (hasOption("public-before-private")) { - // 'protected' is considered public - categories = splitOldStyleOptions(categories, function (kind) { return !kind.includes("private"); }, "public", "private"); - } - return categories; - function hasOption(x) { - return options.indexOf(x) !== -1; - } -} -function splitOldStyleOptions(categories, filter, a, b) { - var newCategories = []; - var _loop_1 = function (cat) { - var yes = []; - var no = []; - for (var _i = 0, _a = cat.kinds; _i < _a.length; _i++) { - var kind = _a[_i]; - if (filter(kind)) { - yes.push(kind); - } - else { - no.push(kind); - } - } - var augmentName = function (s) { - if (a === "field") { - // Replace "member" with "field"/"method" instead of augmenting. - return s; - } - return s + " " + cat.name; - }; - newCategories.push({ name: augmentName(a), kinds: yes }); - newCategories.push({ name: augmentName(b), kinds: no }); - }; - for (var _i = 0, categories_1 = categories; _i < categories_1.length; _i++) { - var cat = categories_1[_i]; - _loop_1(cat); - } - return newCategories; -} -function isFunctionLiteral(node) { - if (node === undefined) { - return false; - } - switch (node.kind) { - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.FunctionExpression: - return true; - default: - return false; - } -} -function nameString(name) { - switch (name.kind) { - case ts.SyntaxKind.Identifier: - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.NumericLiteral: - return name.text; - default: - return ""; - } -} -/** - * Returns the last element of an array. (Or undefined). - */ -function arrayLast(array) { - return array[array.length - 1]; -} -/** - * Array.prototype.findIndex, but the last index. - */ -function arrayFindLastIndex(array, predicate) { - for (var i = array.length; i-- > 0;) { - if (predicate(array[i], i, array)) { - return i; - } - } - return -1; -} -/** - * Applies a Replacement to a part of the text which starts at offset. - * See also Replacement.apply - */ -function applyReplacementOffset(content, replacement, offset) { - return content.substring(0, replacement.start - offset) - + replacement.text - + content.substring(replacement.start - offset + replacement.length); -} -/** - * Get the indexes of the boundaries between nodes in the node array. The following points must be taken into account: - * - Trivia should stay with its corresponding node (comments on the same line following the token belong to the - * previous token, the rest to the next). - * - Reordering the subtexts should not result in code being commented out due to being moved between a "//" and - * the following newline. - * - The end of one node must be the start of the next, otherwise the intravening whitespace will be lost when - * reordering. - * - * Hence, the boundaries are chosen to be _after_ the newline following the node, or the beginning of the next token, - * if that comes first. - */ -function getSplitIndexes(members, text) { - var result = members.map(function (member) { return getNextSplitIndex(text, member.getFullStart()); }); - result.push(getNextSplitIndex(text, arrayLast(members).getEnd())); - return result; -} -/** - * Calculates the index after the newline following pos, or the beginning of the next token, whichever comes first. - * See also getSplitIndexes. - * This method is a modified version of TypeScript's internal iterateCommentRanges function. - */ -function getNextSplitIndex(text, pos) { - scan: while (pos >= 0 && pos < text.length) { - var ch = text.charCodeAt(pos); - switch (ch) { - case 13 /* carriageReturn */: - if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) { - pos++; - } - // falls through - case 10 /* lineFeed */: - pos++; - // split is after new line - return pos; - case 9 /* tab */: - case 11 /* verticalTab */: - case 12 /* formFeed */: - case 32 /* space */: - // skip whitespace - pos++; - continue; - case 47 /* slash */: - var nextChar = text.charCodeAt(pos + 1); - if (nextChar === 47 /* slash */ || nextChar === 42 /* asterisk */) { - var isSingleLineComment = nextChar === 47 /* slash */; - pos += 2; - if (isSingleLineComment) { - while (pos < text.length) { - if (ts.isLineBreak(text.charCodeAt(pos))) { - // the comment ends here, go back to default logic to handle parsing new line and result - continue scan; - } - pos++; - } - } - else { - while (pos < text.length) { - if (text.charCodeAt(pos) === 42 /* asterisk */ && text.charCodeAt(pos + 1) === 47 /* slash */) { - pos += 2; - continue scan; - } - pos++; - } - } - // if we arrive here, it's because pos == text.length - return pos; - } - break scan; - default: - // skip whitespace: - if (ch > 127 /* maxAsciiCharacter */ && (ts.isWhiteSpaceLike(ch))) { - pos++; - continue; - } - break scan; - } - } - return pos; -} -var templateObject_1, templateObject_2; |