From 3a0b8a6d268c0139964093173a051e002a57dc88 Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 24 Jan 2021 17:26:05 -0800 Subject: [PATCH 1/4] feat(eslint-plugin): [member-delimiter-style] checkMemberSeparatorStyle --- .../src/rules/member-delimiter-style.ts | 10 ++- .../rules/member-delimiter-style.test.ts | 72 +++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index 75381a8df2c..9cbaab2f90a 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -215,11 +215,17 @@ export default util.createRule({ 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 (!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 diff --git a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts index d0fa7895b9c..22208455b65 100644 --- a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts +++ b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts @@ -705,6 +705,35 @@ type Bar = { }, ], }, + ` +type Foo = {a: { + b: true; +}}; + `, + { + code: ` +type Foo = {a: { + b: true; +};}; + `, + options: [ + { + singleline: { delimiter: 'semi', requireLast: true }, + }, + ], + }, + { + code: ` +type Foo = { + +}; + `, + options: [ + { + singleline: { delimiter: 'semi', requireLast: true }, + }, + ], + }, { code: ` @@ -3365,5 +3394,48 @@ type Foo = { }, ], }, + { + code: ` +type Foo = {a: { + b: true; +};}; + `, + output: ` +type Foo = {a: { + b: true; +}}; + `, + errors: [ + { + messageId: 'unexpectedSemi', + line: 4, + column: 3, + }, + ], + }, + { + code: ` +type Foo = {a: { + b: true; +}}; + `, + output: ` +type Foo = {a: { + b: true; +};}; + `, + options: [ + { + singleline: { delimiter: 'semi', requireLast: true }, + }, + ], + errors: [ + { + messageId: 'expectedSemi', + line: 4, + column: 2, + }, + ], + }, ], }); From 888cd6b3256b682d75efef436c2470cf1d1c3bdd Mon Sep 17 00:00:00 2001 From: pfg Date: Sun, 24 Jan 2021 17:35:30 -0800 Subject: [PATCH 2/4] feat(eslint-plugin): [member-delimiter-style] add some more tests --- .../rules/member-delimiter-style.test.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts index 22208455b65..4e4bb8a7f36 100644 --- a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts +++ b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts @@ -709,6 +709,13 @@ type Bar = { type Foo = {a: { b: true; }}; + `, + ` +type Foo = { + a: { + b: true; + }; +}; `, { code: ` @@ -3415,6 +3422,29 @@ type Foo = {a: { }, { code: ` +type Foo = { + a: { + b: true; + } +}; + `, + output: ` +type Foo = { + a: { + b: true; + }; +}; + `, + errors: [ + { + messageId: 'expectedSemi', + line: 5, + column: 4, + }, + ], + }, + { + code: ` type Foo = {a: { b: true; }}; From 2b655f508dd40c56628e93d7ea3e87357fd23f95 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 28 Jan 2021 22:37:45 -0800 Subject: [PATCH 3/4] feat(eslint-plugin): [member-delimiter-style] update this to not be a breaking change --- .../src/rules/member-delimiter-style.ts | 11 ++- .../rules/member-delimiter-style.test.ts | 69 ++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index 9cbaab2f90a..64147b37cf2 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -21,6 +21,7 @@ type Config = BaseOptions & { typeLiteral?: BaseOptions; interface?: BaseOptions; }; + multilineDetection?: 'brackets' | 'last-member'; }; type Options = [Config]; type MessageIds = @@ -82,6 +83,9 @@ export default util.createRule({ }, additionalProperties: false, }, + multilineDetection: { + enum: ['brackets', 'last-member'], + }, }), additionalProperties: false, }, @@ -97,6 +101,7 @@ export default util.createRule({ delimiter: 'semi', requireLast: false, }, + multilineDetection: 'brackets', }, ], create(context, [options]) { @@ -219,7 +224,11 @@ export default util.createRule({ node.type === AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members; let isSingleLine = node.loc.start.line === node.loc.end.line; - if (!isSingleLine && members.length > 0) { + 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; diff --git a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts index 4e4bb8a7f36..c69e54e2af0 100644 --- a/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts +++ b/packages/eslint-plugin/tests/rules/member-delimiter-style.test.ts @@ -705,18 +705,49 @@ 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: { @@ -726,6 +757,7 @@ type Foo = {a: { options: [ { singleline: { delimiter: 'semi', requireLast: true }, + multilineDetection: 'last-member', }, ], }, @@ -738,6 +770,7 @@ type Foo = { options: [ { singleline: { delimiter: 'semi', requireLast: true }, + multilineDetection: 'last-member', }, ], }, @@ -3412,6 +3445,11 @@ type Foo = {a: { b: true; }}; `, + options: [ + { + multilineDetection: 'last-member', + }, + ], errors: [ { messageId: 'unexpectedSemi', @@ -3422,6 +3460,25 @@ type Foo = {a: { }, { 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; @@ -3435,6 +3492,11 @@ type Foo = { }; }; `, + options: [ + { + multilineDetection: 'last-member', + }, + ], errors: [ { messageId: 'expectedSemi', @@ -3457,6 +3519,7 @@ type Foo = {a: { options: [ { singleline: { delimiter: 'semi', requireLast: true }, + multilineDetection: 'last-member', }, ], errors: [ From 17c71a8a6a8658431cf33987bac7ecec638aa3c6 Mon Sep 17 00:00:00 2001 From: pfg Date: Thu, 28 Jan 2021 22:42:35 -0800 Subject: [PATCH 4/4] feat(eslint-plugin): [member-delimiter-style] add some documentation --- .../eslint-plugin/docs/rules/member-delimiter-style.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/member-delimiter-style.md b/packages/eslint-plugin/docs/rules/member-delimiter-style.md index ed1b0957756..c6f7ca47000 100644 --- a/packages/eslint-plugin/docs/rules/member-delimiter-style.md +++ b/packages/eslint-plugin/docs/rules/member-delimiter-style.md @@ -72,6 +72,7 @@ type Config = BaseConfig & { interface?: BaseConfig; typeLiteral?: BaseConfig; }; + multilineDetection?: 'brackets' | 'last-member'; }; ``` @@ -86,7 +87,8 @@ Default config: "singleline": { "delimiter": "semi", "requireLast": false - } + }, + "multilineDetection": "brackets" } ``` @@ -94,6 +96,11 @@ Default config: `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`):