Skip to content

Commit

Permalink
[FIX] function-component-definition: replace var by const
Browse files Browse the repository at this point in the history
Signed-off-by: Xavier Le Cunff <xavier@MacBook-Pro-de-Xavier.local>
  • Loading branch information
JohnBerd authored and Xavier Le Cunff committed Apr 15, 2022
1 parent e52eed5 commit 8072551
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 29 deletions.
30 changes: 15 additions & 15 deletions docs/rules/function-component-definition.md
Expand Up @@ -12,12 +12,12 @@ Examples of **incorrect** code for this rule:

```jsx
// function expression for named component
var Component = function (props) {
const Component = function (props) {
return <div>{props.content}</div>;
};

// arrow function for named component
var Component = (props) => {
const Component = (props) => {
return <div>{props.content}</div>;
};

Expand Down Expand Up @@ -49,11 +49,11 @@ Examples of **incorrect** code for this rule:
```jsx
// only function declarations for named components
// [2, { "namedComponents": "function-declaration" }]
var Component = function (props) {
const Component = function (props) {
return <div />;
};

var Component = (props) => {
const Component = (props) => {
return <div />;
};

Expand All @@ -63,7 +63,7 @@ function Component (props) {
return <div />;
};

var Component = (props) => {
const Component = (props) => {
return <div />;
};

Expand All @@ -73,7 +73,7 @@ function Component (props) {
return <div />;
};

var Component = function (props) {
const Component = function (props) {
return <div />;
};

Expand Down Expand Up @@ -107,13 +107,13 @@ function Component (props) {

// only function expressions for named components
// [2, { "namedComponents": "function-expression" }]
var Component = function (props) {
const Component = function (props) {
return <div />;
};

// only arrow functions for named components
// [2, { "namedComponents": "arrow-function" }]
var Component = (props) => {
const Component = (props) => {
return <div />;
};

Expand Down Expand Up @@ -170,11 +170,11 @@ The following patterns can **not** be autofixed in TypeScript:
```tsx
// function expressions and arrow functions that have type annotations cannot be autofixed to function declarations
// [2, { "namedComponents": "function-declaration" }]
var Component: React.FC<Props> = function (props) {
const Component: React.FC<Props> = function (props) {
return <div />;
};

var Component: React.FC<Props> = (props) => {
const Component: React.FC<Props> = (props) => {
return <div />;
};

Expand All @@ -184,7 +184,7 @@ function Component<T>(props: Props<T>) {
return <div />;
};

var Component = function <T>(props: Props<T>) {
const Component = function <T>(props: Props<T>) {
return <div />;
};

Expand All @@ -203,13 +203,13 @@ The following patterns can be autofixed in TypeScript:
```tsx
// autofix to function expression with type annotation
// [2, { "namedComponents": "function-expression" }]
var Component: React.FC<Props> = (props) => {
const Component: React.FC<Props> = (props) => {
return <div />;
};

// autofix to arrow function with type annotation
// [2, { "namedComponents": "function-expression" }]
var Component: React.FC<Props> = function (props) {
const Component: React.FC<Props> = function (props) {
return <div />;
};

Expand All @@ -219,7 +219,7 @@ function Component<T extends {}>(props: Props<T>) {
return <div />;
}

var Component = function <T extends {}>(props: Props<T>) {
const Component = function <T extends {}>(props: Props<T>) {
return <div />;
};

Expand All @@ -229,7 +229,7 @@ function Component<T1, T2>(props: Props<T1, T2>) {
return <div />;
}

var Component = function <T1, T2>(props: Props<T2>) {
const Component = function <T1, T2>(props: Props<T2>) {
return <div />;
};

Expand Down
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': 'var {name}{typeAnnotation} = {typeParams}({params}){returnType} => {body}',
'function-expression': 'var {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 8072551

Please sign in to comment.