eslint-plugin-mobx 0.0.13 → 0.1.0
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/dist/exhaustive-make-observable.d.ts +3 -0
- package/dist/exhaustive-make-observable.js +154 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +51 -546
- package/dist/missing-make-observable.d.ts +3 -0
- package/dist/missing-make-observable.js +72 -0
- package/dist/missing-observer.d.ts +3 -0
- package/dist/missing-observer.js +85 -0
- package/dist/no-anonymous-observer.d.ts +3 -0
- package/dist/no-anonymous-observer.js +64 -0
- package/dist/unconditional-make-observable.d.ts +3 -0
- package/dist/unconditional-make-observable.js +63 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +27 -0
- package/package.json +13 -14
- package/src/{exhaustive-make-observable.js → exhaustive-make-observable.ts} +8 -7
- package/src/{index.js → index.ts} +16 -11
- package/src/{missing-make-observable.js → missing-make-observable.ts} +7 -6
- package/src/{missing-observer.js → missing-observer.ts} +5 -3
- package/src/{no-anonymous-observer.js → no-anonymous-observer.ts} +5 -3
- package/src/{unconditional-make-observable.js → unconditional-make-observable.ts} +7 -5
- package/src/{utils.js → utils.ts} +3 -10
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function create(context) {
|
|
4
|
+
var _a;
|
|
5
|
+
var sourceCode = (_a = context.sourceCode) !== null && _a !== void 0 ? _a : context.getSourceCode();
|
|
6
|
+
return {
|
|
7
|
+
"FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression": function (cmp) {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
if (cmp.parent &&
|
|
10
|
+
cmp.parent.type === "CallExpression" &&
|
|
11
|
+
cmp.parent.callee.name === "observer") {
|
|
12
|
+
// observer(...)
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
var forwardRef = cmp.parent &&
|
|
16
|
+
cmp.parent.type === "CallExpression" &&
|
|
17
|
+
cmp.parent.callee.name === "forwardRef"
|
|
18
|
+
? cmp.parent
|
|
19
|
+
: undefined;
|
|
20
|
+
if (forwardRef &&
|
|
21
|
+
forwardRef.parent &&
|
|
22
|
+
forwardRef.parent.type === "CallExpression" &&
|
|
23
|
+
forwardRef.parent.callee.name === "observer") {
|
|
24
|
+
// forwardRef(observer(...))
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
var cmpOrForwardRef = forwardRef || cmp;
|
|
28
|
+
var name = (_a = cmp.id) === null || _a === void 0 ? void 0 : _a.name;
|
|
29
|
+
// If anonymous try to infer name from variable declaration
|
|
30
|
+
if (!name && ((_b = cmpOrForwardRef.parent) === null || _b === void 0 ? void 0 : _b.type) === "VariableDeclarator") {
|
|
31
|
+
name = cmpOrForwardRef.parent.id.name;
|
|
32
|
+
}
|
|
33
|
+
if (cmp.type.startsWith("Class")) {
|
|
34
|
+
// Must extend Component or React.Component
|
|
35
|
+
var superClass = cmp.superClass;
|
|
36
|
+
if (!superClass) {
|
|
37
|
+
// not a component
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
var superClassText = sourceCode.getText(superClass);
|
|
41
|
+
if (superClassText !== "Component" && superClassText !== "React.Component") {
|
|
42
|
+
// not a component
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Name must start with uppercase letter
|
|
48
|
+
if (!(name === null || name === void 0 ? void 0 : name.charAt(0).match(/^[A-Z]$/))) {
|
|
49
|
+
// not a component
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
var fix = function (fixer) {
|
|
54
|
+
return [
|
|
55
|
+
fixer.insertTextBefore(sourceCode.getFirstToken(cmpOrForwardRef), (name && cmp.type.endsWith("Declaration") ? "const ".concat(name, " = ") : "") +
|
|
56
|
+
"observer("),
|
|
57
|
+
fixer.insertTextAfter(sourceCode.getLastToken(cmpOrForwardRef), ")")
|
|
58
|
+
];
|
|
59
|
+
};
|
|
60
|
+
context.report({
|
|
61
|
+
node: cmp,
|
|
62
|
+
messageId: "missingObserver",
|
|
63
|
+
data: {
|
|
64
|
+
name: name || "<anonymous>"
|
|
65
|
+
},
|
|
66
|
+
fix: fix
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
var rule = {
|
|
72
|
+
meta: {
|
|
73
|
+
type: "problem",
|
|
74
|
+
fixable: "code",
|
|
75
|
+
docs: {
|
|
76
|
+
description: "prevents missing `observer` on react component",
|
|
77
|
+
recommended: true
|
|
78
|
+
},
|
|
79
|
+
messages: {
|
|
80
|
+
missingObserver: "Component `{{ name }}` is missing `observer`."
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
create: create
|
|
84
|
+
};
|
|
85
|
+
exports.default = rule;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function create(context) {
|
|
4
|
+
var _a;
|
|
5
|
+
var sourceCode = (_a = context.sourceCode) !== null && _a !== void 0 ? _a : context.getSourceCode();
|
|
6
|
+
return {
|
|
7
|
+
'CallExpression[callee.name="observer"]': function (observer) {
|
|
8
|
+
var _a;
|
|
9
|
+
var cmp = observer.arguments[0];
|
|
10
|
+
if (!cmp)
|
|
11
|
+
return;
|
|
12
|
+
if ((_a = cmp === null || cmp === void 0 ? void 0 : cmp.id) === null || _a === void 0 ? void 0 : _a.name)
|
|
13
|
+
return;
|
|
14
|
+
var fix = function (fixer) {
|
|
15
|
+
var _a;
|
|
16
|
+
// Use name from variable for autofix
|
|
17
|
+
var name = ((_a = observer.parent) === null || _a === void 0 ? void 0 : _a.type) === "VariableDeclarator"
|
|
18
|
+
? observer.parent.id.name
|
|
19
|
+
: undefined;
|
|
20
|
+
if (!name)
|
|
21
|
+
return;
|
|
22
|
+
if (cmp.type === "ArrowFunctionExpression") {
|
|
23
|
+
var arrowToken = sourceCode.getTokenBefore(cmp.body);
|
|
24
|
+
var fixes = [
|
|
25
|
+
fixer.replaceText(arrowToken, ""),
|
|
26
|
+
fixer.insertTextBefore(cmp, "function ".concat(name))
|
|
27
|
+
];
|
|
28
|
+
if (cmp.body.type !== "BlockStatement") {
|
|
29
|
+
fixes.push(fixer.insertTextBefore(cmp.body, "{ return "), fixer.insertTextAfter(cmp.body, " }"));
|
|
30
|
+
}
|
|
31
|
+
return fixes;
|
|
32
|
+
}
|
|
33
|
+
if (cmp.type === "FunctionExpression") {
|
|
34
|
+
var functionToken = sourceCode.getFirstToken(cmp);
|
|
35
|
+
return fixer.replaceText(functionToken, "function ".concat(name));
|
|
36
|
+
}
|
|
37
|
+
if (cmp.type === "ClassExpression") {
|
|
38
|
+
var classToken = sourceCode.getFirstToken(cmp);
|
|
39
|
+
return fixer.replaceText(classToken, "class ".concat(name));
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
context.report({
|
|
43
|
+
node: cmp,
|
|
44
|
+
messageId: "observerComponentMustHaveName",
|
|
45
|
+
fix: fix
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var rule = {
|
|
51
|
+
meta: {
|
|
52
|
+
type: "problem",
|
|
53
|
+
fixable: "code",
|
|
54
|
+
docs: {
|
|
55
|
+
description: "forbids anonymous functions or classes as `observer` components",
|
|
56
|
+
recommended: true
|
|
57
|
+
},
|
|
58
|
+
messages: {
|
|
59
|
+
observerComponentMustHaveName: "`observer` component must have a name."
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
create: create
|
|
63
|
+
};
|
|
64
|
+
exports.default = rule;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
+
if (!m) return o;
|
|
5
|
+
var i = m.call(o), r, ar = [], e;
|
|
6
|
+
try {
|
|
7
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
+
}
|
|
9
|
+
catch (error) { e = { error: error }; }
|
|
10
|
+
finally {
|
|
11
|
+
try {
|
|
12
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
+
}
|
|
14
|
+
finally { if (e) throw e.error; }
|
|
15
|
+
}
|
|
16
|
+
return ar;
|
|
17
|
+
};
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
var utils_1 = require("./utils");
|
|
20
|
+
function create(context) {
|
|
21
|
+
return {
|
|
22
|
+
'CallExpression[callee.name=/(makeObservable|makeAutoObservable)/]': function (makeObservable) {
|
|
23
|
+
var _a;
|
|
24
|
+
// Only interested about makeObservable(this, ...) inside constructor and not inside nested bindable function
|
|
25
|
+
var _b = __read(makeObservable.arguments, 1), firstArg = _b[0];
|
|
26
|
+
if (!firstArg)
|
|
27
|
+
return;
|
|
28
|
+
if (firstArg.type !== 'ThisExpression')
|
|
29
|
+
return;
|
|
30
|
+
// MethodDefinition[key.name="constructor"][kind="constructor"]
|
|
31
|
+
// FunctionExpression
|
|
32
|
+
// BlockStatement
|
|
33
|
+
// ExpressionStatement
|
|
34
|
+
// CallExpression[callee.name="makeObservable"]
|
|
35
|
+
var closestFunction = (0, utils_1.findAncestor)(makeObservable, function (node) { return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration'; });
|
|
36
|
+
if (((_a = closestFunction === null || closestFunction === void 0 ? void 0 : closestFunction.parent) === null || _a === void 0 ? void 0 : _a.kind) !== 'constructor')
|
|
37
|
+
return;
|
|
38
|
+
if (makeObservable.parent.parent.parent !== closestFunction) {
|
|
39
|
+
context.report({
|
|
40
|
+
node: makeObservable,
|
|
41
|
+
messageId: 'mustCallUnconditionally',
|
|
42
|
+
data: {
|
|
43
|
+
name: makeObservable.callee.name,
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
var rule = {
|
|
51
|
+
meta: {
|
|
52
|
+
type: 'problem',
|
|
53
|
+
docs: {
|
|
54
|
+
description: 'disallows calling `makeObservable(this)` conditionally inside constructors',
|
|
55
|
+
recommended: true,
|
|
56
|
+
},
|
|
57
|
+
messages: {
|
|
58
|
+
mustCallUnconditionally: '`{{ name }}` must be called unconditionally inside constructor.',
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
create: create,
|
|
62
|
+
};
|
|
63
|
+
exports.default = rule;
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isMobxDecorator = isMobxDecorator;
|
|
4
|
+
exports.findAncestor = findAncestor;
|
|
5
|
+
exports.assert = assert;
|
|
6
|
+
var mobxDecorators = new Set(['observable', 'computed', 'action', 'flow', 'override']);
|
|
7
|
+
function isMobxDecorator(decorator) {
|
|
8
|
+
var _a, _b;
|
|
9
|
+
return mobxDecorators.has(decorator.expression.name) // @foo
|
|
10
|
+
|| mobxDecorators.has((_a = decorator.expression.callee) === null || _a === void 0 ? void 0 : _a.name) // @foo()
|
|
11
|
+
|| mobxDecorators.has((_b = decorator.expression.object) === null || _b === void 0 ? void 0 : _b.name); // @foo.bar
|
|
12
|
+
}
|
|
13
|
+
function findAncestor(node, match) {
|
|
14
|
+
var parent = node.parent;
|
|
15
|
+
if (!parent)
|
|
16
|
+
return;
|
|
17
|
+
if (match(parent))
|
|
18
|
+
return parent;
|
|
19
|
+
return findAncestor(parent, match);
|
|
20
|
+
}
|
|
21
|
+
function assert(expr, error) {
|
|
22
|
+
if (!expr) {
|
|
23
|
+
error !== null && error !== void 0 ? error : (error = 'Assertion failed');
|
|
24
|
+
error = error instanceof Error ? error : new Error(error);
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-mobx",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "ESLint rules for MobX",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"repository": {
|
|
7
8
|
"type": "git",
|
|
8
9
|
"url": "https://github.com/mobxjs/mobx.git",
|
|
@@ -25,20 +26,15 @@
|
|
|
25
26
|
],
|
|
26
27
|
"homepage": "https://mobx.js.org/",
|
|
27
28
|
"peerDependencies": {
|
|
28
|
-
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
|
|
29
|
+
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@types/eslint": "^9.6.1",
|
|
33
|
+
"@types/estree": "^1.0.0"
|
|
29
34
|
},
|
|
30
35
|
"devDependencies": {
|
|
31
|
-
"@babel/core": "^7.16.0",
|
|
32
|
-
"@babel/preset-env": "^7.16.4",
|
|
33
|
-
"@rollup/plugin-babel": "^5.3.0",
|
|
34
|
-
"@rollup/plugin-commonjs": "^21.0.1",
|
|
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
36
|
"eslint-7": "npm:eslint@^7.0.0",
|
|
40
|
-
"eslint-9": "npm:eslint@^9.0.0"
|
|
41
|
-
"rollup": "^2.60.2"
|
|
37
|
+
"eslint-9": "npm:eslint@^9.0.0"
|
|
42
38
|
},
|
|
43
39
|
"keywords": [
|
|
44
40
|
"eslint",
|
|
@@ -50,7 +46,10 @@
|
|
|
50
46
|
"test:7": "jest --config jest.config-eslint-7.js",
|
|
51
47
|
"test:9": "jest --config jest.config-eslint-9.js",
|
|
52
48
|
"test": "npm run test:7 && npm run test:9",
|
|
53
|
-
"
|
|
54
|
-
"
|
|
49
|
+
"test:types": "tsc --noEmit",
|
|
50
|
+
"test:check": "npm run test:types",
|
|
51
|
+
"prebuild": "rm -rf dist",
|
|
52
|
+
"build": "tsc",
|
|
53
|
+
"prepublishOnly": "npm run build"
|
|
55
54
|
}
|
|
56
55
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Rule } from "eslint"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { findAncestor, isMobxDecorator } from "./utils"
|
|
4
4
|
|
|
5
5
|
// TODO support this.foo = 5; in constructor
|
|
6
6
|
// TODO? report on field as well
|
|
7
7
|
function create(context) {
|
|
8
|
-
const sourceCode = context.getSourceCode()
|
|
8
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
9
9
|
const autofixAnnotation = context.options[0]?.autofixAnnotation ?? true
|
|
10
10
|
|
|
11
11
|
function fieldToKey(field) {
|
|
@@ -42,7 +42,7 @@ function create(context) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const annotationProps = secondArg?.properties || []
|
|
45
|
-
const nonAnnotatedMembers = []
|
|
45
|
+
const nonAnnotatedMembers: any[] = []
|
|
46
46
|
let hasAnyDecorator = false
|
|
47
47
|
|
|
48
48
|
members.forEach(member => {
|
|
@@ -102,7 +102,7 @@ function create(context) {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
const rule: Rule.RuleModule = {
|
|
106
106
|
meta: {
|
|
107
107
|
type: "suggestion",
|
|
108
108
|
fixable: "code",
|
|
@@ -119,8 +119,7 @@ module.exports = {
|
|
|
119
119
|
],
|
|
120
120
|
docs: {
|
|
121
121
|
description: "enforce all fields being listen in `makeObservable`",
|
|
122
|
-
recommended: true
|
|
123
|
-
suggestion: false
|
|
122
|
+
recommended: true
|
|
124
123
|
},
|
|
125
124
|
messages: {
|
|
126
125
|
missingAnnotation:
|
|
@@ -129,3 +128,5 @@ module.exports = {
|
|
|
129
128
|
},
|
|
130
129
|
create
|
|
131
130
|
}
|
|
131
|
+
|
|
132
|
+
export default rule
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import fs from "fs"
|
|
2
|
+
import path from "path"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const path = require("path")
|
|
4
|
+
import type { ESLint, Linter } from "eslint"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import exhaustiveMakeObservable from "./exhaustive-make-observable"
|
|
7
|
+
import unconditionalMakeObservable from "./unconditional-make-observable"
|
|
8
|
+
import missingMakeObservable from "./missing-make-observable"
|
|
9
|
+
import missingObserver from "./missing-observer"
|
|
10
|
+
import noAnonymousObserver from "./no-anonymous-observer"
|
|
11
11
|
|
|
12
12
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"))
|
|
13
13
|
|
|
14
|
-
const pluginMobx = {
|
|
14
|
+
const pluginMobx: ESLint.Plugin = {
|
|
15
15
|
meta: {
|
|
16
16
|
name: pkg.name,
|
|
17
17
|
version: pkg.version
|
|
@@ -25,14 +25,17 @@ const pluginMobx = {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const recommendedRules = {
|
|
28
|
+
const recommendedRules: Linter.RulesRecord = {
|
|
29
29
|
"mobx/exhaustive-make-observable": "warn",
|
|
30
30
|
"mobx/unconditional-make-observable": "error",
|
|
31
31
|
"mobx/missing-make-observable": "error",
|
|
32
32
|
"mobx/missing-observer": "warn"
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
const plugin: typeof pluginMobx & {
|
|
36
|
+
configs: { recommended: Linter.LegacyConfig }
|
|
37
|
+
flatConfigs: { recommended: Linter.Config }
|
|
38
|
+
} = {
|
|
36
39
|
...pluginMobx,
|
|
37
40
|
configs: {
|
|
38
41
|
recommended: {
|
|
@@ -48,3 +51,5 @@ module.exports = {
|
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
}
|
|
54
|
+
|
|
55
|
+
export = plugin
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { findAncestor, isMobxDecorator } from './utils';
|
|
4
4
|
|
|
5
5
|
function create(context) {
|
|
6
|
-
const sourceCode = context.getSourceCode();
|
|
6
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
7
7
|
|
|
8
8
|
return {
|
|
9
9
|
'Decorator': decorator => {
|
|
@@ -53,14 +53,13 @@ function create(context) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
const rule: Rule.RuleModule = {
|
|
57
57
|
meta: {
|
|
58
58
|
type: 'problem',
|
|
59
59
|
fixable: 'code',
|
|
60
60
|
docs: {
|
|
61
61
|
description: 'prevents missing `makeObservable(this)` when using decorators',
|
|
62
62
|
recommended: true,
|
|
63
|
-
suggestion: false,
|
|
64
63
|
},
|
|
65
64
|
messages: {
|
|
66
65
|
missingMakeObservable: "Constructor is missing `makeObservable(this)`.",
|
|
@@ -68,4 +67,6 @@ module.exports = {
|
|
|
68
67
|
},
|
|
69
68
|
},
|
|
70
69
|
create,
|
|
71
|
-
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export default rule;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Rule } from "eslint"
|
|
2
2
|
|
|
3
3
|
function create(context) {
|
|
4
|
-
const sourceCode = context.getSourceCode()
|
|
4
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
5
5
|
|
|
6
6
|
return {
|
|
7
7
|
"FunctionDeclaration,FunctionExpression,ArrowFunctionExpression,ClassDeclaration,ClassExpression":
|
|
@@ -78,7 +78,7 @@ function create(context) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
const rule: Rule.RuleModule = {
|
|
82
82
|
meta: {
|
|
83
83
|
type: "problem",
|
|
84
84
|
fixable: "code",
|
|
@@ -92,3 +92,5 @@ module.exports = {
|
|
|
92
92
|
},
|
|
93
93
|
create
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
export default rule
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Rule } from "eslint"
|
|
2
2
|
|
|
3
3
|
function create(context) {
|
|
4
|
-
const sourceCode = context.getSourceCode()
|
|
4
|
+
const sourceCode = context.sourceCode ?? context.getSourceCode()
|
|
5
5
|
|
|
6
6
|
return {
|
|
7
7
|
'CallExpression[callee.name="observer"]': observer => {
|
|
@@ -49,7 +49,7 @@ function create(context) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
const rule: Rule.RuleModule = {
|
|
53
53
|
meta: {
|
|
54
54
|
type: "problem",
|
|
55
55
|
fixable: "code",
|
|
@@ -63,3 +63,5 @@ module.exports = {
|
|
|
63
63
|
},
|
|
64
64
|
create
|
|
65
65
|
}
|
|
66
|
+
|
|
67
|
+
export default rule
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { findAncestor } from './utils';
|
|
4
4
|
|
|
5
5
|
function create(context) {
|
|
6
6
|
return {
|
|
7
7
|
'CallExpression[callee.name=/(makeObservable|makeAutoObservable)/]': makeObservable => {
|
|
8
|
-
// Only
|
|
8
|
+
// Only interested about makeObservable(this, ...) inside constructor and not inside nested bindable function
|
|
9
9
|
const [firstArg] = makeObservable.arguments;
|
|
10
10
|
if (!firstArg) return;
|
|
11
11
|
if (firstArg.type !== 'ThisExpression') return;
|
|
@@ -29,7 +29,7 @@ function create(context) {
|
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const rule: Rule.RuleModule = {
|
|
33
33
|
meta: {
|
|
34
34
|
type: 'problem',
|
|
35
35
|
docs: {
|
|
@@ -41,4 +41,6 @@ module.exports = {
|
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
create,
|
|
44
|
-
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default rule;
|
|
@@ -1,29 +1,22 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const mobxDecorators = new Set(['observable', 'computed', 'action', 'flow', 'override']);
|
|
4
2
|
|
|
5
|
-
function isMobxDecorator(decorator) {
|
|
3
|
+
export function isMobxDecorator(decorator) {
|
|
6
4
|
return mobxDecorators.has(decorator.expression.name) // @foo
|
|
7
5
|
|| mobxDecorators.has(decorator.expression.callee?.name) // @foo()
|
|
8
6
|
|| mobxDecorators.has(decorator.expression.object?.name) // @foo.bar
|
|
9
7
|
}
|
|
10
8
|
|
|
11
|
-
function findAncestor(node, match) {
|
|
9
|
+
export function findAncestor(node, match) {
|
|
12
10
|
const { parent } = node;
|
|
13
11
|
if (!parent) return;
|
|
14
12
|
if (match(parent)) return parent;
|
|
15
13
|
return findAncestor(parent, match);
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
function assert(expr, error) {
|
|
16
|
+
export function assert(expr, error?) {
|
|
19
17
|
if (!expr) {
|
|
20
18
|
error ??= 'Assertion failed';
|
|
21
19
|
error = error instanceof Error ? error : new Error(error)
|
|
22
20
|
throw error;
|
|
23
21
|
}
|
|
24
22
|
}
|
|
25
|
-
|
|
26
|
-
module.exports = {
|
|
27
|
-
findAncestor,
|
|
28
|
-
isMobxDecorator,
|
|
29
|
-
}
|