eslint-plugin-mobx 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # eslint-plugin-mobx
2
2
 
3
+ ## 0.0.12
4
+
5
+ ### Patch Changes
6
+
7
+ - [`218ebde877712775054e027cfda812210d2aa7d6`](https://github.com/mobxjs/mobx/commit/218ebde877712775054e027cfda812210d2aa7d6) [#3942](https://github.com/mobxjs/mobx/pull/3942) Thanks [@dartess](https://github.com/dartess)! - add eslint@9 support and flat config
8
+
9
+ ## 0.0.11
10
+
11
+ ### Patch Changes
12
+
13
+ - [`638533e592f4fda7663fa351447380f9d0917d14`](https://github.com/mobxjs/mobx/commit/638533e592f4fda7663fa351447380f9d0917d14) [#3909](https://github.com/mobxjs/mobx/pull/3909) Thanks [@urugator](https://github.com/urugator)! - mobx/missing-observer rule false positive with forwardRef #3908
14
+
3
15
  ## 0.0.10
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -10,6 +10,8 @@ npm install --save-dev eslint @typescript-eslint/parser eslint-plugin-mobx
10
10
 
11
11
  ## Configuration
12
12
 
13
+ ### Legacy Config
14
+
13
15
  ```javascript
14
16
  // .eslintrc.js
15
17
  module.exports = {
@@ -24,12 +26,37 @@ module.exports = {
24
26
  "mobx/exhaustive-make-observable": "warn",
25
27
  "mobx/unconditional-make-observable": "error",
26
28
  "mobx/missing-make-observable": "error",
27
- "mobx/missing-observer": "warn",
28
- "mobx/no-anonymous-observer": "warn"
29
+ "mobx/missing-observer": "warn"
29
30
  }
30
31
  }
31
32
  ```
32
33
 
34
+ ### Flat Config
35
+
36
+ ```javascript
37
+ // eslint.config.js
38
+ import pluginMobx from "eslint-plugin-mobx"
39
+
40
+ export default [
41
+ // ...
42
+
43
+ // Either extend our recommended configuration:
44
+ pluginMobx.flatConfigs.recommended,
45
+
46
+ // ...or specify and customize individual rules:
47
+ {
48
+ plugins: { mobx: pluginMobx },
49
+ rules: {
50
+ // these values are the same as recommended
51
+ "mobx/exhaustive-make-observable": "warn",
52
+ "mobx/unconditional-make-observable": "error",
53
+ "mobx/missing-make-observable": "error",
54
+ "mobx/missing-observer": "warn"
55
+ }
56
+ }
57
+ ]
58
+ ```
59
+
33
60
  ## Rules
34
61
 
35
62
  ### mobx/exhaustive-make-observable
package/dist/index.js CHANGED
@@ -1,65 +1,115 @@
1
1
  'use strict';
2
2
 
3
- function _iterableToArrayLimit(arr, i) {
4
- var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
5
- if (null != _i) {
6
- var _s,
7
- _e,
8
- _x,
9
- _r,
10
- _arr = [],
11
- _n = !0,
12
- _d = !1;
3
+ var require$$0 = require('fs');
4
+ var require$$1 = require('path');
5
+
6
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
7
+
8
+ var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
9
+ var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
10
+
11
+ function _arrayLikeToArray(r, a) {
12
+ (null == a || a > r.length) && (a = r.length);
13
+ for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
14
+ return n;
15
+ }
16
+ function _arrayWithHoles(r) {
17
+ if (Array.isArray(r)) return r;
18
+ }
19
+ function _arrayWithoutHoles(r) {
20
+ if (Array.isArray(r)) return _arrayLikeToArray(r);
21
+ }
22
+ function _defineProperty(e, r, t) {
23
+ return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
24
+ value: t,
25
+ enumerable: !0,
26
+ configurable: !0,
27
+ writable: !0
28
+ }) : e[r] = t, e;
29
+ }
30
+ function _iterableToArray(r) {
31
+ if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
32
+ }
33
+ function _iterableToArrayLimit(r, l) {
34
+ var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
35
+ if (null != t) {
36
+ var e,
37
+ n,
38
+ i,
39
+ u,
40
+ a = [],
41
+ f = !0,
42
+ o = !1;
13
43
  try {
14
- if (_x = (_i = _i.call(arr)).next, 0 === i) {
15
- if (Object(_i) !== _i) return;
16
- _n = !1;
17
- } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
18
- } catch (err) {
19
- _d = !0, _e = err;
44
+ if (i = (t = t.call(r)).next, 0 === l) {
45
+ if (Object(t) !== t) return;
46
+ f = !1;
47
+ } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
48
+ } catch (r) {
49
+ o = !0, n = r;
20
50
  } finally {
21
51
  try {
22
- if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
52
+ if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
23
53
  } finally {
24
- if (_d) throw _e;
54
+ if (o) throw n;
25
55
  }
26
56
  }
27
- return _arr;
57
+ return a;
28
58
  }
29
59
  }
30
- function _slicedToArray(arr, i) {
31
- return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
60
+ function _nonIterableRest() {
61
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
32
62
  }
33
- function _toConsumableArray(arr) {
34
- return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
63
+ function _nonIterableSpread() {
64
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
35
65
  }
36
- function _arrayWithoutHoles(arr) {
37
- if (Array.isArray(arr)) return _arrayLikeToArray(arr);
66
+ function ownKeys(e, r) {
67
+ var t = Object.keys(e);
68
+ if (Object.getOwnPropertySymbols) {
69
+ var o = Object.getOwnPropertySymbols(e);
70
+ r && (o = o.filter(function (r) {
71
+ return Object.getOwnPropertyDescriptor(e, r).enumerable;
72
+ })), t.push.apply(t, o);
73
+ }
74
+ return t;
38
75
  }
39
- function _arrayWithHoles(arr) {
40
- if (Array.isArray(arr)) return arr;
76
+ function _objectSpread2(e) {
77
+ for (var r = 1; r < arguments.length; r++) {
78
+ var t = null != arguments[r] ? arguments[r] : {};
79
+ r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
80
+ _defineProperty(e, r, t[r]);
81
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
82
+ Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
83
+ });
84
+ }
85
+ return e;
41
86
  }
42
- function _iterableToArray(iter) {
43
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
87
+ function _slicedToArray(r, e) {
88
+ return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
44
89
  }
45
- function _unsupportedIterableToArray(o, minLen) {
46
- if (!o) return;
47
- if (typeof o === "string") return _arrayLikeToArray(o, minLen);
48
- var n = Object.prototype.toString.call(o).slice(8, -1);
49
- if (n === "Object" && o.constructor) n = o.constructor.name;
50
- if (n === "Map" || n === "Set") return Array.from(o);
51
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
90
+ function _toConsumableArray(r) {
91
+ return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
52
92
  }
53
- function _arrayLikeToArray(arr, len) {
54
- if (len == null || len > arr.length) len = arr.length;
55
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
56
- return arr2;
93
+ function _toPrimitive(t, r) {
94
+ if ("object" != typeof t || !t) return t;
95
+ var e = t[Symbol.toPrimitive];
96
+ if (void 0 !== e) {
97
+ var i = e.call(t, r || "default");
98
+ if ("object" != typeof i) return i;
99
+ throw new TypeError("@@toPrimitive must return a primitive value.");
100
+ }
101
+ return ("string" === r ? String : Number)(t);
57
102
  }
58
- function _nonIterableSpread() {
59
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
103
+ function _toPropertyKey(t) {
104
+ var i = _toPrimitive(t, "string");
105
+ return "symbol" == typeof i ? i : i + "";
60
106
  }
61
- function _nonIterableRest() {
62
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
107
+ function _unsupportedIterableToArray(r, a) {
108
+ if (r) {
109
+ if ("string" == typeof r) return _arrayLikeToArray(r, a);
110
+ var t = {}.toString.call(r).slice(8, -1);
111
+ return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
112
+ }
63
113
  }
64
114
 
65
115
  var mobxDecorators = new Set(['observable', 'computed', 'action', 'flow', 'override']);
@@ -69,7 +119,6 @@ function isMobxDecorator$2(decorator) {
69
119
  || mobxDecorators.has((_decorator$expression = decorator.expression.callee) === null || _decorator$expression === void 0 ? void 0 : _decorator$expression.name) // @foo()
70
120
  || mobxDecorators.has((_decorator$expression2 = decorator.expression.object) === null || _decorator$expression2 === void 0 ? void 0 : _decorator$expression2.name); // @foo.bar
71
121
  }
72
-
73
122
  function findAncestor$3(node, match) {
74
123
  var parent = node.parent;
75
124
  if (!parent) return;
@@ -115,7 +164,7 @@ function create$4(context) {
115
164
  var closestFunction = findAncestor$2(makeObservable, function (node) {
116
165
  return node.type === "FunctionExpression" || node.type === "FunctionDeclaration";
117
166
  });
118
- if ((closestFunction === null || closestFunction === void 0 ? void 0 : (_closestFunction$pare = closestFunction.parent) === null || _closestFunction$pare === void 0 ? void 0 : _closestFunction$pare.kind) !== "constructor") return;
167
+ if ((closestFunction === null || closestFunction === void 0 || (_closestFunction$pare = closestFunction.parent) === null || _closestFunction$pare === void 0 ? void 0 : _closestFunction$pare.kind) !== "constructor") return;
119
168
  members = closestFunction.parent.parent.parent.body.body;
120
169
  } else if (firstArg.type === "ObjectExpression") {
121
170
  members = firstArg.properties;
@@ -229,7 +278,7 @@ function create$3(context) {
229
278
  var closestFunction = findAncestor$1(makeObservable, function (node) {
230
279
  return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration';
231
280
  });
232
- if ((closestFunction === null || closestFunction === void 0 ? void 0 : (_closestFunction$pare = closestFunction.parent) === null || _closestFunction$pare === void 0 ? void 0 : _closestFunction$pare.kind) !== 'constructor') return;
281
+ if ((closestFunction === null || closestFunction === void 0 || (_closestFunction$pare = closestFunction.parent) === null || _closestFunction$pare === void 0 ? void 0 : _closestFunction$pare.kind) !== 'constructor') return;
233
282
  if (makeObservable.parent.parent.parent !== closestFunction) {
234
283
  context.report({
235
284
  node: makeObservable,
@@ -262,7 +311,7 @@ function create$2(context) {
262
311
  var sourceCode = context.getSourceCode();
263
312
  return {
264
313
  'Decorator': function Decorator(decorator) {
265
- var _clazz$body$body$find, _constructor$value$bo, _constructor$value$bo2;
314
+ var _clazz$body$body$find, _constructor$value$bo;
266
315
  if (!isMobxDecorator(decorator)) return;
267
316
  var clazz = findAncestor(decorator, function (node) {
268
317
  return node.type === 'ClassDeclaration' || node.type === 'ClassExpression';
@@ -276,10 +325,10 @@ function create$2(context) {
276
325
  });
277
326
  // MethodDefinition > FunctionExpression > BlockStatement > []
278
327
  var isMakeObservable = function isMakeObservable(node) {
279
- var _node$expression, _node$expression$call, _node$expression2, _node$expression2$arg;
280
- return ((_node$expression = node.expression) === null || _node$expression === void 0 ? void 0 : (_node$expression$call = _node$expression.callee) === null || _node$expression$call === void 0 ? void 0 : _node$expression$call.name) === 'makeObservable' && ((_node$expression2 = node.expression) === null || _node$expression2 === void 0 ? void 0 : (_node$expression2$arg = _node$expression2.arguments[0]) === null || _node$expression2$arg === void 0 ? void 0 : _node$expression2$arg.type) === 'ThisExpression';
328
+ var _node$expression, _node$expression2;
329
+ return ((_node$expression = node.expression) === null || _node$expression === void 0 || (_node$expression = _node$expression.callee) === null || _node$expression === void 0 ? void 0 : _node$expression.name) === 'makeObservable' && ((_node$expression2 = node.expression) === null || _node$expression2 === void 0 || (_node$expression2 = _node$expression2.arguments[0]) === null || _node$expression2 === void 0 ? void 0 : _node$expression2.type) === 'ThisExpression';
281
330
  };
282
- var makeObservable = constructor === null || constructor === void 0 ? void 0 : (_constructor$value$bo = constructor.value.body) === null || _constructor$value$bo === void 0 ? void 0 : (_constructor$value$bo2 = _constructor$value$bo.body.find(isMakeObservable)) === null || _constructor$value$bo2 === void 0 ? void 0 : _constructor$value$bo2.expression;
331
+ var makeObservable = constructor === null || constructor === void 0 || (_constructor$value$bo = constructor.value.body) === null || _constructor$value$bo === void 0 || (_constructor$value$bo = _constructor$value$bo.body.find(isMakeObservable)) === null || _constructor$value$bo === void 0 ? void 0 : _constructor$value$bo.expression;
283
332
  if (makeObservable) {
284
333
  // make sure second arg is nullish
285
334
  var secondArg = makeObservable.arguments[1];
@@ -334,34 +383,51 @@ var missingMakeObservable$1 = {
334
383
  function create$1(context) {
335
384
  var sourceCode = context.getSourceCode();
336
385
  return {
337
- 'FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression': function FunctionDeclarationFunctionExpressionArrowFunctionExpressionClassDeclarationClassExpression(cmp) {
338
- var _cmp$id, _cmp$parent;
339
- // Already has observer
340
- if (cmp.parent && cmp.parent.type === 'CallExpression' && cmp.parent.callee.name === 'observer') return;
386
+ "FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression": function FunctionDeclarationFunctionExpressionArrowFunctionExpressionClassDeclarationClassExpression(cmp) {
387
+ var _cmp$id, _cmpOrForwardRef$pare;
388
+ if (cmp.parent && cmp.parent.type === "CallExpression" && cmp.parent.callee.name === "observer") {
389
+ // observer(...)
390
+ return;
391
+ }
392
+ var forwardRef = cmp.parent && cmp.parent.type === "CallExpression" && cmp.parent.callee.name === "forwardRef" ? cmp.parent : undefined;
393
+ if (forwardRef && forwardRef.parent && forwardRef.parent.type === "CallExpression" && forwardRef.parent.callee.name === "observer") {
394
+ // forwardRef(observer(...))
395
+ return;
396
+ }
397
+ var cmpOrForwardRef = forwardRef || cmp;
341
398
  var name = (_cmp$id = cmp.id) === null || _cmp$id === void 0 ? void 0 : _cmp$id.name;
342
- // If anonymous try to infer name from variable declaration
343
- if (!name && ((_cmp$parent = cmp.parent) === null || _cmp$parent === void 0 ? void 0 : _cmp$parent.type) === 'VariableDeclarator') {
344
- name = cmp.parent.id.name;
399
+ // If anonymous try to infer name from variable declaration
400
+ if (!name && ((_cmpOrForwardRef$pare = cmpOrForwardRef.parent) === null || _cmpOrForwardRef$pare === void 0 ? void 0 : _cmpOrForwardRef$pare.type) === "VariableDeclarator") {
401
+ name = cmpOrForwardRef.parent.id.name;
345
402
  }
346
- if (cmp.type.startsWith('Class')) {
403
+ if (cmp.type.startsWith("Class")) {
347
404
  // Must extend Component or React.Component
348
405
  var superClass = cmp.superClass;
349
- if (!superClass) return;
406
+ if (!superClass) {
407
+ // not a component
408
+ return;
409
+ }
350
410
  var superClassText = sourceCode.getText(superClass);
351
- if (superClassText !== 'Component' && superClassText !== 'React.Component') return;
411
+ if (superClassText !== "Component" && superClassText !== "React.Component") {
412
+ // not a component
413
+ return;
414
+ }
352
415
  } else {
353
416
  var _name;
354
417
  // Name must start with uppercase letter
355
- if (!((_name = name) !== null && _name !== void 0 && _name.charAt(0).match(/^[A-Z]$/))) return;
418
+ if (!((_name = name) !== null && _name !== void 0 && _name.charAt(0).match(/^[A-Z]$/))) {
419
+ // not a component
420
+ return;
421
+ }
356
422
  }
357
423
  var fix = function fix(fixer) {
358
- return [fixer.insertTextBefore(sourceCode.getFirstToken(cmp), (name && cmp.type.endsWith('Declaration') ? "const ".concat(name, " = ") : '') + 'observer('), fixer.insertTextAfter(sourceCode.getLastToken(cmp), ')')];
424
+ return [fixer.insertTextBefore(sourceCode.getFirstToken(cmpOrForwardRef), (name && cmp.type.endsWith("Declaration") ? "const ".concat(name, " = ") : "") + "observer("), fixer.insertTextAfter(sourceCode.getLastToken(cmpOrForwardRef), ")")];
359
425
  };
360
426
  context.report({
361
427
  node: cmp,
362
- messageId: 'missingObserver',
428
+ messageId: "missingObserver",
363
429
  data: {
364
- name: name || '<anonymous>'
430
+ name: name || "<anonymous>"
365
431
  },
366
432
  fix: fix
367
433
  });
@@ -370,10 +436,10 @@ function create$1(context) {
370
436
  }
371
437
  var missingObserver$1 = {
372
438
  meta: {
373
- type: 'problem',
374
- fixable: 'code',
439
+ type: "problem",
440
+ fixable: "code",
375
441
  docs: {
376
- description: 'prevents missing `observer` on react component',
442
+ description: "prevents missing `observer` on react component",
377
443
  recommended: true
378
444
  },
379
445
  messages: {
@@ -436,22 +502,18 @@ var noAnonymousObserver$1 = {
436
502
  create: create
437
503
  };
438
504
 
505
+ var fs = require$$0__default["default"];
506
+ var path = require$$1__default["default"];
439
507
  var exhaustiveMakeObservable = exhaustiveMakeObservable$1;
440
508
  var unconditionalMakeObservable = unconditionalMakeObservable$1;
441
509
  var missingMakeObservable = missingMakeObservable$1;
442
510
  var missingObserver = missingObserver$1;
443
511
  var noAnonymousObserver = noAnonymousObserver$1;
444
- var src = {
445
- configs: {
446
- recommended: {
447
- plugins: ["mobx"],
448
- rules: {
449
- "mobx/exhaustive-make-observable": "warn",
450
- "mobx/unconditional-make-observable": "error",
451
- "mobx/missing-make-observable": "error",
452
- "mobx/missing-observer": "warn"
453
- }
454
- }
512
+ var pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
513
+ var pluginMobx = {
514
+ meta: {
515
+ name: pkg.name,
516
+ version: pkg.version
455
517
  },
456
518
  rules: {
457
519
  "exhaustive-make-observable": exhaustiveMakeObservable,
@@ -461,5 +523,28 @@ var src = {
461
523
  "no-anonymous-observer": noAnonymousObserver
462
524
  }
463
525
  };
526
+ var recommendedRules = {
527
+ "mobx/exhaustive-make-observable": "warn",
528
+ "mobx/unconditional-make-observable": "error",
529
+ "mobx/missing-make-observable": "error",
530
+ "mobx/missing-observer": "warn"
531
+ };
532
+ var src = _objectSpread2(_objectSpread2({}, pluginMobx), {}, {
533
+ configs: {
534
+ recommended: {
535
+ plugins: ["mobx"],
536
+ rules: recommendedRules
537
+ }
538
+ },
539
+ flatConfigs: {
540
+ recommended: {
541
+ name: "react-hooks/recommended",
542
+ plugins: {
543
+ "mobx": pluginMobx
544
+ },
545
+ rules: recommendedRules
546
+ }
547
+ }
548
+ });
464
549
 
465
550
  module.exports = src;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-mobx",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "ESLint rules for MobX",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -25,18 +25,20 @@
25
25
  ],
26
26
  "homepage": "https://mobx.js.org/",
27
27
  "peerDependencies": {
28
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
28
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@typescript-eslint/eslint-plugin": "^5.0.0",
32
- "@typescript-eslint/parser": "^5.0.0",
33
- "eslint": "^7.0.0",
34
31
  "@babel/core": "^7.16.0",
35
32
  "@babel/preset-env": "^7.16.4",
36
- "rollup": "^2.60.2",
37
33
  "@rollup/plugin-babel": "^5.3.0",
38
34
  "@rollup/plugin-commonjs": "^21.0.1",
39
- "@rollup/plugin-node-resolve": "13.0.6"
35
+ "@rollup/plugin-node-resolve": "13.0.6",
36
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
37
+ "@typescript-eslint/parser": "^5.0.0",
38
+ "eslint": "^7.0.0",
39
+ "eslint-7": "npm:eslint@^7.0.0",
40
+ "eslint-9": "npm:eslint@^9.0.0",
41
+ "rollup": "^2.60.2"
40
42
  },
41
43
  "keywords": [
42
44
  "eslint",
@@ -45,7 +47,9 @@
45
47
  "mobx"
46
48
  ],
47
49
  "scripts": {
48
- "test": "jest",
50
+ "test:7": "jest --config jest.config-eslint-7.js",
51
+ "test:9": "jest --config jest.config-eslint-9.js",
52
+ "test": "npm run test:7 && npm run test:9",
49
53
  "build": "yarn rollup --config",
50
54
  "prepublishOnly": "yarn build"
51
55
  }
package/src/index.js CHANGED
@@ -1,22 +1,20 @@
1
1
  "use strict"
2
2
 
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
3
6
  const exhaustiveMakeObservable = require("./exhaustive-make-observable.js")
4
7
  const unconditionalMakeObservable = require("./unconditional-make-observable.js")
5
8
  const missingMakeObservable = require("./missing-make-observable.js")
6
9
  const missingObserver = require("./missing-observer")
7
10
  const noAnonymousObserver = require("./no-anonymous-observer.js")
8
11
 
9
- module.exports = {
10
- configs: {
11
- recommended: {
12
- plugins: ["mobx"],
13
- rules: {
14
- "mobx/exhaustive-make-observable": "warn",
15
- "mobx/unconditional-make-observable": "error",
16
- "mobx/missing-make-observable": "error",
17
- "mobx/missing-observer": "warn"
18
- }
19
- }
12
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
13
+
14
+ const pluginMobx = {
15
+ meta: {
16
+ name: pkg.name,
17
+ version: pkg.version
20
18
  },
21
19
  rules: {
22
20
  "exhaustive-make-observable": exhaustiveMakeObservable,
@@ -25,4 +23,28 @@ module.exports = {
25
23
  "missing-observer": missingObserver,
26
24
  "no-anonymous-observer": noAnonymousObserver
27
25
  }
26
+ };
27
+
28
+ const recommendedRules = {
29
+ "mobx/exhaustive-make-observable": "warn",
30
+ "mobx/unconditional-make-observable": "error",
31
+ "mobx/missing-make-observable": "error",
32
+ "mobx/missing-observer": "warn"
33
+ }
34
+
35
+ module.exports = {
36
+ ...pluginMobx,
37
+ configs: {
38
+ recommended: {
39
+ plugins: ["mobx"],
40
+ rules: recommendedRules,
41
+ }
42
+ },
43
+ flatConfigs: {
44
+ recommended: {
45
+ name: "react-hooks/recommended",
46
+ plugins: { "mobx": pluginMobx },
47
+ rules: recommendedRules
48
+ }
49
+ }
28
50
  }
@@ -1,63 +1,94 @@
1
- 'use strict';
1
+ "use strict"
2
2
 
3
3
  function create(context) {
4
- const sourceCode = context.getSourceCode();
4
+ const sourceCode = context.getSourceCode()
5
5
 
6
- return {
7
- 'FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression': cmp => {
8
- // Already has observer
9
- if (cmp.parent && cmp.parent.type === 'CallExpression' && cmp.parent.callee.name === 'observer') return;
10
- let name = cmp.id?.name;
11
- // If anonymous try to infer name from variable declaration
12
- if (!name && cmp.parent?.type === 'VariableDeclarator') {
13
- name = cmp.parent.id.name;
14
- }
15
- if (cmp.type.startsWith('Class')) {
16
- // Must extend Component or React.Component
17
- const { superClass } = cmp;
18
- if (!superClass) return;
19
- const superClassText = sourceCode.getText(superClass);
20
- if (superClassText !== 'Component' && superClassText !== 'React.Component') return;
21
- } else {
22
- // Name must start with uppercase letter
23
- if (!name?.charAt(0).match(/^[A-Z]$/)) return;
24
- }
6
+ return {
7
+ "FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression":
8
+ cmp => {
9
+ if (
10
+ cmp.parent &&
11
+ cmp.parent.type === "CallExpression" &&
12
+ cmp.parent.callee.name === "observer"
13
+ ) {
14
+ // observer(...)
15
+ return
16
+ }
17
+ let forwardRef =
18
+ cmp.parent &&
19
+ cmp.parent.type === "CallExpression" &&
20
+ cmp.parent.callee.name === "forwardRef"
21
+ ? cmp.parent
22
+ : undefined
23
+ if (
24
+ forwardRef &&
25
+ forwardRef.parent &&
26
+ forwardRef.parent.type === "CallExpression" &&
27
+ forwardRef.parent.callee.name === "observer"
28
+ ) {
29
+ // forwardRef(observer(...))
30
+ return
31
+ }
25
32
 
26
- const fix = fixer => {
27
- return [
28
- fixer.insertTextBefore(
29
- sourceCode.getFirstToken(cmp),
30
- (name && cmp.type.endsWith('Declaration') ? `const ${name} = ` : '') + 'observer(',
31
- ),
32
- fixer.insertTextAfter(
33
- sourceCode.getLastToken(cmp),
34
- ')',
35
- ),
36
- ]
37
- }
38
- context.report({
39
- node: cmp,
40
- messageId: 'missingObserver',
41
- data: {
42
- name: name || '<anonymous>',
43
- },
44
- fix,
45
- })
46
- },
47
- };
33
+ const cmpOrForwardRef = forwardRef || cmp
34
+ let name = cmp.id?.name
35
+ // If anonymous try to infer name from variable declaration
36
+ if (!name && cmpOrForwardRef.parent?.type === "VariableDeclarator") {
37
+ name = cmpOrForwardRef.parent.id.name
38
+ }
39
+ if (cmp.type.startsWith("Class")) {
40
+ // Must extend Component or React.Component
41
+ const { superClass } = cmp
42
+ if (!superClass) {
43
+ // not a component
44
+ return
45
+ }
46
+ const superClassText = sourceCode.getText(superClass)
47
+ if (superClassText !== "Component" && superClassText !== "React.Component") {
48
+ // not a component
49
+ return
50
+ }
51
+ } else {
52
+ // Name must start with uppercase letter
53
+ if (!name?.charAt(0).match(/^[A-Z]$/)) {
54
+ // not a component
55
+ return
56
+ }
57
+ }
58
+
59
+ const fix = fixer => {
60
+ return [
61
+ fixer.insertTextBefore(
62
+ sourceCode.getFirstToken(cmpOrForwardRef),
63
+ (name && cmp.type.endsWith("Declaration") ? `const ${name} = ` : "") +
64
+ "observer("
65
+ ),
66
+ fixer.insertTextAfter(sourceCode.getLastToken(cmpOrForwardRef), ")")
67
+ ]
68
+ }
69
+ context.report({
70
+ node: cmp,
71
+ messageId: "missingObserver",
72
+ data: {
73
+ name: name || "<anonymous>"
74
+ },
75
+ fix
76
+ })
77
+ }
78
+ }
48
79
  }
49
80
 
50
81
  module.exports = {
51
- meta: {
52
- type: 'problem',
53
- fixable: 'code',
54
- docs: {
55
- description: 'prevents missing `observer` on react component',
56
- recommended: true,
57
- },
58
- messages: {
59
- missingObserver: "Component `{{ name }}` is missing `observer`.",
82
+ meta: {
83
+ type: "problem",
84
+ fixable: "code",
85
+ docs: {
86
+ description: "prevents missing `observer` on react component",
87
+ recommended: true
88
+ },
89
+ messages: {
90
+ missingObserver: "Component `{{ name }}` is missing `observer`."
91
+ }
60
92
  },
61
- },
62
- create,
63
- };
93
+ create
94
+ }