diff --git a/.changeset/tall-meals-walk.md b/.changeset/tall-meals-walk.md new file mode 100644 index 000000000..51e54ff9e --- /dev/null +++ b/.changeset/tall-meals-walk.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-mobx": patch +--- + +fix `no-anonymous-observer` autofix for arrow functions without BlockStatement body diff --git a/packages/eslint-plugin-mobx/preview/no-anonymous-observer.js b/packages/eslint-plugin-mobx/preview/no-anonymous-observer.js index a18c7b25e..866148e39 100644 --- a/packages/eslint-plugin-mobx/preview/no-anonymous-observer.js +++ b/packages/eslint-plugin-mobx/preview/no-anonymous-observer.js @@ -1,12 +1,15 @@ /* eslint mobx/no-anonymous-observer: "error" */ -observer(() => { }); -observer(function () { }); -observer(class { }); +observer(() => {}) +observer(function () {}) +observer(class {}) -const Cmp = observer(() => { }); -const Cmp = observer(function () { }); -const Cmp = observer(class { }); +const Cmp = observer(() => {}) +const Cmp = observer(() => "") // different autofix +const Cmp = observer(() => expr()) // different autofix +const Cmp = observer(() => literal) // different autofix +const Cmp = observer(function () {}) +const Cmp = observer(class {}) -observer(function Name() { }); -observer(class Name { }); \ No newline at end of file +observer(function Name() {}) +observer(class Name {}) diff --git a/packages/eslint-plugin-mobx/src/no-anonymous-observer.js b/packages/eslint-plugin-mobx/src/no-anonymous-observer.js index c54b7f2ba..0ce636c97 100644 --- a/packages/eslint-plugin-mobx/src/no-anonymous-observer.js +++ b/packages/eslint-plugin-mobx/src/no-anonymous-observer.js @@ -1,57 +1,65 @@ -'use strict'; +"use strict" function create(context) { - const sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode() - return { - 'CallExpression[callee.name="observer"]': observer => { - const cmp = observer.arguments[0]; - if (!cmp) return; - if (cmp?.id?.name) return; + return { + 'CallExpression[callee.name="observer"]': observer => { + const cmp = observer.arguments[0] + if (!cmp) return + if (cmp?.id?.name) return - const fix = fixer => { - // Use name from variable for autofix - const name = observer.parent?.type === 'VariableDeclarator' - ? observer.parent.id.name - : undefined; + const fix = fixer => { + // Use name from variable for autofix + const name = + observer.parent?.type === "VariableDeclarator" + ? observer.parent.id.name + : undefined - if (!name) return; - if (cmp.type === 'ArrowFunctionExpression') { - const arrowToken = sourceCode.getTokenBefore(cmp.body); - return [ - fixer.replaceText(arrowToken, ''), - fixer.insertTextBefore(cmp, `function ${name}`), - ] + if (!name) return + if (cmp.type === "ArrowFunctionExpression") { + const arrowToken = sourceCode.getTokenBefore(cmp.body) + const fixes = [ + fixer.replaceText(arrowToken, ""), + fixer.insertTextBefore(cmp, `function ${name}`) + ] + if (cmp.body.type !== "BlockStatement") { + fixes.push( + fixer.insertTextBefore(cmp.body, `{ return `), + fixer.insertTextAfter(cmp.body, ` }`) + ) + } + return fixes + } + if (cmp.type === "FunctionExpression") { + const functionToken = sourceCode.getFirstToken(cmp) + return fixer.replaceText(functionToken, `function ${name}`) + } + if (cmp.type === "ClassExpression") { + const classToken = sourceCode.getFirstToken(cmp) + return fixer.replaceText(classToken, `class ${name}`) + } + } + context.report({ + node: cmp, + messageId: "observerComponentMustHaveName", + fix + }) } - if (cmp.type === 'FunctionExpression') { - const functionToken = sourceCode.getFirstToken(cmp); - return fixer.replaceText(functionToken, `function ${name}`); - } - if (cmp.type === 'ClassExpression') { - const classToken = sourceCode.getFirstToken(cmp); - return fixer.replaceText(classToken, `class ${name}`); - } - } - context.report({ - node: cmp, - messageId: 'observerComponentMustHaveName', - fix, - }) - }, - }; + } } module.exports = { - meta: { - type: 'problem', - fixable: 'code', - docs: { - description: 'forbids anonymous functions or classes as `observer` components', - recommended: true, - }, - messages: { - observerComponentMustHaveName: "`observer` component must have a name.", + meta: { + type: "problem", + fixable: "code", + docs: { + description: "forbids anonymous functions or classes as `observer` components", + recommended: true + }, + messages: { + observerComponentMustHaveName: "`observer` component must have a name." + } }, - }, - create, -}; \ No newline at end of file + create +}