Skip to content

Commit

Permalink
Merge branch 'master' into feat-init-declarations
Browse files Browse the repository at this point in the history
  • Loading branch information
anikethsaha committed Apr 6, 2020
2 parents f2b0294 + 16ce74d commit 9a9fff7
Show file tree
Hide file tree
Showing 27 changed files with 3,625 additions and 608 deletions.
24 changes: 13 additions & 11 deletions .cspell.json
Expand Up @@ -35,45 +35,47 @@
"\\(#.+?\\)"
],
"words": [
"ASTs",
"Airbnb",
"Airbnb's",
"Codecov",
"Crockford",
"errored",
"IDE's",
"IIFE",
"IIFEs",
"OOM",
"OOMs",
"Premade",
"ROADMAP",
"ASTs",
"autofix",
"autofixers",
"backticks",
"bigint",
"bivariant",
"blockless",
"codebases",
"Codecov",
"contravariant",
"Crockford",
"declarators",
"destructure",
"destructured",
"errored",
"erroring",
"ESLint",
"ESLint's",
"espree",
"estree",
"IDE's",
"IIFE",
"IIFEs",
"linebreaks",
"necroing",
"nocheck",
"nullish",
"OOM",
"OOMs",
"parameterised",
"performant",
"pluggable",
"postprocess",
"Premade",
"prettier's",
"recurse",
"reimplement",
"resync",
"ROADMAP",
"ruleset",
"rulesets",
"superset",
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/eslint-plugin-tslint.md
Expand Up @@ -15,7 +15,7 @@ The more relevant information you can include, the faster we can find the issue

<!--
Make sure you read through our FAQ before posting.
https://github.com/typescript-eslint/typescript-eslint/blob/issue-template-update/docs/getting-started/linting/FAQ.md
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md
-->

**Repro**
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/eslint-plugin-typescript.md
Expand Up @@ -28,7 +28,7 @@ Are you opening an issue because the rule you're trying to use is not found?

<!--
Make sure you read through our FAQ before posting.
https://github.com/typescript-eslint/typescript-eslint/blob/issue-template-update/docs/getting-started/linting/FAQ.md
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md
-->

**Repro**
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/typescript-eslint-parser.md
Expand Up @@ -15,7 +15,7 @@ The more relevant information you can include, the faster we can find the issue

<!--
Make sure you read through our FAQ before posting.
https://github.com/typescript-eslint/typescript-eslint/blob/issue-template-update/docs/getting-started/linting/FAQ.md
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md
-->

**Repro**
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/typescript-eslint-utils.md
Expand Up @@ -15,7 +15,7 @@ The more relevant information you can include, the faster we can find the issue

<!--
Make sure you read through our FAQ before posting.
https://github.com/typescript-eslint/typescript-eslint/blob/issue-template-update/docs/getting-started/linting/FAQ.md
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md
-->

**Repro**
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/typescript-estree.md
Expand Up @@ -15,7 +15,7 @@ The more relevant information you can include, the faster we can find the issue

<!--
Make sure you read through our FAQ before posting.
https://github.com/typescript-eslint/typescript-eslint/blob/issue-template-update/docs/getting-started/linting/FAQ.md
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md
-->

**Repro**
Expand Down
1 change: 1 addition & 0 deletions packages/eslint-plugin/README.md
Expand Up @@ -107,6 +107,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int
| [`@typescript-eslint/explicit-module-boundary-types`](./docs/rules/explicit-module-boundary-types.md) | Require explicit return and argument types on exported functions' and classes' public class methods | | | |
| [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | :heavy_check_mark: | :wrench: | |
| [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | |
| [`@typescript-eslint/method-signature-style`](./docs/rules/method-signature-style.md) | Enforces using a particular method signature syntax. | | :wrench: | |
| [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: |
| [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: |
| [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | |
Expand Down
202 changes: 151 additions & 51 deletions packages/eslint-plugin/docs/rules/member-ordering.md
@@ -1,29 +1,54 @@
# Require a consistent member declaration order (`member-ordering`)

A consistent ordering of fields, methods and constructors can make interfaces, type literals, classes and class
expressions easier to read, navigate and edit.
A consistent ordering of fields, methods and constructors can make interfaces, type literals, classes and class expressions easier to read, navigate and edit.

## Rule Details

This rule aims to standardize the way class declarations, class expressions, interfaces and type literals are structured.
This rule aims to standardize the way class declarations, class expressions, interfaces and type literals are structured and ordered.

It allows to group members by their type (e.g. `public-static-field`, `protected-static-field`, `private-static-field`, `public-instance-field`, ...). By default, their order is the same inside `classes`, `classExpressions`, `interfaces` and `typeLiterals` (note: not all member types apply to `interfaces` and `typeLiterals`). It is possible to define the order for any of those individually or to change the default order for all of them by setting the `default` option.
### Grouping and sorting member groups

It allows to group members by their type (e.g. `public-static-field`, `protected-static-field`, `private-static-field`, `public-instance-field`, ...) and enforce a certain order for these groups. By default, their order is the same inside `classes`, `classExpressions`, `interfaces` and `typeLiterals` (note: not all member types apply to `interfaces` and `typeLiterals`). It is possible to define the order for any of those individually or to change the default order for all of them by setting the `default` option.

### Sorting members

Besides grouping the members and sorting their groups, this rule also allows to sort the members themselves (e.g. `a`, `b`, `c`, ...). You have 2 options: Sort all of them while ignoring their type or sort them while respecting their types (e.g. sort all fields in an interface alphabetically).

## Options

These options allow to specify how to group the members and sort their groups.

- Sort groups, don't enforce member order: Use `memberTypes`
- Sort members, don't enforce group order: Use `order`
- Sort members within groups: Use `memberTypes` and `order`

```ts
type TypeOptions<T> =
| {
memberTypes: Array<T> | 'never',
order?: 'alphabetically' | 'as-written',
}
| {
order: 'alphabetically',
};

{
default?: Array<MemberType> | never
classes?: Array<MemberType> | never
classExpressions?: Array<MemberType> | never
default?: TypeOptions<MemberTypes>,

classes?: TypeOptions<MemberTypes>,
classExpressions?: TypeOptions<MemberTypes>,

interfaces?: ['signature' | 'field' | 'method' | 'constructor'] | never
typeLiterals?: ['signature' | 'field' | 'method' | 'constructor'] | never
interfaces?: TypeOptions<'signature' | 'field' | 'method' | 'constructor'>,
typeLiterals?: TypeOptions<'signature' | 'field' | 'method' | 'constructor'>,
}
```

See below for the possible definitions of `MemberType`.

### Deprecated syntax

Note: There is a deprecated syntax to specify the member types as an array.

### Member types (granular form)

There are multiple ways to specify the member types. The most explicit and granular form is the following:
Expand Down Expand Up @@ -138,62 +163,72 @@ The third grouping option is to ignore both scope and accessibility.

The default configuration looks as follows:

```json
```json5
{
"default": [
"signature",
default: [
// Index signature
'signature',

"public-static-field",
"protected-static-field",
"private-static-field",
// Fields
'public-static-field',
'protected-static-field',
'private-static-field',

"public-instance-field",
"protected-instance-field",
"private-instance-field",
'public-instance-field',
'protected-instance-field',
'private-instance-field',

"public-abstract-field",
"protected-abstract-field",
"private-abstract-field",
'public-abstract-field',
'protected-abstract-field',
'private-abstract-field',

"public-field",
"protected-field",
"private-field",
'public-field',
'protected-field',
'private-field',

"static-field",
"instance-field",
"abstract-field",
'static-field',
'instance-field',
'abstract-field',

"field",
'field',

"constructor",
// Constructors
'public-constructor',
'protected-constructor',
'private-constructor',

"public-static-method",
"protected-static-method",
"private-static-method",
'constructor',

"public-instance-method",
"protected-instance-method",
"private-instance-method",
// Methods
'public-static-method',
'protected-static-method',
'private-static-method',

"public-abstract-method",
"protected-abstract-method",
"private-abstract-method",
'public-instance-method',
'protected-instance-method',
'private-instance-method',

"public-method",
"protected-method",
"private-method",
'public-abstract-method',
'protected-abstract-method',
'private-abstract-method',

"static-method",
"instance-method",
"abstract-method",
'public-method',
'protected-method',
'private-method',

"method"
]
'static-method',
'instance-method',
'abstract-method',

'method',
],
}
```

Note: The default configuration contains member group types which contain other member types (see above). This is intentional to provide better error messages.

Note: By default, the members are not sorted. If you want to sort them alphabetically, you have to provide a custom configuration.

## Examples

### Custom `default` configuration
Expand Down Expand Up @@ -448,7 +483,7 @@ const foo = class {
};
```

Issue: Public static fields should come first, followed by static fields and instance fields.
Note: Public static fields should come first, followed by static fields and instance fields.

##### Correct examples

Expand Down Expand Up @@ -542,21 +577,19 @@ class Foo {

##### Correct example

Examples of **correct** code for `{ "classes": [...] }` option:

```ts
class Foo {
private C: string; // (irrelevant)

public D: string; // (irrelevant)

public static E: string; // -> public static field
public B(): void {} // -> public instance method

constructor() {} // (irrelevant)

public static A(): void {} // (irrelevant)

public B(): void {} // -> public instance method
public static E: string; // -> public static field
}
```

Expand Down Expand Up @@ -712,6 +745,73 @@ type Foo = {
};
```

### Sorting alphabetically within member groups

It is possible to sort all members within a group alphabetically.

#### Configuration: `{ default: { memberTypes: <Default Order>, order: 'alphabetically' } }`

This will apply the default order (see above) and enforce an alphabetic order within each group.

##### Incorrect examples

```ts
interface Foo {
a: x;
b: x;
c: x;

new (): Bar;
(): Baz;

a(): void;
b(): void;
c(): void;

// Wrong group order, should be placed before all field definitions
[a: string]: number;
}
```

```ts
interface Foo {
[a: string]: number;

a: x;
b: x;
c: x;

new (): Bar;
(): Baz;

// Wrong alphabetic order within group
c(): void;
b(): void;
a(): void;
}
```

### Sorting alphabetically while ignoring member groups

It is also possible to sort all members and ignore the member groups completely.

#### Configuration: `{ default: { memberTypes: 'never', order: 'alphabetically' } }`

##### Incorrect example

```ts
interface Foo {
b(): void;
a: b;

[a: string]: number; // Order doesn't matter (no sortable identifier)
new (): Bar; // Order doesn't matter (no sortable identifier)
(): Baz; // Order doesn't matter (no sortable identifier)
}
```

Note: Wrong alphabetic order `b(): void` should come after `a: b`.

## When Not To Use It

If you don't care about the general structure of your classes and interfaces, then you will not need this rule.
Expand Down

0 comments on commit 9a9fff7

Please sign in to comment.