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 +12 -0
- package/README.md +29 -2
- package/dist/index.js +164 -79
- package/package.json +12 -8
- package/src/index.js +33 -11
- package/src/missing-observer.js +86 -55
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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 (
|
|
15
|
-
if (Object(
|
|
16
|
-
|
|
17
|
-
} else for (; !(
|
|
18
|
-
} catch (
|
|
19
|
-
|
|
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 (!
|
|
52
|
+
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
23
53
|
} finally {
|
|
24
|
-
if (
|
|
54
|
+
if (o) throw n;
|
|
25
55
|
}
|
|
26
56
|
}
|
|
27
|
-
return
|
|
57
|
+
return a;
|
|
28
58
|
}
|
|
29
59
|
}
|
|
30
|
-
function
|
|
31
|
-
|
|
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
|
|
34
|
-
|
|
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
|
|
37
|
-
|
|
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
|
|
40
|
-
|
|
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
|
|
43
|
-
|
|
87
|
+
function _slicedToArray(r, e) {
|
|
88
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
44
89
|
}
|
|
45
|
-
function
|
|
46
|
-
|
|
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
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
59
|
-
|
|
103
|
+
function _toPropertyKey(t) {
|
|
104
|
+
var i = _toPrimitive(t, "string");
|
|
105
|
+
return "symbol" == typeof i ? i : i + "";
|
|
60
106
|
}
|
|
61
|
-
function
|
|
62
|
-
|
|
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
|
|
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
|
|
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
|
|
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$
|
|
280
|
-
return ((_node$expression = node.expression) === null || _node$expression === void 0
|
|
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
|
|
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
|
-
|
|
338
|
-
var _cmp$id,
|
|
339
|
-
|
|
340
|
-
|
|
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 && ((
|
|
344
|
-
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(
|
|
403
|
+
if (cmp.type.startsWith("Class")) {
|
|
347
404
|
// Must extend Component or React.Component
|
|
348
405
|
var superClass = cmp.superClass;
|
|
349
|
-
if (!superClass)
|
|
406
|
+
if (!superClass) {
|
|
407
|
+
// not a component
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
350
410
|
var superClassText = sourceCode.getText(superClass);
|
|
351
|
-
if (superClassText !==
|
|
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]$/)))
|
|
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(
|
|
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:
|
|
428
|
+
messageId: "missingObserver",
|
|
363
429
|
data: {
|
|
364
|
-
name: name ||
|
|
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:
|
|
374
|
-
fixable:
|
|
439
|
+
type: "problem",
|
|
440
|
+
fixable: "code",
|
|
375
441
|
docs: {
|
|
376
|
-
description:
|
|
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
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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.
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
}
|
package/src/missing-observer.js
CHANGED
|
@@ -1,63 +1,94 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict"
|
|
2
2
|
|
|
3
3
|
function create(context) {
|
|
4
|
-
|
|
4
|
+
const sourceCode = context.getSourceCode()
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
63
|
-
};
|
|
93
|
+
create
|
|
94
|
+
}
|