Skip to content

Commit f2bafa4

Browse files
author
Casey Visco
committed
Refactor to ES6
This is an almost complete rewrite of most of the rules. The goal started as a simple update to take advantage of some newer ES6 features but ended up being a complete refactor to make the code more concise and, hopefully, readable.
1 parent 7426782 commit f2bafa4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2144
-2287
lines changed

.eslintrc.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,16 @@ rules:
2222
- error
2323
- declaration
2424
- allowArrowFunctions: true
25+
quote-props:
26+
- error
27+
- consistent
28+
no-undefined: off
29+
no-multi-spaces:
30+
- error
31+
- exceptions: { VariableDeclarator: true }
32+
curly:
33+
- error
34+
- multi-line
35+
key-spacing:
36+
- error
37+
- mode: minimum

lib/rules/amd-function-arity.js

Lines changed: 89 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,110 @@
11
/**
2-
* @fileoverview Ensure AMD-style callbacks contain correct number of arguments
3-
* @author Kevin Partington
2+
* @file Rule to ensure AMD-style callbacks contain correct number of
3+
* arguments
4+
* @author Kevin Partington
45
*/
56

67
"use strict";
78

8-
const util = require("../util");
9+
const rjs = require("../utils/rjs");
910
const ast = require("../utils/ast");
1011

