1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5 | }) : (function(o, m, k, k2) {
|
6 | if (k2 === undefined) k2 = k;
|
7 | o[k2] = m[k];
|
8 | }));
|
9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11 | }) : function(o, v) {
|
12 | o["default"] = v;
|
13 | });
|
14 | var __importStar = (this && this.__importStar) || function (mod) {
|
15 | if (mod && mod.__esModule) return mod;
|
16 | var result = {};
|
17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18 | __setModuleDefault(result, mod);
|
19 | return result;
|
20 | };
|
21 | Object.defineProperty(exports, "__esModule", { value: true });
|
22 | exports.defaultOrder = void 0;
|
23 | const utils_1 = require("@typescript-eslint/utils");
|
24 | const util = __importStar(require("../util"));
|
25 | const neverConfig = {
|
26 | type: 'string',
|
27 | enum: ['never'],
|
28 | };
|
29 | const arrayConfig = (memberTypes) => ({
|
30 | type: 'array',
|
31 | items: {
|
32 | enum: memberTypes,
|
33 | },
|
34 | });
|
35 | const objectConfig = (memberTypes) => ({
|
36 | type: 'object',
|
37 | properties: {
|
38 | memberTypes: {
|
39 | oneOf: [arrayConfig(memberTypes), neverConfig],
|
40 | },
|
41 | order: {
|
42 | type: 'string',
|
43 | enum: ['alphabetically', 'alphabetically-case-insensitive', 'as-written'],
|
44 | },
|
45 | },
|
46 | additionalProperties: false,
|
47 | });
|
48 | exports.defaultOrder = [
|
49 |
|
50 | 'signature',
|
51 | 'call-signature',
|
52 |
|
53 | 'public-static-field',
|
54 | 'protected-static-field',
|
55 | 'private-static-field',
|
56 | 'public-decorated-field',
|
57 | 'protected-decorated-field',
|
58 | 'private-decorated-field',
|
59 | 'public-instance-field',
|
60 | 'protected-instance-field',
|
61 | 'private-instance-field',
|
62 | 'public-abstract-field',
|
63 | 'protected-abstract-field',
|
64 | 'private-abstract-field',
|
65 | 'public-field',
|
66 | 'protected-field',
|
67 | 'private-field',
|
68 | 'static-field',
|
69 | 'instance-field',
|
70 | 'abstract-field',
|
71 | 'decorated-field',
|
72 | 'field',
|
73 |
|
74 | 'public-constructor',
|
75 | 'protected-constructor',
|
76 | 'private-constructor',
|
77 | 'constructor',
|
78 |
|
79 | 'public-static-get',
|
80 | 'protected-static-get',
|
81 | 'private-static-get',
|
82 | 'public-decorated-get',
|
83 | 'protected-decorated-get',
|
84 | 'private-decorated-get',
|
85 | 'public-instance-get',
|
86 | 'protected-instance-get',
|
87 | 'private-instance-get',
|
88 | 'public-abstract-get',
|
89 | 'protected-abstract-get',
|
90 | 'private-abstract-get',
|
91 | 'public-get',
|
92 | 'protected-get',
|
93 | 'private-get',
|
94 | 'static-get',
|
95 | 'instance-get',
|
96 | 'abstract-get',
|
97 | 'decorated-get',
|
98 | 'get',
|
99 |
|
100 | 'public-static-set',
|
101 | 'protected-static-set',
|
102 | 'private-static-set',
|
103 | 'public-decorated-set',
|
104 | 'protected-decorated-set',
|
105 | 'private-decorated-set',
|
106 | 'public-instance-set',
|
107 | 'protected-instance-set',
|
108 | 'private-instance-set',
|
109 | 'public-abstract-set',
|
110 | 'protected-abstract-set',
|
111 | 'private-abstract-set',
|
112 | 'public-set',
|
113 | 'protected-set',
|
114 | 'private-set',
|
115 | 'static-set',
|
116 | 'instance-set',
|
117 | 'abstract-set',
|
118 | 'decorated-set',
|
119 | 'set',
|
120 |
|
121 | 'public-static-method',
|
122 | 'protected-static-method',
|
123 | 'private-static-method',
|
124 | 'public-decorated-method',
|
125 | 'protected-decorated-method',
|
126 | 'private-decorated-method',
|
127 | 'public-instance-method',
|
128 | 'protected-instance-method',
|
129 | 'private-instance-method',
|
130 | 'public-abstract-method',
|
131 | 'protected-abstract-method',
|
132 | 'private-abstract-method',
|
133 | 'public-method',
|
134 | 'protected-method',
|
135 | 'private-method',
|
136 | 'static-method',
|
137 | 'instance-method',
|
138 | 'abstract-method',
|
139 | 'decorated-method',
|
140 | 'method',
|
141 | ];
|
142 | const allMemberTypes = [
|
143 | 'signature',
|
144 | 'field',
|
145 | 'method',
|
146 | 'call-signature',
|
147 | 'constructor',
|
148 | 'get',
|
149 | 'set',
|
150 | ].reduce((all, type) => {
|
151 | all.push(type);
|
152 | ['public', 'protected', 'private'].forEach(accessibility => {
|
153 | if (type !== 'signature') {
|
154 | all.push(`${accessibility}-${type}`);
|
155 | }
|
156 |
|
157 | if (type === 'field' ||
|
158 | type === 'method' ||
|
159 | type === 'get' ||
|
160 | type === 'set') {
|
161 | const decoratedMemberType = `${accessibility}-decorated-${type}`;
|
162 | const decoratedMemberTypeNoAccessibility = `decorated-${type}`;
|
163 | if (!all.includes(decoratedMemberType)) {
|
164 | all.push(decoratedMemberType);
|
165 | }
|
166 | if (!all.includes(decoratedMemberTypeNoAccessibility)) {
|
167 | all.push(decoratedMemberTypeNoAccessibility);
|
168 | }
|
169 | }
|
170 | if (type !== 'constructor' && type !== 'signature') {
|
171 |
|
172 | ['static', 'instance', 'abstract'].forEach(scope => {
|
173 | if (!all.includes(`${scope}-${type}`)) {
|
174 | all.push(`${scope}-${type}`);
|
175 | }
|
176 | all.push(`${accessibility}-${scope}-${type}`);
|
177 | });
|
178 | }
|
179 | });
|
180 | return all;
|
181 | }, []);
|
182 | const functionExpressions = [
|
183 | utils_1.AST_NODE_TYPES.FunctionExpression,
|
184 | utils_1.AST_NODE_TYPES.ArrowFunctionExpression,
|
185 | ];
|
186 |
|
187 |
|
188 |
|
189 |
|
190 |
|
191 | function getNodeType(node) {
|
192 | switch (node.type) {
|
193 | case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
|
194 | case utils_1.AST_NODE_TYPES.MethodDefinition:
|
195 | return node.kind;
|
196 | case utils_1.AST_NODE_TYPES.TSMethodSignature:
|
197 | return 'method';
|
198 | case utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration:
|
199 | return 'call-signature';
|
200 | case utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration:
|
201 | return 'constructor';
|
202 | case utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition:
|
203 | return 'field';
|
204 | case utils_1.AST_NODE_TYPES.PropertyDefinition:
|
205 | return node.value && functionExpressions.includes(node.value.type)
|
206 | ? 'method'
|
207 | : 'field';
|
208 | case utils_1.AST_NODE_TYPES.TSPropertySignature:
|
209 | return 'field';
|
210 | case utils_1.AST_NODE_TYPES.TSIndexSignature:
|
211 | return 'signature';
|
212 | default:
|
213 | return null;
|
214 | }
|
215 | }
|
216 |
|
217 |
|
218 |
|
219 | function getMemberRawName(member, sourceCode) {
|
220 | const { name, type } = util.getNameFromMember(member, sourceCode);
|
221 | if (type === util.MemberNameType.Quoted) {
|
222 | return name.substr(1, name.length - 2);
|
223 | }
|
224 | if (type === util.MemberNameType.Private) {
|
225 | return name.substr(1);
|
226 | }
|
227 | return name;
|
228 | }
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | function getMemberName(node, sourceCode) {
|
236 | switch (node.type) {
|
237 | case utils_1.AST_NODE_TYPES.TSPropertySignature:
|
238 | case utils_1.AST_NODE_TYPES.TSMethodSignature:
|
239 | case utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition:
|
240 | case utils_1.AST_NODE_TYPES.PropertyDefinition:
|
241 | return getMemberRawName(node, sourceCode);
|
242 | case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition:
|
243 | case utils_1.AST_NODE_TYPES.MethodDefinition:
|
244 | return node.kind === 'constructor'
|
245 | ? 'constructor'
|
246 | : getMemberRawName(node, sourceCode);
|
247 | case utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration:
|
248 | return 'new';
|
249 | case utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration:
|
250 | return 'call';
|
251 | case utils_1.AST_NODE_TYPES.TSIndexSignature:
|
252 | return util.getNameFromIndexSignature(node);
|
253 | default:
|
254 | return null;
|
255 | }
|
256 | }
|
257 |
|
258 |
|
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 | function getRankOrder(memberGroups, orderConfig) {
|
270 | let rank = -1;
|
271 | const stack = memberGroups.slice();
|
272 | while (stack.length > 0 && rank === -1) {
|
273 | rank = orderConfig.indexOf(stack.shift());
|
274 | }
|
275 | return rank;
|
276 | }
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 | function getRank(node, orderConfig, supportsModifiers) {
|
284 | const type = getNodeType(node);
|
285 | if (type === null) {
|
286 |
|
287 | return orderConfig.length - 1;
|
288 | }
|
289 | const abstract = node.type === utils_1.AST_NODE_TYPES.TSAbstractPropertyDefinition ||
|
290 | node.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition;
|
291 | const scope = 'static' in node && node.static
|
292 | ? 'static'
|
293 | : abstract
|
294 | ? 'abstract'
|
295 | : 'instance';
|
296 | const accessibility = 'accessibility' in node && node.accessibility
|
297 | ? node.accessibility
|
298 | : 'public';
|
299 |
|
300 | const memberGroups = [];
|
301 | if (supportsModifiers) {
|
302 | const decorated = 'decorators' in node && node.decorators.length > 0;
|
303 | if (decorated &&
|
304 | (type === 'field' ||
|
305 | type === 'method' ||
|
306 | type === 'get' ||
|
307 | type === 'set')) {
|
308 | memberGroups.push(`${accessibility}-decorated-${type}`);
|
309 | memberGroups.push(`decorated-${type}`);
|
310 | }
|
311 | if (type !== 'constructor') {
|
312 |
|
313 | memberGroups.push(`${accessibility}-${scope}-${type}`);
|
314 | memberGroups.push(`${scope}-${type}`);
|
315 | }
|
316 | memberGroups.push(`${accessibility}-${type}`);
|
317 | }
|
318 | memberGroups.push(type);
|
319 | return getRankOrder(memberGroups, orderConfig);
|
320 | }
|
321 |
|
322 |
|
323 |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 | function getLowestRank(ranks, target, order) {
|
341 | let lowest = ranks[ranks.length - 1];
|
342 | ranks.forEach(rank => {
|
343 | if (rank > target) {
|
344 | lowest = Math.min(lowest, rank);
|
345 | }
|
346 | });
|
347 | return order[lowest].replace(/-/g, ' ');
|
348 | }
|
349 | exports.default = util.createRule({
|
350 | name: 'member-ordering',
|
351 | meta: {
|
352 | type: 'suggestion',
|
353 | docs: {
|
354 | description: 'Require a consistent member declaration order',
|
355 | recommended: false,
|
356 | },
|
357 | messages: {
|
358 | incorrectOrder: 'Member {{member}} should be declared before member {{beforeMember}}.',
|
359 | incorrectGroupOrder: 'Member {{name}} should be declared before all {{rank}} definitions.',
|
360 | },
|
361 | schema: [
|
362 | {
|
363 | type: 'object',
|
364 | properties: {
|
365 | default: {
|
366 | oneOf: [
|
367 | neverConfig,
|
368 | arrayConfig(allMemberTypes),
|
369 | objectConfig(allMemberTypes),
|
370 | ],
|
371 | },
|
372 | classes: {
|
373 | oneOf: [
|
374 | neverConfig,
|
375 | arrayConfig(allMemberTypes),
|
376 | objectConfig(allMemberTypes),
|
377 | ],
|
378 | },
|
379 | classExpressions: {
|
380 | oneOf: [
|
381 | neverConfig,
|
382 | arrayConfig(allMemberTypes),
|
383 | objectConfig(allMemberTypes),
|
384 | ],
|
385 | },
|
386 | interfaces: {
|
387 | oneOf: [
|
388 | neverConfig,
|
389 | arrayConfig(['signature', 'field', 'method', 'constructor']),
|
390 | objectConfig(['signature', 'field', 'method', 'constructor']),
|
391 | ],
|
392 | },
|
393 | typeLiterals: {
|
394 | oneOf: [
|
395 | neverConfig,
|
396 | arrayConfig(['signature', 'field', 'method', 'constructor']),
|
397 | objectConfig(['signature', 'field', 'method', 'constructor']),
|
398 | ],
|
399 | },
|
400 | },
|
401 | additionalProperties: false,
|
402 | },
|
403 | ],
|
404 | },
|
405 | defaultOptions: [
|
406 | {
|
407 | default: exports.defaultOrder,
|
408 | },
|
409 | ],
|
410 | create(context, [options]) {
|
411 | |
412 |
|
413 |
|
414 |
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 | function checkGroupSort(members, groupOrder, supportsModifiers) {
|
421 | const previousRanks = [];
|
422 | const memberGroups = [];
|
423 | let isCorrectlySorted = true;
|
424 |
|
425 | members.forEach(member => {
|
426 | const rank = getRank(member, groupOrder, supportsModifiers);
|
427 | const name = getMemberName(member, context.getSourceCode());
|
428 | const rankLastMember = previousRanks[previousRanks.length - 1];
|
429 | if (rank === -1) {
|
430 | return;
|
431 | }
|
432 |
|
433 | if (rank < rankLastMember) {
|
434 | context.report({
|
435 | node: member,
|
436 | messageId: 'incorrectGroupOrder',
|
437 | data: {
|
438 | name,
|
439 | rank: getLowestRank(previousRanks, rank, groupOrder),
|
440 | },
|
441 | });
|
442 | isCorrectlySorted = false;
|
443 | }
|
444 | else if (rank === rankLastMember) {
|
445 |
|
446 | memberGroups[memberGroups.length - 1].push(member);
|
447 | }
|
448 | else {
|
449 |
|
450 | previousRanks.push(rank);
|
451 | memberGroups.push([member]);
|
452 | }
|
453 | });
|
454 | return isCorrectlySorted ? memberGroups : null;
|
455 | }
|
456 | |
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 | function checkAlphaSort(members, caseSensitive) {
|
465 | let previousName = '';
|
466 | let isCorrectlySorted = true;
|
467 |
|
468 | members.forEach(member => {
|
469 | const name = getMemberName(member, context.getSourceCode());
|
470 |
|
471 | if (name) {
|
472 | if (caseSensitive
|
473 | ? name < previousName
|
474 | : name.toLowerCase() < previousName.toLowerCase()) {
|
475 | context.report({
|
476 | node: member,
|
477 | messageId: 'incorrectOrder',
|
478 | data: {
|
479 | member: name,
|
480 | beforeMember: previousName,
|
481 | },
|
482 | });
|
483 | isCorrectlySorted = false;
|
484 | }
|
485 | previousName = name;
|
486 | }
|
487 | });
|
488 | return isCorrectlySorted;
|
489 | }
|
490 | |
491 |
|
492 |
|
493 |
|
494 |
|
495 |
|
496 |
|
497 | function validateMembersOrder(members, orderConfig, supportsModifiers) {
|
498 | if (orderConfig === 'never') {
|
499 | return;
|
500 | }
|
501 |
|
502 | let order = null;
|
503 | let memberTypes;
|
504 | if (Array.isArray(orderConfig)) {
|
505 | memberTypes = orderConfig;
|
506 | }
|
507 | else {
|
508 | order = orderConfig.order;
|
509 | memberTypes = orderConfig.memberTypes;
|
510 | }
|
511 | const hasAlphaSort = order === null || order === void 0 ? void 0 : order.startsWith('alphabetically');
|
512 | const alphaSortIsCaseSensitive = order !== 'alphabetically-case-insensitive';
|
513 |
|
514 | if (Array.isArray(memberTypes)) {
|
515 | const grouped = checkGroupSort(members, memberTypes, supportsModifiers);
|
516 | if (grouped === null) {
|
517 | return;
|
518 | }
|
519 | if (hasAlphaSort) {
|
520 | grouped.some(groupMember => !checkAlphaSort(groupMember, alphaSortIsCaseSensitive));
|
521 | }
|
522 | }
|
523 | else if (hasAlphaSort) {
|
524 | checkAlphaSort(members, alphaSortIsCaseSensitive);
|
525 | }
|
526 | }
|
527 | return {
|
528 | ClassDeclaration(node) {
|
529 | var _a;
|
530 | validateMembersOrder(node.body.body, (_a = options.classes) !== null && _a !== void 0 ? _a : options.default, true);
|
531 | },
|
532 | ClassExpression(node) {
|
533 | var _a;
|
534 | validateMembersOrder(node.body.body, (_a = options.classExpressions) !== null && _a !== void 0 ? _a : options.default, true);
|
535 | },
|
536 | TSInterfaceDeclaration(node) {
|
537 | var _a;
|
538 | validateMembersOrder(node.body.body, (_a = options.interfaces) !== null && _a !== void 0 ? _a : options.default, false);
|
539 | },
|
540 | TSTypeLiteral(node) {
|
541 | var _a;
|
542 | validateMembersOrder(node.members, (_a = options.typeLiterals) !== null && _a !== void 0 ? _a : options.default, false);
|
543 | },
|
544 | };
|
545 | },
|
546 | });
|
547 |
|
\ | No newline at end of file |