1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | const ALLOW_OPTIONS = Object.freeze([
|
13 | "functions",
|
14 | "arrowFunctions",
|
15 | "generatorFunctions",
|
16 | "methods",
|
17 | "generatorMethods",
|
18 | "getters",
|
19 | "setters",
|
20 | "constructors"
|
21 | ]);
|
22 | const SHOW_KIND = Object.freeze({
|
23 | functions: "function",
|
24 | arrowFunctions: "arrow function",
|
25 | generatorFunctions: "generator function",
|
26 | asyncFunctions: "async function",
|
27 | methods: "method",
|
28 | generatorMethods: "generator method",
|
29 | asyncMethods: "async method",
|
30 | getters: "getter",
|
31 | setters: "setter",
|
32 | constructors: "constructor"
|
33 | });
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | function getKind(node) {
|
47 | const parent = node.parent;
|
48 | let kind = "";
|
49 |
|
50 | if (node.type === "ArrowFunctionExpression") {
|
51 | return "arrowFunctions";
|
52 | }
|
53 |
|
54 |
|
55 | if (parent.type === "Property") {
|
56 | if (parent.kind === "get") {
|
57 | return "getters";
|
58 | }
|
59 | if (parent.kind === "set") {
|
60 | return "setters";
|
61 | }
|
62 | kind = parent.method ? "methods" : "functions";
|
63 |
|
64 | } else if (parent.type === "MethodDefinition") {
|
65 | if (parent.kind === "get") {
|
66 | return "getters";
|
67 | }
|
68 | if (parent.kind === "set") {
|
69 | return "setters";
|
70 | }
|
71 | if (parent.kind === "constructor") {
|
72 | return "constructors";
|
73 | }
|
74 | kind = "methods";
|
75 |
|
76 | } else {
|
77 | kind = "functions";
|
78 | }
|
79 |
|
80 |
|
81 | let prefix = "";
|
82 |
|
83 | if (node.generator) {
|
84 | prefix = "generator";
|
85 | } else if (node.async) {
|
86 | prefix = "async";
|
87 | } else {
|
88 | return kind;
|
89 | }
|
90 | return prefix + kind[0].toUpperCase() + kind.slice(1);
|
91 | }
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | module.exports = {
|
98 | meta: {
|
99 | docs: {
|
100 | description: "disallow empty functions",
|
101 | category: "Best Practices",
|
102 | recommended: false
|
103 | },
|
104 |
|
105 | schema: [
|
106 | {
|
107 | type: "object",
|
108 | properties: {
|
109 | allow: {
|
110 | type: "array",
|
111 | items: {enum: ALLOW_OPTIONS},
|
112 | uniqueItems: true
|
113 | }
|
114 | },
|
115 | additionalProperties: false
|
116 | }
|
117 | ]
|
118 | },
|
119 |
|
120 | create(context) {
|
121 | const options = context.options[0] || {};
|
122 | const allowed = options.allow || [];
|
123 |
|
124 | const sourceCode = context.getSourceCode();
|
125 |
|
126 | |
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 | function reportIfEmpty(node) {
|
139 | const kind = getKind(node);
|
140 |
|
141 | if (allowed.indexOf(kind) === -1 &&
|
142 | node.body.type === "BlockStatement" &&
|
143 | node.body.body.length === 0 &&
|
144 | sourceCode.getComments(node.body).trailing.length === 0
|
145 | ) {
|
146 | context.report({
|
147 | node,
|
148 | loc: node.body.loc.start,
|
149 | message: "Unexpected empty {{kind}}.",
|
150 | data: {
|
151 | kind: SHOW_KIND[kind]
|
152 | }
|
153 | });
|
154 | }
|
155 | }
|
156 |
|
157 | return {
|
158 | ArrowFunctionExpression: reportIfEmpty,
|
159 | FunctionDeclaration: reportIfEmpty,
|
160 | FunctionExpression: reportIfEmpty
|
161 | };
|
162 | }
|
163 | };
|