mirror of
https://github.com/JamesIves/github-pages-deploy-action.git
synced 2023-12-15 20:03:39 +08:00
651 lines
31 KiB
JavaScript
651 lines
31 KiB
JavaScript
"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 `fields-first` puts, in order of precedence:\n\n * fields before constructors before methods\n * static members before instance members\n * public members before protected members before private members\n\n `instance-sandwich` puts, in order of precedence:\n\n * fields before constructors before methods\n * static fields before instance fields, but static methods *after* instance methods\n * public members before protected members before private members\n\n `statics-first` puts, in order of precedence:\n\n * static members before instance members\n * public members before protected members before private members\n * fields before methods\n * instance fields before constructors before instance methods\n * fields before constructors before methods\n * public members before protected members before private members\n\n Note that these presets, despite looking similar, can have subtly different behavior due to the order in which these\n rules are specified. A fully expanded ordering can be found in the PRESETS constant in\n https://github.com/palantir/tslint/blob/master/src/rules/memberOrderingRule.ts.\n (You may need to check the version of the file corresponding to your version of tslint.)\n\n Alternatively, the value for `order` may 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 \\`fields-first\\` puts, in order of precedence:\n\n * fields before constructors before methods\n * static members before instance members\n * public members before protected members before private members\n\n \\`instance-sandwich\\` puts, in order of precedence:\n\n * fields before constructors before methods\n * static fields before instance fields, but static methods *after* instance methods\n * public members before protected members before private members\n\n \\`statics-first\\` puts, in order of precedence:\n\n * static members before instance members\n * public members before protected members before private members\n * fields before methods\n * instance fields before constructors before instance methods\n * fields before constructors before methods\n * public members before protected members before private members\n\n Note that these presets, despite looking similar, can have subtly different behavior due to the order in which these\n rules are specified. A fully expanded ordering can be found in the PRESETS constant in\n https://github.com/palantir/tslint/blob/master/src/rules/memberOrderingRule.ts.\n (You may need to check the version of the file corresponding to your version of tslint.)\n\n Alternatively, the value for \\`order\\` may 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,
|
|
},
|
|
],
|
|
},
|
|
alphabetize: {
|
|
type: "boolean",
|
|
},
|
|
},
|
|
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",
|
|
],
|
|
alphabetize: true,
|
|
},
|
|
],
|
|
[
|
|
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 whether 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 {
|
|
alphabetize: firstOption[OPTION_ALPHABETIZE] === true,
|
|
order: categoryFromOption(firstOption[OPTION_ORDER]),
|
|
};
|
|
}
|
|
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;
|