diff --git a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts index f7c356698dd..1ccdeab215f 100644 --- a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts +++ b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts @@ -49,32 +49,34 @@ export default createRule({ return; } if (mode === 'lhs' && !lhs && rhs.typeParameters) { + const { typeParameters, callee } = rhs; + const typeAnnotation = + sourceCode.getText(callee) + sourceCode.getText(typeParameters); context.report({ node, messageId: 'preferLHS', fix(fixer) { - const { typeParameters, callee } = rhs; - const typeAnnotation = - sourceCode.getText(callee) + sourceCode.getText(typeParameters); return [ - fixer.remove(typeParameters!), + fixer.remove(typeParameters), fixer.insertTextAfter(node.id, ': ' + typeAnnotation), ]; }, }); } if (mode === 'rhs' && lhs?.typeParameters && !rhs.typeParameters) { + const hasParens = sourceCode.getTokenAfter(rhs.callee)?.value === '('; context.report({ node, messageId: 'preferRHS', - fix(fixer) { - return [ - fixer.remove(lhs.parent!), - fixer.insertTextAfter( - rhs.callee, - sourceCode.getText(lhs.typeParameters), - ), - ]; + *fix(fixer) { + yield fixer.remove(lhs.parent!); + yield fixer.insertTextAfter( + rhs.callee, + sourceCode.getText(lhs.typeParameters), + ); + if (!hasParens) { + yield fixer.insertTextAfter(rhs.callee, '()'); + } }, }); } diff --git a/packages/eslint-plugin/tests/rules/consistent-generic-constructors.test.ts b/packages/eslint-plugin/tests/rules/consistent-generic-constructors.test.ts index 9ad84e5e062..1a0d260dbee 100644 --- a/packages/eslint-plugin/tests/rules/consistent-generic-constructors.test.ts +++ b/packages/eslint-plugin/tests/rules/consistent-generic-constructors.test.ts @@ -107,6 +107,44 @@ ruleTester.run('consistent-generic-constructors', rule, { ], output: noFormat`const a = new Map ();`, }, + { + code: noFormat`const a: Foo = new Foo;`, + errors: [ + { + messageId: 'preferRHS', + }, + ], + output: noFormat`const a = new Foo();`, + }, + { + code: 'const a: Foo/* comment */ = new Foo();', + errors: [ + { + messageId: 'preferRHS', + }, + ], + // FIXME + output: 'const a = new Foo();', + }, + { + code: 'const a: Foo/* comment */ = new Foo /* another */();', + errors: [ + { + messageId: 'preferRHS', + }, + ], + // FIXME + output: 'const a = new Foo /* another */();', + }, + { + code: noFormat`const a: Foo = new \n Foo \n ();`, + errors: [ + { + messageId: 'preferRHS', + }, + ], + output: noFormat`const a = new \n Foo \n ();`, + }, { code: 'const a = new Foo();', options: ['lhs'], @@ -147,5 +185,25 @@ ruleTester.run('consistent-generic-constructors', rule, { ], output: noFormat`const a: Map< string, number > = new Map();`, }, + { + code: noFormat`const a = new \n Foo \n ();`, + options: ['lhs'], + errors: [ + { + messageId: 'preferLHS', + }, + ], + output: noFormat`const a: Foo = new \n Foo \n ();`, + }, + { + code: 'const a = new Foo/* comment */ /* another */();', + options: ['lhs'], + errors: [ + { + messageId: 'preferLHS', + }, + ], + output: noFormat`const a: Foo = new Foo/* comment */ /* another */();`, + }, ], });