11-
module.exports = {
12-
meta: {
13-
docs: {},
14-
schema: [
15-
{
16-
"type": "object",
17-
"properties": {
18-
"allowExtraDependencies": {
19-
anyOf: [
20-
{
21-
"type": "boolean",
22-
"default": false
23-
},
24-
{
25-
"type": "array",
26-
"uniqueItems": true,
27-
"items": {
28-
"type": "string"
29-
}
30-
}
31-
]
12+
const hasCallback = ast.hasCallback;
13+
const getDependencyNodes = rjs.getDependencyNodes;
14+
const getModuleFunction = rjs.getModuleFunction;
15+
const isAmdDefine = rjs.isAmdDefine;
16+
const isRequireCall = rjs.isRequireCall;
17+
18+
// -----------------------------------------------------------------------------
19+
// Configuration
20+
// -----------------------------------------------------------------------------
21+
22+
const docs = {
23+
description: "Ensure AMD-style callbacks contain correct number of arguments",
24+
category: "Stylistic Choices",
25+
recommended: false
26+
};
27+
28+
const schema = [
29+
{
30+
type: "object",
31+
properties: {
32+
allowExtraDependencies: {
33+
anyOf: [
34+
{
35+
type: "boolean",
36+
default: false
37+
},
38+
{
39+
type: "array",
40+
uniqueItems: true,
41+
items: {
42+
type: "string"
43+
}
3244
}
33-
},
34-
"additionalProperties": false
45+
]
3546
}
36-
]
37-
},
47+
},
48+
additionalProperties: false
49+
}
50+
];
3851

39-
create: function (context) {
40-
const allowExtraDependencies = (context.options && context.options[0] && context.options[0].allowExtraDependencies) || false;
41-
const TOO_MANY_PARAMS_MESSAGE = "Too many parameters in {{functionName}} callback (expected {{expected}}, found {{actual}}).";
42-
const TOO_FEW_PARAMS_MESSAGE = "Not enough parameters in {{functionName}} callback (expected {{expected}}, found {{actual}}).";
52+
const defaults = {
53+
allowExtraDependencies: false
54+
};
4355

44-
function allUnassignedPathsAreAllowed(dependencyNodes, callbackParams) {
45-
if (typeof allowExtraDependencies === "boolean") {
46-
return allowExtraDependencies;
47-
}
56+
// -----------------------------------------------------------------------------
57+
// Helpers
58+
// -----------------------------------------------------------------------------
4859

49-
const unassignedPaths = dependencyNodes.slice(callbackParams.length);
60+
const isBoolean = (value) => typeof value === "boolean";
61+
const unassigned = (paths, params) => paths.slice(params.length);
62+
const includes = (list) => (path) => list.indexOf(path.value) !== -1;
5063

51-
return unassignedPaths.every(function (path) {
52-
return allowExtraDependencies.indexOf(path.value) !== -1;
53-
});
54-
}
64+
const isAmdWithCallback = (node) =>
65+
isAmdDefine(node) || isRequireCall(node) && hasCallback(node);
66+
67+
const reportTooFew = (expected, actual) =>
68+
`Not enough parameters in callback (expected ${expected}, found ${actual}).`;
5569

56-
function checkArity(node, funcName) {
57-
const dependencyNodes = util.getDependencyNodes(node);
70+
const reportTooMany = (expected, actual) =>
71+
`Too many parameters in callback (expected ${expected}, found ${actual}).`;
5872

59-
if (!dependencyNodes) {
60-
return;
73+
// -----------------------------------------------------------------------------
74+
// Rule Definition
75+
// -----------------------------------------------------------------------------
76+
77+
function create(context) {
78+
const opts = Object.assign({}, defaults, context.options[0]);
79+
const allowed = opts.allowExtraDependencies;
80+
81+
const isAllowed = (paths) =>
82+
isBoolean(allowed) ? allowed : paths.every(includes(allowed));
83+
84+
return {
85+
CallExpression(node) {
86+
if (!isAmdWithCallback(node)) return;
87+
88+
const paths = getDependencyNodes(node);
89+
const pathCount = paths.length;
90+
91+
if (!pathCount) return;
92+
93+
const params = getModuleFunction(node).params;
94+
const paramCount = params.length;
95+
96+
if (pathCount < paramCount) {
97+
context.report(node, reportTooMany(pathCount, paramCount));
6198
}
6299

63-
const dependencyCount = dependencyNodes.length;
64-
const callbackParams = util.getAmdCallback(node).params;
65-
const actualParamCount = callbackParams.length;
66-
67-
if (dependencyCount < actualParamCount) {
68-
context.report(node, TOO_MANY_PARAMS_MESSAGE, {
69-
functionName: funcName,
70-
expected: dependencyCount,
71-
actual: actualParamCount
72-
});
73-
} else if (dependencyCount > actualParamCount && !allUnassignedPathsAreAllowed(dependencyNodes, callbackParams)) {
74-
context.report(node, TOO_FEW_PARAMS_MESSAGE, {
75-
functionName: funcName,
76-
expected: dependencyCount,
77-
actual: actualParamCount
78-
});
100+
if (pathCount > paramCount && !isAllowed(unassigned(paths, params))) {
101+
context.report(node, reportTooFew(pathCount, paramCount));
79102
}
80103
}
104+
};
105+
}
81106

82-
return {
83-
"CallExpression": function (node) {
84-
/* istanbul ignore else: correctly does nothing */
85-
if (util.isDefineCall(node) && util.isAmdDefine(node)) {
86-
checkArity(node, "define");
87-
} else if (util.isRequireCall(node) && ast.hasCallback(node)) {
88-
checkArity(node, node.callee.name);
89-
}
90-
}
91-
};
92-
}
107+
module.exports = {
108+
meta: { docs, schema },
109+
create
93110
};

lib/rules/enforce-define.js

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,77 @@
11
/**
2-
* @fileoverview Disallow files that are not wrapped in a call to `define`
3-
* @author Casey Visco
2+
* @file Rule to disallow files that are not wrapped in a call to `define`
3+
* @author Casey Visco <[email protected]>
44
*/
55

66
"use strict";
77

88
const path = require("path");
9-
const util = require("../util");
9+
const rjs = require("../utils/rjs");
1010
const ast = require("../utils/ast");
1111

12-
module.exports = {
13-
meta: {
14-
docs: {},
15-
schema: [
12+
const isDefineCall = rjs.isDefineCall;
13+
const isExprStatement = ast.isExprStatement;
14+
const basename = path.basename;
15+
16+
// -----------------------------------------------------------------------------
17+
// Configuration
18+
// -----------------------------------------------------------------------------
19+
20+
const docs = {
21+
description: "Disallow files that are not wrapped in a call to `define`",
22+
category: "Stylistic Choices",
23+
recommended: false
24+
};
25+
26+
const schema = [
27+
{
28+
anyOf: [
1629
{
17-
"anyOf": [
18-
{
19-
"type": "string"
20-
},
21-
{
22-
"type": "array",
23-
"uniqueItems": true,
24-
"items": {
25-
"type": "string"
26-
}
27-
}
28-
]
30+
type: "string"
31+
},
32+
{
33+
type: "array",
34+
uniqueItems: true,
35+
items: {
36+
type: "string"
37+
}
2938
}
3039
]
31-
},
32-
33-
create: function (context) {
34-
const MESSAGE = "File must be wrapped in a `define` call";
35-
const ignoredFiles = context.options[0] || [];
36-
37-
/**
38-
* Determine if supplied `filename` is allowed to not be wrapped in a
39-
* `define` call.
40-
* @private
41-
* @param {String} filename - filename to test
42-
* @returns {Boolean} true if filename is allowed
43-
*/
44-
function isIgnoredFile(filename) {
45-
const basename = path.basename(filename);
46-
return ignoredFiles.indexOf(basename) !== -1;
47-
}
40+
}
41+
];
4842

49-
return {
50-
"Program": function (node) {
51-
const filename = context.getFilename();
43+
const message = "File must be wrapped in a `define` call";
5244

53-
if (isIgnoredFile(filename)) {
54-
return;
55-
}
45+
// -----------------------------------------------------------------------------
46+
// Helpers
47+
// -----------------------------------------------------------------------------
5648

57-
for (let i = 0, length = node.body.length; i < length; i += 1) {
58-
const child = node.body[i];
49+
const includes = (list, item) => list.indexOf(item) !== -1;
5950

60-
if (!(ast.isExprStatement(child) && util.isDefineCall(child.expression))) {
61-
context.report(node, MESSAGE);
62-
break;
63-
}
64-
}
51+
const isDefineExpr = (child) =>
52+
isExprStatement(child) && isDefineCall(child.expression);
53+
54+
// -----------------------------------------------------------------------------
55+
// Rule Definition
56+
// -----------------------------------------------------------------------------
57+
58+
function create(context) {
59+
const ignoredFiles = context.options[0] || [];
60+
61+
return {
62+
Program(node) {
63+
const filename = basename(context.getFilename());
64+
65+
if (includes(ignoredFiles, filename)) return;
66+
67+
if (!node.body.every(isDefineExpr)) {
68+
context.report(node, message);
6569
}
66-
};
67-
}
70+
}
71+
};
72+
}
73+
74+
module.exports = {
75+
meta: { docs, schema },
76+
create
6877
};

lib/rules/no-amd-define.js

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,43 @@
11
/**
2-
* @fileoverview Disallow use of AMD (dependency array) form of `define`
3-
* @author Casey Visco
2+
* @file Rule to disallow use of AMD (dependency array) form of `define`
3+
* @author Casey Visco <[email protected]>
44
*/
55

66
"use strict";
77

8-
const util = require("../util");
8+
const rjs = require("../utils/rjs");
99

10-
module.exports = {
11-
meta: {
12-
docs: {},
13-
schema: []
14-
},
15-
16-
create: function (context) {
17-
const MESSAGE = "AMD form of `define` is not allowed.";
18-
19-
return {
20-
"CallExpression": function (node) {
21-
if (util.isDefineCall(node) && util.isAmdDefine(node)) {
22-
context.report(node, MESSAGE);
23-
}
10+
const isAmdDefine = rjs.isAmdDefine;
11+
12+
// -----------------------------------------------------------------------------
13+
// Configuration
14+
// -----------------------------------------------------------------------------
15+
16+
const docs = {
17+
description: "Disallow use of AMD (dependency array) form of `define`",
18+
category: "Stylistic Choices",
19+
recommended: false
20+
};
21+
22+
const schema = [];
23+
24+
const message = "AMD form of `define` is not allowed.";
25+
26+
// -----------------------------------------------------------------------------
27+
// Rule Definition
28+
// -----------------------------------------------------------------------------
29+
30+
function create(context) {
31+
return {
32+
CallExpression(node) {
33+
if (isAmdDefine(node)) {
34+
context.report(node, message);
2435
}
25-
};
26-
}
36+
}
37+
};
38+
}
39+
40+
module.exports = {
41+
meta: { docs, schema },
42+
create
2743
};

0 commit comments

Comments
 (0)