eslint-plugin-mobx
Version:
ESLint rules for MobX
71 lines (65 loc) • 2.72 kB
JavaScript
;
const { findAncestor, isMobxDecorator } = require('./utils.js');
function create(context) {
const sourceCode = context.getSourceCode();
return {
'Decorator': decorator => {
if (!isMobxDecorator(decorator)) return;
const clazz = findAncestor(decorator, node => node.type === 'ClassDeclaration' || node.type === 'ClassExpression');
if (!clazz) return;
// ClassDeclaration > ClassBody > []
const constructor = clazz.body.body.find(node => node.kind === 'constructor' && node.value.type === 'FunctionExpression') ??
clazz.body.body.find(node => node.kind === 'constructor');
// MethodDefinition > FunctionExpression > BlockStatement > []
const isMakeObservable = node => node.expression?.callee?.name === 'makeObservable' && node.expression?.arguments[0]?.type === 'ThisExpression';
const makeObservable = constructor?.value.body?.body.find(isMakeObservable)?.expression;
if (makeObservable) {
// make sure second arg is nullish
const secondArg = makeObservable.arguments[1];
if (secondArg && secondArg.value !== null && secondArg.name !== 'undefined') {
context.report({
node: makeObservable,
messageId: 'secondArgMustBeNullish',
})
}
} else {
const fix = fixer => {
if (constructor?.value.type === 'TSEmptyBodyFunctionExpression') {
// constructor() - yes this a thing
const closingBracket = sourceCode.getLastToken(constructor.value);
return fixer.insertTextAfter(closingBracket, ' { makeObservable(this); }')
} else if (constructor) {
// constructor() {}
const closingBracket = sourceCode.getLastToken(constructor.value.body);
return fixer.insertTextBefore(closingBracket, ';makeObservable(this);')
} else {
// class C {}
const openingBracket = sourceCode.getFirstToken(clazz.body);
return fixer.insertTextAfter(openingBracket, '\nconstructor() { makeObservable(this); }')
}
};
context.report({
node: clazz,
messageId: 'missingMakeObservable',
fix,
})
}
},
};
}
module.exports = {
meta: {
type: 'problem',
fixable: 'code',
docs: {
description: 'prevents missing `makeObservable(this)` when using decorators',
recommended: true,
suggestion: false,
},
messages: {
missingMakeObservable: "Constructor is missing `makeObservable(this)`.",
secondArgMustBeNullish: "`makeObservable`'s second argument must be nullish or not provided when using decorators."
},
},
create,
};