Skip to content

Commit 39bb41b

Browse files
committed
Add support for matching on TypeScript accessibility modifiers.
1 parent f41029b commit 39bb41b

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Members can be matched to positional slots using several criteria, including nam
104104
- `accessorPair`: `true|false`. True to match only getters and setters that are part of a pair. i.e., only those that have both `get` and `set` methods defined.
105105
- `static`: `true|false` to restrict the match to static or instance members.
106106
- `private`: `true|false` to restrict the match to [private members](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields). **Note**: Private members currently require a custom parser like [babel-eslint](https://github.com/babel/babel-eslint).
107+
- `accessibility`: `"public"|"private"|"protected"` to restrict the match to members with the specified typescript accessibility modifier. **Note**: Requires `@typescript-eslint/parser`.
107108
- `async`: `true|false` to restrict the match to async members.
108109
- `sort`: `"alphabetical"|"none"`. Used to require a specific sorting within the slot for matched members. Defaults to `"none"`.
109110
- `groupByDecorator`: a string used to group properties with the same decorator name (e.g. `observable` for `@observable`). Can be used together with `sort`. **Note**: Decorators are a Stage 2 proposal and require a custom parser like [babel-eslint](https://github.com/babel/babel-eslint).

src/rules/schema.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const sortClassMembersSchema = [
3939
static: { type: 'boolean' },
4040
private: { type: 'boolean' },
4141
async: { type: 'boolean' },
42+
accessibility: { enum: ['public', 'private', 'protected'] },
4243
},
4344
additionalProperties: false,
4445
},

src/rules/sort-class-members.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ function getMemberInfo(node, sourceCode) {
175175
let propertyType;
176176
let async = false;
177177
let decorators = [];
178+
const accessibility = node.accessibility ?? 'public';
178179

179180
decorators =
180181
(!!node.decorators &&
@@ -218,6 +219,7 @@ function getMemberInfo(node, sourceCode) {
218219
static: node.static,
219220
async,
220221
private: isPrivate,
222+
accessibility,
221223
kind: node.kind,
222224
propertyType,
223225
node,
@@ -418,6 +420,7 @@ const comparers = [
418420
{ property: 'static', value: 10, test: (m, s) => s.static === m.static },
419421
{ property: 'async', value: 10, test: (m, s) => s.async === m.async },
420422
{ property: 'private', value: 10, test: (m, s) => s.private === m.private },
423+
{ property: 'accessibility', value: 10, test: (m, s) => s.accessibility == m.accessibility },
421424
{ property: 'kind', value: 10, test: (m, s) => s.kind === m.kind },
422425
{
423426
property: 'groupByDecorator',

test/rules/sort-class-members.spec.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,24 @@ const privateRegexpOptions = [
236236
},
237237
];
238238

239+
const typescriptAccessibilityOptions = [
240+
{
241+
groups: {
242+
private: [
243+
{
244+
accessibility: 'private',
245+
},
246+
],
247+
public: [
248+
{
249+
accessibility: 'public',
250+
},
251+
],
252+
},
253+
order: ['[private]', 'constructor', '[public]'],
254+
},
255+
];
256+
239257
ruleTester.run('sort-class-members', rule, {
240258
valid: [
241259
{ code: 'class A {}', options: defaultOptions },
@@ -344,6 +362,18 @@ ruleTester.run('sort-class-members', rule, {
344362
// Class expressions
345363
{ code: 'module.exports = class A {}', options: defaultOptions },
346364
{ code: 'class { [k: string]: any; }', parser: require.resolve('@typescript-eslint/parser') },
365+
366+
// TS accessibility
367+
{
368+
code: 'class { private a: any; constructor(){} b(){} }',
369+
options: typescriptAccessibilityOptions,
370+
parser: require.resolve('@typescript-eslint/parser'),
371+
},
372+
{
373+
code: 'class { private a: any; constructor(){} public b(){} c(){} }',
374+
options: typescriptAccessibilityOptions,
375+
parser: require.resolve('@typescript-eslint/parser'),
376+
},
347377
],
348378
invalid: [
349379
{
@@ -832,6 +862,30 @@ ruleTester.run('sort-class-members', rule, {
832862
options: privateRegexpOptions,
833863
},
834864
]),
865+
{
866+
code: 'class { constructor(){} private b: any; }',
867+
output: 'class { private b: any; constructor(){} }',
868+
errors: [
869+
{
870+
message: 'Expected property b to come before constructor.',
871+
type: 'PropertyDefinition',
872+
},
873+
],
874+
options: typescriptAccessibilityOptions,
875+
parser: require.resolve('@typescript-eslint/parser'),
876+
},
877+
{
878+
code: 'class { a(){} private b: any; }',
879+
output: 'class { private b: any; a(){} }',
880+
errors: [
881+
{
882+
message: 'Expected property b to come before method a.',
883+
type: 'PropertyDefinition',
884+
},
885+
],
886+
options: typescriptAccessibilityOptions,
887+
parser: require.resolve('@typescript-eslint/parser'),
888+
},
835889
],
836890
});
837891

0 commit comments

Comments
 (0)