.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / rules / memberOrderingRule.js
1 "use strict";
2 /**
3  * @license
4  * Copyright 2013 Palantir Technologies, Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 var tsutils_1 = require("tsutils");
21 var ts = require("typescript");
22 var error_1 = require("../error");
23 var Lint = require("../index");
24 var utils_1 = require("../utils");
25 var OPTION_ORDER = "order";
26 var OPTION_ALPHABETIZE = "alphabetize";
27 var MemberKind;
28 (function (MemberKind) {
29     MemberKind[MemberKind["publicStaticField"] = 0] = "publicStaticField";
30     MemberKind[MemberKind["publicStaticMethod"] = 1] = "publicStaticMethod";
31     MemberKind[MemberKind["protectedStaticField"] = 2] = "protectedStaticField";
32     MemberKind[MemberKind["protectedStaticMethod"] = 3] = "protectedStaticMethod";
33     MemberKind[MemberKind["privateStaticField"] = 4] = "privateStaticField";
34     MemberKind[MemberKind["privateStaticMethod"] = 5] = "privateStaticMethod";
35     MemberKind[MemberKind["publicInstanceField"] = 6] = "publicInstanceField";
36     MemberKind[MemberKind["protectedInstanceField"] = 7] = "protectedInstanceField";
37     MemberKind[MemberKind["privateInstanceField"] = 8] = "privateInstanceField";
38     MemberKind[MemberKind["publicConstructor"] = 9] = "publicConstructor";
39     MemberKind[MemberKind["protectedConstructor"] = 10] = "protectedConstructor";
40     MemberKind[MemberKind["privateConstructor"] = 11] = "privateConstructor";
41     MemberKind[MemberKind["publicInstanceMethod"] = 12] = "publicInstanceMethod";
42     MemberKind[MemberKind["protectedInstanceMethod"] = 13] = "protectedInstanceMethod";
43     MemberKind[MemberKind["privateInstanceMethod"] = 14] = "privateInstanceMethod";
44 })(MemberKind || (MemberKind = {}));
45 var PRESETS = new Map([
46     [
47         "fields-first",
48         [
49             "public-static-field",
50             "protected-static-field",
51             "private-static-field",
52             "public-instance-field",
53             "protected-instance-field",
54             "private-instance-field",
55             "constructor",
56             "public-static-method",
57             "protected-static-method",
58             "private-static-method",
59             "public-instance-method",
60             "protected-instance-method",
61             "private-instance-method",
62         ],
63     ],
64     [
65         "instance-sandwich",
66         [
67             "public-static-field",
68             "protected-static-field",
69             "private-static-field",
70             "public-instance-field",
71             "protected-instance-field",
72             "private-instance-field",
73             "constructor",
74             "public-instance-method",
75             "protected-instance-method",
76             "private-instance-method",
77             "public-static-method",
78             "protected-static-method",
79             "private-static-method",
80         ],
81     ],
82     [
83         "statics-first",
84         [
85             "public-static-field",
86             "public-static-method",
87             "protected-static-field",
88             "protected-static-method",
89             "private-static-field",
90             "private-static-method",
91             "public-instance-field",
92             "protected-instance-field",
93             "private-instance-field",
94             "constructor",
95             "public-instance-method",
96             "protected-instance-method",
97             "private-instance-method",
98         ],
99     ],
100 ]);
101 var PRESET_NAMES = Array.from(PRESETS.keys());
102 var allMemberKindNames = utils_1.mapDefined(Object.keys(MemberKind), function (key) {
103     var mk = MemberKind[key];
104     return typeof mk === "number"
105         ? MemberKind[mk].replace(/[A-Z]/g, function (cap) { return "-" + cap.toLowerCase(); })
106         : undefined;
107 });
108 function namesMarkdown(names) {
109     return names.map(function (name) { return "* `" + name + "`"; }).join("\n    ");
110 }
111 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);
112 var Rule = /** @class */ (function (_super) {
113     tslib_1.__extends(Rule, _super);
114     function Rule() {
115         return _super !== null && _super.apply(this, arguments) || this;
116     }
117     Rule.FAILURE_STRING_ALPHABETIZE = function (prevName, curName) {
118         return show(curName) + " should come alphabetically before " + show(prevName);
119         function show(s) {
120             return s === "" ? "Computed property" : "'" + s + "'";
121         }
122     };
123     /* tslint:enable:object-literal-sort-keys */
124     Rule.prototype.apply = function (sourceFile) {
125         var options;
126         try {
127             options = parseOptions(this.ruleArguments);
128         }
129         catch (e) {
130             error_1.showWarningOnce("Warning: " + this.ruleName + " - " + e.message);
131             return [];
132         }
133         return this.applyWithWalker(new MemberOrderingWalker(sourceFile, this.ruleName, options));
134     };
135     /* tslint:disable:object-literal-sort-keys */
136     Rule.metadata = {
137         ruleName: "member-ordering",
138         description: "Enforces member ordering.",
139         hasFix: true,
140         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        "]))),
141         optionsDescription: optionsDescription,
142         options: {
143             type: "object",
144             properties: {
145                 order: {
146                     oneOf: [
147                         {
148                             type: "string",
149                             enum: PRESET_NAMES,
150                         },
151                         {
152                             type: "array",
153                             items: {
154                                 type: "string",
155                                 enum: allMemberKindNames,
156                             },
157                             maxLength: 13,
158                         },
159                     ],
160                 },
161                 alphabetize: {
162                     type: "boolean",
163                 },
164             },
165             additionalProperties: false,
166         },
167         optionExamples: [
168             [true, { order: "fields-first" }],
169             [
170                 true,
171                 {
172                     order: [
173                         "public-static-field",
174                         "public-instance-field",
175                         "public-constructor",
176                         "private-static-field",
177                         "private-instance-field",
178                         "private-constructor",
179                         "public-instance-method",
180                         "protected-instance-method",
181                         "private-instance-method",
182                     ],
183                     alphabetize: true,
184                 },
185             ],
186             [
187                 true,
188                 {
189                     order: [
190                         {
191                             name: "static non-private",
192                             kinds: [
193                                 "public-static-field",
194                                 "protected-static-field",
195                                 "public-static-method",
196                                 "protected-static-method",
197                             ],
198                         },
199                         "constructor",
200                     ],
201                 },
202             ],
203         ],
204         type: "typescript",
205         typescriptOnly: false,
206     };
207     return Rule;
208 }(Lint.Rules.AbstractRule));
209 exports.Rule = Rule;
210 var MemberOrderingWalker = /** @class */ (function (_super) {
211     tslib_1.__extends(MemberOrderingWalker, _super);
212     function MemberOrderingWalker() {
213         var _this = _super !== null && _super.apply(this, arguments) || this;
214         _this.fixes = [];
215         return _this;
216     }
217     MemberOrderingWalker.prototype.walk = function (sourceFile) {
218         var _this = this;
219         var cb = function (node) {
220             // NB: iterate through children first!
221             ts.forEachChild(node, cb);
222             switch (node.kind) {
223                 case ts.SyntaxKind.ClassDeclaration:
224                 case ts.SyntaxKind.ClassExpression:
225                 case ts.SyntaxKind.InterfaceDeclaration:
226                 case ts.SyntaxKind.TypeLiteral:
227                     _this.checkMembers(node.members);
228             }
229         };
230         ts.forEachChild(sourceFile, cb);
231         // assign Replacements which have not been merged into surrounding ones to their RuleFailures.
232         this.fixes.forEach(function (_a) {
233             var failure = _a[0], replacement = _a[1];
234             failure.getFix().push(replacement);
235         });
236     };
237     /**
238      * Check whether the passed members adhere to the configured order. If not, RuleFailures are generated and a single
239      * Lint.Replacement is generated, which replaces the entire NodeArray with a correctly sorted one. The Replacement
240      * is not immediately added to a RuleFailure, as incorrectly sorted nodes can be nested (e.g. a class declaration
241      * in a method implementation), but instead temporarily stored in `this.fixes`. Nested Replacements are manually
242      * merged, as TSLint doesn't handle overlapping ones. For this reason it is important that the recursion happens
243      * before the checkMembers call in this.walk().
244      */
245     MemberOrderingWalker.prototype.checkMembers = function (members) {
246         var _this = this;
247         var prevRank = -1;
248         var prevName;
249         var failureExists = false;
250         for (var _i = 0, members_1 = members; _i < members_1.length; _i++) {
251             var member = members_1[_i];
252             var rank = this.memberRank(member);
253             if (rank === -1) {
254                 // no explicit ordering for this kind of node specified, so continue
255                 continue;
256             }
257             if (rank < prevRank) {
258                 var nodeType = this.rankName(rank);
259                 var prevNodeType = this.rankName(prevRank);
260                 var lowerRank = this.findLowerRank(members, rank);
261                 var locationHint = lowerRank !== -1
262                     ? "after " + this.rankName(lowerRank) + "s"
263                     : "at the beginning of the class/interface";
264                 var errorLine1 = "Declaration of " + nodeType + " not allowed after declaration of " + prevNodeType + ". " +
265                     ("Instead, this should come " + locationHint + ".");
266                 // add empty array as fix so we can add a replacement later. (fix itself is readonly)
267                 this.addFailureAtNode(member, errorLine1, []);
268                 failureExists = true;
269             }
270             else {
271                 if (this.options.alphabetize && member.name !== undefined) {
272                     if (rank !== prevRank) {
273                         // No alphabetical ordering between different ranks
274                         prevName = undefined;
275                     }
276                     var curName = nameString(member.name);
277                     if (prevName !== undefined && caseInsensitiveLess(curName, prevName)) {
278                         this.addFailureAtNode(member.name, Rule.FAILURE_STRING_ALPHABETIZE(this.findLowerName(members, rank, curName), curName), []);
279                         failureExists = true;
280                     }
281                     else {
282                         prevName = curName;
283                     }
284                 }
285                 // keep track of last good node
286                 prevRank = rank;
287             }
288         }
289         if (failureExists) {
290             var sortedMemberIndexes = members
291                 .map(function (_, i) { return i; })
292                 .sort(function (ai, bi) {
293                 var a = members[ai];
294                 var b = members[bi];
295                 // first, sort by member rank
296                 var rankDiff = _this.memberRank(a) - _this.memberRank(b);
297                 if (rankDiff !== 0) {
298                     return rankDiff;
299                 }
300                 // then lexicographically if alphabetize == true
301                 if (_this.options.alphabetize && a.name !== undefined && b.name !== undefined) {
302                     var aName = nameString(a.name);
303                     var bName = nameString(b.name);
304                     var nameDiff = aName.localeCompare(bName);
305                     if (nameDiff !== 0) {
306                         return nameDiff;
307                     }
308                 }
309                 // finally, sort by position in original NodeArray so the sort remains stable.
310                 return ai - bi;
311             });
312             var splits_1 = getSplitIndexes(members, this.sourceFile.text);
313             var sortedMembersText = sortedMemberIndexes.map(function (i) {
314                 var start = splits_1[i];
315                 var end = splits_1[i + 1];
316                 var nodeText = _this.sourceFile.text.substring(start, end);
317                 while (true) {
318                     // check if there are previous fixes which we need to merge into this one
319                     // if yes, remove it from the list so that we do not return overlapping Replacements
320                     var fixIndex = arrayFindLastIndex(_this.fixes, function (_a) {
321                         var r = _a[1];
322                         return r.start >= start && r.start + r.length <= end;
323                     });
324                     if (fixIndex === -1) {
325                         break;
326                     }
327                     var fix = _this.fixes.splice(fixIndex, 1)[0];
328                     var replacement = fix[1];
329                     nodeText = applyReplacementOffset(nodeText, replacement, start);
330                 }
331                 return nodeText;
332             });
333             // instead of assigning the fix immediately to the last failure, we temporarily store it in `this.fixes`,
334             // in case a containing node needs to be fixed too. We only "add" the fix to the last failure, although
335             // it fixes all failures in this NodeArray, as TSLint doesn't handle duplicate Replacements.
336             this.fixes.push([
337                 arrayLast(this.failures),
338                 Lint.Replacement.replaceFromTo(splits_1[0], arrayLast(splits_1), sortedMembersText.join("")),
339             ]);
340         }
341     };
342     /** Finds the lowest name higher than 'targetName'. */
343     MemberOrderingWalker.prototype.findLowerName = function (members, targetRank, targetName) {
344         for (var _i = 0, members_2 = members; _i < members_2.length; _i++) {
345             var member = members_2[_i];
346             if (member.name === undefined || this.memberRank(member) !== targetRank) {
347                 continue;
348             }
349             var name = nameString(member.name);
350             if (caseInsensitiveLess(targetName, name)) {
351                 return name;
352             }
353         }
354         throw new Error("Expected to find a name");
355     };
356     /** Finds the highest existing rank lower than `targetRank`. */
357     MemberOrderingWalker.prototype.findLowerRank = function (members, targetRank) {
358         var max = -1;
359         for (var _i = 0, members_3 = members; _i < members_3.length; _i++) {
360             var member = members_3[_i];
361             var rank = this.memberRank(member);
362             if (rank !== -1 && rank < targetRank) {
363                 max = Math.max(max, rank);
364             }
365         }
366         return max;
367     };
368     MemberOrderingWalker.prototype.memberRank = function (member) {
369         var optionName = getMemberKind(member);
370         if (optionName === undefined) {
371             return -1;
372         }
373         return this.options.order.findIndex(function (category) { return category.has(optionName); });
374     };
375     MemberOrderingWalker.prototype.rankName = function (rank) {
376         return this.options.order[rank].name;
377     };
378     return MemberOrderingWalker;
379 }(Lint.AbstractWalker));
380 function caseInsensitiveLess(a, b) {
381     return a.toLowerCase() < b.toLowerCase();
382 }
383 function memberKindForConstructor(access) {
384     return MemberKind[access + "Constructor"];
385 }
386 function memberKindForMethodOrField(access, membership, kind) {
387     return MemberKind[access + membership + kind];
388 }
389 var allAccess = ["public", "protected", "private"];
390 function memberKindFromName(name) {
391     var kind = MemberKind[Lint.Utils.camelize(name)];
392     return typeof kind === "number" ? [kind] : allAccess.map(addModifier);
393     function addModifier(modifier) {
394         var modifiedKind = MemberKind[Lint.Utils.camelize(modifier + "-" + name)];
395         if (typeof modifiedKind !== "number") {
396             throw new Error("Bad member kind: " + name);
397         }
398         return modifiedKind;
399     }
400 }
401 function getMemberKind(member) {
402     var accessLevel = tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.PrivateKeyword)
403         ? "private"
404         : tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.ProtectedKeyword)
405             ? "protected"
406             : "public";
407     switch (member.kind) {
408         case ts.SyntaxKind.Constructor:
409         case ts.SyntaxKind.ConstructSignature:
410             return memberKindForConstructor(accessLevel);
411         case ts.SyntaxKind.PropertyDeclaration:
412         case ts.SyntaxKind.PropertySignature:
413             return methodOrField(isFunctionLiteral(member.initializer));
414         case ts.SyntaxKind.MethodDeclaration:
415         case ts.SyntaxKind.MethodSignature:
416             return methodOrField(true);
417         default:
418             return undefined;
419     }
420     function methodOrField(isMethod) {
421         var membership = tsutils_1.hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword)
422             ? "Static"
423             : "Instance";
424         return memberKindForMethodOrField(accessLevel, membership, isMethod ? "Method" : "Field");
425     }
426 }
427 var MemberCategory = /** @class */ (function () {
428     function MemberCategory(name, kinds) {
429         this.name = name;
430         this.kinds = kinds;
431     }
432     MemberCategory.prototype.has = function (kind) {
433         return this.kinds.has(kind);
434     };
435     return MemberCategory;
436 }());
437 function parseOptions(options) {
438     var _a = getOptionsJson(options), orderJson = _a.order, alphabetize = _a.alphabetize;
439     var order = orderJson.map(function (cat) {
440         return typeof cat === "string"
441             ? new MemberCategory(cat.replace(/-/g, " "), new Set(memberKindFromName(cat)))
442             : new MemberCategory(cat.name, new Set(utils_1.flatMap(cat.kinds, memberKindFromName)));
443     });
444     return { order: order, alphabetize: alphabetize };
445 }
446 function getOptionsJson(allOptions) {
447     if (allOptions == undefined || allOptions.length === 0 || allOptions[0] == undefined) {
448         throw new Error("Got empty options");
449     }
450     var firstOption = allOptions[0];
451     if (typeof firstOption !== "object") {
452         // Undocumented direct string option. Deprecate eventually.
453         return { order: convertFromOldStyleOptions(allOptions), alphabetize: false }; // presume allOptions to be string[]
454     }
455     return {
456         alphabetize: firstOption[OPTION_ALPHABETIZE] === true,
457         order: categoryFromOption(firstOption[OPTION_ORDER]),
458     };
459 }
460 function categoryFromOption(orderOption) {
461     if (Array.isArray(orderOption)) {
462         return orderOption;
463     }
464     var preset = PRESETS.get(orderOption);
465     if (preset === undefined) {
466         throw new Error("Bad order: " + JSON.stringify(orderOption));
467     }
468     return preset;
469 }
470 /**
471  * Convert from undocumented old-style options.
472  * This is designed to mimic the old behavior and should be removed eventually.
473  */
474 function convertFromOldStyleOptions(options) {
475     var categories = [{ name: "member", kinds: allMemberKindNames }];
476     if (hasOption("variables-before-functions")) {
477         categories = splitOldStyleOptions(categories, function (kind) { return kind.includes("field"); }, "field", "method");
478     }
479     if (hasOption("static-before-instance")) {
480         categories = splitOldStyleOptions(categories, function (kind) { return kind.includes("static"); }, "static", "instance");
481     }
482     if (hasOption("public-before-private")) {
483         // 'protected' is considered public
484         categories = splitOldStyleOptions(categories, function (kind) { return !kind.includes("private"); }, "public", "private");
485     }
486     return categories;
487     function hasOption(x) {
488         return options.indexOf(x) !== -1;
489     }
490 }
491 function splitOldStyleOptions(categories, filter, a, b) {
492     var newCategories = [];
493     var _loop_1 = function (cat) {
494         var yes = [];
495         var no = [];
496         for (var _i = 0, _a = cat.kinds; _i < _a.length; _i++) {
497             var kind = _a[_i];
498             if (filter(kind)) {
499                 yes.push(kind);
500             }
501             else {
502                 no.push(kind);
503             }
504         }
505         var augmentName = function (s) {
506             if (a === "field") {
507                 // Replace "member" with "field"/"method" instead of augmenting.
508                 return s;
509             }
510             return s + " " + cat.name;
511         };
512         newCategories.push({ name: augmentName(a), kinds: yes });
513         newCategories.push({ name: augmentName(b), kinds: no });
514     };
515     for (var _i = 0, categories_1 = categories; _i < categories_1.length; _i++) {
516         var cat = categories_1[_i];
517         _loop_1(cat);
518     }
519     return newCategories;
520 }
521 function isFunctionLiteral(node) {
522     if (node === undefined) {
523         return false;
524     }
525     switch (node.kind) {
526         case ts.SyntaxKind.ArrowFunction:
527         case ts.SyntaxKind.FunctionExpression:
528             return true;
529         default:
530             return false;
531     }
532 }
533 function nameString(name) {
534     switch (name.kind) {
535         case ts.SyntaxKind.Identifier:
536         case ts.SyntaxKind.StringLiteral:
537         case ts.SyntaxKind.NumericLiteral:
538             return name.text;
539         default:
540             return "";
541     }
542 }
543 /**
544  * Returns the last element of an array. (Or undefined).
545  */
546 function arrayLast(array) {
547     return array[array.length - 1];
548 }
549 /**
550  * Array.prototype.findIndex, but the last index.
551  */
552 function arrayFindLastIndex(array, predicate) {
553     for (var i = array.length; i-- > 0;) {
554         if (predicate(array[i], i, array)) {
555             return i;
556         }
557     }
558     return -1;
559 }
560 /**
561  * Applies a Replacement to a part of the text which starts at offset.
562  * See also Replacement.apply
563  */
564 function applyReplacementOffset(content, replacement, offset) {
565     return (content.substring(0, replacement.start - offset) +
566         replacement.text +
567         content.substring(replacement.start - offset + replacement.length));
568 }
569 /**
570  * Get the indexes of the boundaries between nodes in the node array. The following points must be taken into account:
571  * - Trivia should stay with its corresponding node (comments on the same line following the token belong to the
572  *   previous token, the rest to the next).
573  * - Reordering the subtexts should not result in code being commented out due to being moved between a "//" and
574  *   the following newline.
575  * - The end of one node must be the start of the next, otherwise the intravening whitespace will be lost when
576  *   reordering.
577  *
578  * Hence, the boundaries are chosen to be _after_ the newline following the node, or the beginning of the next token,
579  * if that comes first.
580  */
581 function getSplitIndexes(members, text) {
582     var result = members.map(function (member) { return getNextSplitIndex(text, member.getFullStart()); });
583     result.push(getNextSplitIndex(text, arrayLast(members).getEnd()));
584     return result;
585 }
586 /**
587  * Calculates the index after the newline following pos, or the beginning of the next token, whichever comes first.
588  * See also getSplitIndexes.
589  * This method is a modified version of TypeScript's internal iterateCommentRanges function.
590  */
591 function getNextSplitIndex(text, pos) {
592     scan: while (pos >= 0 && pos < text.length) {
593         var ch = text.charCodeAt(pos);
594         switch (ch) {
595             case 13 /* carriageReturn */:
596                 if (text.charCodeAt(pos + 1) === 10 /* lineFeed */) {
597                     pos++;
598                 }
599             // falls through
600             case 10 /* lineFeed */:
601                 pos++;
602                 // split is after new line
603                 return pos;
604             case 9 /* tab */:
605             case 11 /* verticalTab */:
606             case 12 /* formFeed */:
607             case 32 /* space */:
608                 // skip whitespace
609                 pos++;
610                 continue;
611             case 47 /* slash */:
612                 var nextChar = text.charCodeAt(pos + 1);
613                 if (nextChar === 47 /* slash */ || nextChar === 42 /* asterisk */) {
614                     var isSingleLineComment = nextChar === 47 /* slash */;
615                     pos += 2;
616                     if (isSingleLineComment) {
617                         while (pos < text.length) {
618                             if (ts.isLineBreak(text.charCodeAt(pos))) {
619                                 // the comment ends here, go back to default logic to handle parsing new line and result
620                                 continue scan;
621                             }
622                             pos++;
623                         }
624                     }
625                     else {
626                         while (pos < text.length) {
627                             if (text.charCodeAt(pos) === 42 /* asterisk */ &&
628                                 text.charCodeAt(pos + 1) === 47 /* slash */) {
629                                 pos += 2;
630                                 continue scan;
631                             }
632                             pos++;
633                         }
634                     }
635                     // if we arrive here, it's because pos == text.length
636                     return pos;
637                 }
638                 break scan;
639             default:
640                 // skip whitespace:
641                 if (ch > 127 /* maxAsciiCharacter */ && ts.isWhiteSpaceLike(ch)) {
642                     pos++;
643                     continue;
644                 }
645                 break scan;
646         }
647     }
648     return pos;
649 }
650 var templateObject_1, templateObject_2;