eslint-plugin-crisp 1.5.2 → 1.5.3
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/index.js +3 -1
- package/package.json +1 -1
- package/recommended-vue.js +2 -6
- package/rules/vue-watch-handler.js +115 -0
package/index.js
CHANGED
|
@@ -58,6 +58,7 @@ import ruleVuePropsDeclarationLineBreak from "./rules/vue-props-declaration-line
|
|
|
58
58
|
import ruleVuePropsDeclarationMultiline from "./rules/vue-props-declaration-multiline.js";
|
|
59
59
|
import ruleVuePropsDeclarationOrder from "./rules/vue-props-declaration-order.js";
|
|
60
60
|
import ruleVueRefCase from "./rules/vue-ref-case.js";
|
|
61
|
+
import ruleVueWatchHandler from "./rules/vue-watch-handler.js";
|
|
61
62
|
|
|
62
63
|
import fs from "fs";
|
|
63
64
|
|
|
@@ -128,7 +129,8 @@ const plugin = {
|
|
|
128
129
|
"vue-props-declaration-line-break": ruleVuePropsDeclarationLineBreak,
|
|
129
130
|
"vue-props-declaration-multiline": ruleVuePropsDeclarationMultiline,
|
|
130
131
|
"vue-props-declaration-order": ruleVuePropsDeclarationOrder,
|
|
131
|
-
"vue-ref-case": ruleVueRefCase
|
|
132
|
+
"vue-ref-case": ruleVueRefCase,
|
|
133
|
+
"vue-watch-handler": ruleVueWatchHandler
|
|
132
134
|
}
|
|
133
135
|
};
|
|
134
136
|
|
package/package.json
CHANGED
package/recommended-vue.js
CHANGED
|
@@ -111,11 +111,6 @@ export default function configRecommendedVue(pluginCrisp) {
|
|
|
111
111
|
{
|
|
112
112
|
"selector": "SwitchCase > *.consequent[type!='BlockStatement']",
|
|
113
113
|
"message": "Switch cases without braces are disallowed."
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
{
|
|
117
|
-
"selector": "Property[key.name='watch'] > ObjectExpression > Property[value.type='FunctionExpression']",
|
|
118
|
-
"message": "Watchers must use the object form with a `handler` function."
|
|
119
114
|
}
|
|
120
115
|
],
|
|
121
116
|
"no-tabs": "error",
|
|
@@ -397,7 +392,8 @@ export default function configRecommendedVue(pluginCrisp) {
|
|
|
397
392
|
"crisp/vue-props-declaration-line-break": "error",
|
|
398
393
|
"crisp/vue-props-declaration-multiline": "error",
|
|
399
394
|
"crisp/vue-props-declaration-order": "error",
|
|
400
|
-
"crisp/vue-ref-case": "error"
|
|
395
|
+
"crisp/vue-ref-case": "error",
|
|
396
|
+
"crisp/vue-watch-handler": "error"
|
|
401
397
|
}
|
|
402
398
|
}
|
|
403
399
|
];
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const VALID_SIGNATURES = [
|
|
2
|
+
[],
|
|
3
|
+
["value"],
|
|
4
|
+
["newValue"],
|
|
5
|
+
["newValue", "oldValue"]
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
function getPropertyName(property) {
|
|
9
|
+
if (property.computed) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (property.key.type === "Identifier") {
|
|
14
|
+
return property.key.name;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return property.key.value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function hasValidSignature(handler) {
|
|
21
|
+
return VALID_SIGNATURES.some((signature) => {
|
|
22
|
+
return (
|
|
23
|
+
handler.params.length === signature.length &&
|
|
24
|
+
handler.params.every((parameter, index) => {
|
|
25
|
+
return (
|
|
26
|
+
parameter.type === "Identifier" &&
|
|
27
|
+
parameter.name === signature[index]
|
|
28
|
+
);
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
meta: {
|
|
36
|
+
type: "suggestion",
|
|
37
|
+
docs: {
|
|
38
|
+
description: "enforce Vue watcher handler form and signature",
|
|
39
|
+
category: "Stylistic Issues",
|
|
40
|
+
recommended: false
|
|
41
|
+
},
|
|
42
|
+
fixable: null,
|
|
43
|
+
schema: [],
|
|
44
|
+
messages: {
|
|
45
|
+
objectForm: "Watchers must use the object form with a `handler` function.",
|
|
46
|
+
missingHandler: "Watcher objects must define a `handler` function.",
|
|
47
|
+
invalidHandler: "Watcher `handler` must be a function.",
|
|
48
|
+
invalidSignature:
|
|
49
|
+
"Watcher `handler` must use one of these signatures: " +
|
|
50
|
+
"`handler()`, `handler(value)`, `handler(newValue)`, or " +
|
|
51
|
+
"`handler(newValue, oldValue)`."
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
create(context) {
|
|
56
|
+
return {
|
|
57
|
+
'Property[key.name="watch"] > ObjectExpression'(node) {
|
|
58
|
+
node.properties.forEach((watcher) => {
|
|
59
|
+
if (watcher.type !== "Property") {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (watcher.value.type !== "ObjectExpression") {
|
|
64
|
+
context.report({
|
|
65
|
+
node: watcher,
|
|
66
|
+
messageId: "objectForm"
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const handlerProperty = watcher.value.properties.find((property) => {
|
|
73
|
+
return (
|
|
74
|
+
property.type === "Property" &&
|
|
75
|
+
getPropertyName(property) === "handler"
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (!handlerProperty) {
|
|
80
|
+
context.report({
|
|
81
|
+
node: watcher,
|
|
82
|
+
messageId: "missingHandler"
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const handler = handlerProperty.value;
|
|
89
|
+
|
|
90
|
+
if (
|
|
91
|
+
handlerProperty.kind !== "init" ||
|
|
92
|
+
(
|
|
93
|
+
handler.type !== "FunctionExpression" &&
|
|
94
|
+
handler.type !== "ArrowFunctionExpression"
|
|
95
|
+
)
|
|
96
|
+
) {
|
|
97
|
+
context.report({
|
|
98
|
+
node: handlerProperty,
|
|
99
|
+
messageId: "invalidHandler"
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!hasValidSignature(handler)) {
|
|
106
|
+
context.report({
|
|
107
|
+
node: handlerProperty,
|
|
108
|
+
messageId: "invalidSignature"
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
};
|