Skip to content

Commit

Permalink
[FIX] function-component-definition: replace var by const in ce…
Browse files Browse the repository at this point in the history
…rtain situations

Preserves existing variable definition if it exists.
  • Loading branch information
SimeonC authored and Xavier Le Cunff committed Apr 15, 2022
1 parent aeefa48 commit c593379
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 14 deletions.
35 changes: 29 additions & 6 deletions lib/rules/function-component-definition.js
Expand Up @@ -21,8 +21,8 @@ function buildFunction(template, parts) {

const NAMED_FUNCTION_TEMPLATES = {
'function-declaration': 'function {name}{typeParams}({params}){returnType} {body}',
'arrow-function': 'const {name}{typeAnnotation} = {typeParams}({params}){returnType} => {body}',
'function-expression': 'const {name}{typeAnnotation} = function{typeParams}({params}){returnType} {body}',
'arrow-function': '{varType} {name}{typeAnnotation} = {typeParams}({params}){returnType} => {body}',
'function-expression': '{varType} {name}{typeAnnotation} = function{typeParams}({params}){returnType} {body}',
};

const UNNAMED_FUNCTION_TEMPLATES = {
Expand Down Expand Up @@ -145,6 +145,7 @@ module.exports = {

create: Components.detect((context, components) => {
const configuration = context.options[0] || {};
let fileVarType = 'var';

const namedConfig = [].concat(configuration.namedComponents || 'function-declaration');
const unnamedConfig = [].concat(configuration.unnamedComponents || 'function-expression');
Expand All @@ -159,6 +160,10 @@ module.exports = {
if (options.type === 'arrow-function' && hasOneUnconstrainedTypeParam(node)) return;
if (isUnfixableBecauseOfExport(node)) return;
if (isFunctionExpressionWithName(node)) return;
let varType = fileVarType;
if ((node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') && node.parent.type === 'VariableDeclarator') {
varType = node.parent.parent.kind;
}

return (fixer) => fixer.replaceTextRange(options.range, buildFunction(options.template, {
typeAnnotation,
Expand All @@ -167,6 +172,7 @@ module.exports = {
returnType: getNodeText(node.returnType, source),
body: getBody(node, source),
name: getName(node),
varType,
}));
}

Expand Down Expand Up @@ -209,11 +215,28 @@ module.exports = {
// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------

const validatePairs = [];
let hasEs6OrJsx = false;
return {
FunctionDeclaration(node) { validate(node, 'function-declaration'); },
ArrowFunctionExpression(node) { validate(node, 'arrow-function'); },
FunctionExpression(node) { validate(node, 'function-expression'); },
FunctionDeclaration(node) {
validatePairs.push([node, 'function-declaration']);
},
ArrowFunctionExpression(node) {
validatePairs.push([node, 'arrow-function']);
},
FunctionExpression(node) {
validatePairs.push([node, 'function-expression']);
},
VariableDeclaration(node) {
hasEs6OrJsx = hasEs6OrJsx || node.kind === 'const' || node.kind === 'let';
},
JSXElement() {
hasEs6OrJsx = true;
},
'Program:exit'() {
if (hasEs6OrJsx) fileVarType = 'const';
validatePairs.forEach((pair) => validate(pair[0], pair[1]));
},
};
}),
};
43 changes: 35 additions & 8 deletions tests/lib/rules/function-component-definition.js
Expand Up @@ -57,6 +57,10 @@ ruleTester.run('function-component-definition', rule, {
code: 'var Hello = (props) => { return <div/> }',
options: [{ namedComponents: 'arrow-function' }],
},
{
code: 'const Hello = (props) => { return <div/> }',
options: [{ namedComponents: 'arrow-function' }],
},
{
code: 'function Hello(props) { return <div/> }',
options: [{ namedComponents: 'function-declaration' }],
Expand All @@ -65,6 +69,10 @@ ruleTester.run('function-component-definition', rule, {
code: 'var Hello = function(props) { return <div/> }',
options: [{ namedComponents: 'function-expression' }],
},
{
code: 'const Hello = function(props) { return <div/> }',
options: [{ namedComponents: 'function-expression' }],
},
{
code: 'function Hello() { return function() { return <div/> } }',
options: [{ unnamedComponents: 'function-expression' }],
Expand All @@ -77,6 +85,10 @@ ruleTester.run('function-component-definition', rule, {
code: 'var Foo = React.memo(function Foo() { return <p/> })',
options: [{ namedComponents: 'function-declaration' }],
},
{
code: 'const Foo = React.memo(function Foo() { return <p/> })',
options: [{ namedComponents: 'function-declaration' }],
},
{
// shouldn't trigger this rule since functions stating with a lowercase
// letter are not considered components
Expand Down Expand Up @@ -404,7 +416,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = (props) => {
const Hello = (props) => {
return <div/>;
}
`,
Expand Down Expand Up @@ -474,7 +486,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = function(props) {
const Hello = function(props) {
return <div/>;
}
`,
Expand Down Expand Up @@ -554,7 +566,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = (props: Test) => {
const Hello = (props: Test) => {
return <div/>;
}
`,
Expand Down Expand Up @@ -584,14 +596,29 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = function(props: Test) {
const Hello = function(props: Test) {
return <div/>;
}
`,
options: [{ namedComponents: 'function-expression' }],
errors: [{ messageId: 'function-expression' }],
features: ['types'],
},
{
code: `
function Hello(props: Test) {
return React.createElement('div');
}
`,
output: `
var Hello = function(props: Test) {
return React.createElement('div');
}
`,
options: [{ namedComponents: 'function-expression' }],
errors: [{ messageId: 'function-expression' }],
features: ['types'],
},
{
code: `
var Hello = (props: Test) => {
Expand Down Expand Up @@ -674,7 +701,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = <Test extends {}>(props: Test) => {
const Hello = <Test extends {}>(props: Test) => {
return <div/>;
}
`,
Expand Down Expand Up @@ -704,7 +731,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = function<Test extends {}>(props: Test) {
const Hello = function<Test extends {}>(props: Test) {
return <div/>;
}
`,
Expand Down Expand Up @@ -874,7 +901,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
export var Hello = (props) => {
export const Hello = (props) => {
return <div/>;
}
`,
Expand Down Expand Up @@ -934,7 +961,7 @@ ruleTester.run('function-component-definition', rule, {
}
`,
output: `
var Hello = (props) => {
const Hello = (props) => {
return <div/>;
}
`,
Expand Down

0 comments on commit c593379

Please sign in to comment.