Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/eslint-plugin/docs/rules/member-delimiter-style.md
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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,
},
],
},
],
});