Skip to content

Commit

Permalink
feat(eslint-plugin): [member-delimiter-style] Add an option 'multilin…
Browse files Browse the repository at this point in the history
…eDetection' to treat types and interfaces as single line if the last member ends on the same line as the closing bracket (#2970)
  • Loading branch information
pfgithub committed Feb 28, 2021
1 parent c32f803 commit cf86f42
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 3 deletions.
9 changes: 8 additions & 1 deletion packages/eslint-plugin/docs/rules/member-delimiter-style.md
Expand Up @@ -72,6 +72,7 @@ type Config = BaseConfig & {
interface?: BaseConfig;
typeLiteral?: BaseConfig;
};
multilineDetection?: 'brackets' | 'last-member';
};
```

Expand All @@ -86,14 +87,20 @@ Default config:
"singleline": {
"delimiter": "semi",
"requireLast": false
}
},
"multilineDetection": "brackets"
}
```

`multiline` config only applies to multiline `interface`/`type` definitions.
`singleline` config only applies to single line `interface`/`type` definitions.
The two configs are entirely separate, and do not effect one another.

`multilineDetection` determines what counts as multiline

- `"brackets"` (default) any newlines in the type or interface make it multiline.
- `"last-member"` if the last member of the interface is on the same line as the last bracket, it is counted as a single line.

### `delimiter`

Accepts three values (or two for `singleline`):
Expand Down
19 changes: 17 additions & 2 deletions packages/eslint-plugin/src/rules/member-delimiter-style.ts
Expand Up @@ -21,6 +21,7 @@ type Config = BaseOptions & {
typeLiteral?: BaseOptions;
interface?: BaseOptions;
};
multilineDetection?: 'brackets' | 'last-member';
};
type Options = [Config];
type MessageIds =
Expand Down Expand Up @@ -82,6 +83,9 @@ export default util.createRule<Options, MessageIds>({
},
additionalProperties: false,
},
multilineDetection: {
enum: ['brackets', 'last-member'],
},
}),
additionalProperties: false,
},
Expand All @@ -97,6 +101,7 @@ export default util.createRule<Options, MessageIds>({
delimiter: 'semi',
requireLast: false,
},
multilineDetection: 'brackets',
},
],
create(context, [options]) {
Expand Down Expand Up @@ -215,11 +220,21 @@ export default util.createRule<Options, MessageIds>({
function checkMemberSeparatorStyle(
node: TSESTree.TSInterfaceBody | TSESTree.TSTypeLiteral,
): void {
const isSingleLine = node.loc.start.line === node.loc.end.line;

const members =
node.type === AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members;

let isSingleLine = node.loc.start.line === node.loc.end.line;
if (
options.multilineDetection === 'last-member' &&
!isSingleLine &&
members.length > 0
) {
const lastMember = members[members.length - 1];
if (lastMember.loc.end.line === node.loc.end.line) {
isSingleLine = true;
}
}

const typeOpts =
node.type === AST_NODE_TYPES.TSInterfaceBody
? interfaceOptions
Expand Down
165 changes: 165 additions & 0 deletions packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts
Expand Up @@ -705,6 +705,75 @@ type Bar = {
},
],
},
{
code: `
type Foo = {a: {
b: true;
}};
`,
options: [
{
multilineDetection: 'last-member',
},
],
},
`
type Foo = {a: {
b: true;
};};
`,
{
code: `
type Foo = {a: {
b: true;
};};
`,
options: [
{
multilineDetection: 'brackets',
},
],
},
{
code: `
type Foo = {
a: {
b: true;
};
};
`,
options: [
{
multilineDetection: 'last-member',
},
],
},
{
code: `
type Foo = {a: {
b: true;
};};
`,
options: [
{
singleline: { delimiter: 'semi', requireLast: true },
multilineDetection: 'last-member',
},
],
},
{
code: `
type Foo = {
};
`,
options: [
{
singleline: { delimiter: 'semi', requireLast: true },
multilineDetection: 'last-member',
},
],
},

{
code: `
Expand Down Expand Up @@ -3365,5 +3434,101 @@ type Foo = {
},
],
},
{
code: `
type Foo = {a: {
b: true;
};};
`,
output: `
type Foo = {a: {
b: true;
}};
`,
options: [
{
multilineDetection: 'last-member',
},
],
errors: [
{
messageId: 'unexpectedSemi',
line: 4,
column: 3,
},
],
},
{
code: `
type Foo = {a: {
b: true;
}};
`,
output: `
type Foo = {a: {
b: true;
};};
`,
errors: [
{
messageId: 'expectedSemi',
line: 4,
column: 2,
},
],
},
{
code: `
type Foo = {
a: {
b: true;
}
};
`,
output: `
type Foo = {
a: {
b: true;
};
};
`,
options: [
{
multilineDetection: 'last-member',
},
],
errors: [
{
messageId: 'expectedSemi',
line: 5,
column: 4,
},
],
},
{
code: `
type Foo = {a: {
b: true;
}};
`,
output: `
type Foo = {a: {
b: true;
};};
`,
options: [
{
singleline: { delimiter: 'semi', requireLast: true },
multilineDetection: 'last-member',
},
],
errors: [
{
messageId: 'expectedSemi',
line: 4,
column: 2,
},
],
},
],
});

0 comments on commit cf86f42

Please sign in to comment.