eslint 4.11.0 → 4.13.1
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 +34 -0
- package/README.md +3 -3
- package/conf/environments.js +128 -4
- package/conf/eslint-recommended.js +1 -0
- package/lib/linter.js +29 -22
- package/lib/rules/camelcase.js +27 -16
- package/lib/rules/eol-last.js +8 -0
- package/lib/rules/implicit-arrow-linebreak.js +86 -0
- package/lib/rules/no-restricted-imports.js +137 -28
- package/lib/rules/prefer-destructuring.js +1 -1
- package/lib/rules/semi.js +132 -37
- package/lib/rules/sort-vars.js +45 -10
- package/lib/rules/space-in-parens.js +1 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
v4.13.1 - December 11, 2017
|
2
|
+
|
3
|
+
* b72dc83 Fix: eol-last allow empty-string to always pass (refs #9534) (#9696) (Kevin Partington)
|
4
|
+
* d80aa7c Fix: camelcase destructure leading/trailing underscore (fixes #9700) (#9701) (Kevin Partington)
|
5
|
+
* d49d9d0 Docs: Add missing period to the README (#9702) (Kevin Partington)
|
6
|
+
* 4564fe0 Chore: no-invalid-meta crash if no export assignment (refs #9534) (#9698) (Kevin Partington)
|
7
|
+
|
8
|
+
v4.13.0 - December 8, 2017
|
9
|
+
|
10
|
+
* 256481b Update: update handling of destructuring in camelcase (fixes #8511) (#9468) (Erin)
|
11
|
+
* d067ae1 Docs: Don’t use undocumented array-style configuration for max-len (#9690) (Jed Fox)
|
12
|
+
* 1ad3091 Chore: fix test-suite to work with node master (#9688) (Myles Borins)
|
13
|
+
* cdb1488 Docs: Adds an example with try/catch. (#9672) (Jaap Taal)
|
14
|
+
|
15
|
+
v4.12.1 - November 30, 2017
|
16
|
+
|
17
|
+
* 1e362a0 Revert "Fix: Use XML 1.1 on XML formatters (fixes #9607) (#9608)" (#9667) (Kevin Partington)
|
18
|
+
|
19
|
+
v4.12.0 - November 25, 2017
|
20
|
+
|
21
|
+
* 76dab18 Upgrade: doctrine@^2.0.2 (#9656) (Kevin Partington)
|
22
|
+
* 28c9c8e New: add a Linter#defineParser function (#9321) (Ives van Hoorne)
|
23
|
+
* 5619910 Update: Add autofix for `sort-vars` (#9496) (Trevin Hofmann)
|
24
|
+
* 71eedbf Update: add `beforeStatementContinuationChars` to semi (fixes #9521) (#9594) (Toru Nagashima)
|
25
|
+
* 4118f14 New: Adds implicit-arrow-linebreak rule (refs #9510) (#9629) (Sharmila Jesupaul)
|
26
|
+
* 208fb0f Fix: Use XML 1.1 on XML formatters (fixes #9607) (#9608) (Daniel Reigada)
|
27
|
+
* 6e04f14 Upgrade: `globals` to 11.0.1 (fixes #9614) (#9632) (Toru Nagashima)
|
28
|
+
* e13d439 Fix: space-in-parens crash (#9655) (Toru Nagashima)
|
29
|
+
* 92171cc Docs: Updating migration guide for single-line disable (#9385) (Justin Helmer)
|
30
|
+
* f39ffe7 Docs: remove extra punctuation from readme (#9640) (Teddy Katz)
|
31
|
+
* a015234 Fix: prefer-destructuring false positive on "super" (fixes #9625) (#9626) (Kei Ito)
|
32
|
+
* 0cf081e Update: add importNames option to no-restricted-imports (#9506) (Benjamin R Gibson)
|
33
|
+
* 332c214 Docs: Add @platinumazure to TSC (#9618) (Ilya Volodin)
|
34
|
+
|
1
35
|
v4.11.0 - November 10, 2017
|
2
36
|
|
3
37
|
* d4557a6 Docs: disallow use of the comma operator using no-restricted-syntax (#9585) (薛定谔的猫)
|
package/README.md
CHANGED
@@ -116,6 +116,7 @@ These folks keep the project moving and are resources for help.
|
|
116
116
|
* Alberto Rodríguez ([@alberto](https://github.com/alberto))
|
117
117
|
* Kai Cataldo ([@kaicataldo](https://github.com/kaicataldo))
|
118
118
|
* Teddy Katz ([@not-an-aardvark](https://github.com/not-an-aardvark))
|
119
|
+
* Kevin Partington ([@platinumazure](https://github.com/platinumazure))
|
119
120
|
|
120
121
|
### Development Team
|
121
122
|
|
@@ -130,7 +131,6 @@ These folks keep the project moving and are resources for help.
|
|
130
131
|
* Henry Zhu ([@hzoo](https://github.com/hzoo))
|
131
132
|
* Marat Dulin ([@mdevils](https://github.com/mdevils))
|
132
133
|
* Alexej Yaroshevich ([@zxqfox](https://github.com/zxqfox))
|
133
|
-
* Kevin Partington ([@platinumazure](https://github.com/platinumazure))
|
134
134
|
* Vitor Balocco ([@vitorbal](https://github.com/vitorbal))
|
135
135
|
* James Henry ([@JamesHenry](https://github.com/JamesHenry))
|
136
136
|
* Reyad Attiyat ([@soda0289](https://github.com/soda0289))
|
@@ -225,7 +225,7 @@ In all cases, make sure your plugins' peerDependencies have been installed as we
|
|
225
225
|
|
226
226
|
### Does ESLint support JSX?
|
227
227
|
|
228
|
-
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring)
|
228
|
+
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring)). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics.
|
229
229
|
|
230
230
|
### What about ECMAScript 6 support?
|
231
231
|
|
@@ -239,7 +239,7 @@ Once a language feature has been adopted into the ECMAScript standard (stage 4 a
|
|
239
239
|
|
240
240
|
### Where to ask for help?
|
241
241
|
|
242
|
-
Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://gitter.im/eslint/eslint)
|
242
|
+
Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://gitter.im/eslint/eslint).
|
243
243
|
|
244
244
|
|
245
245
|
[npm-image]: https://img.shields.io/npm/v/eslint.svg?style=flat-square
|
package/conf/environments.js
CHANGED
@@ -17,10 +17,126 @@ const globals = require("globals");
|
|
17
17
|
module.exports = {
|
18
18
|
builtin: globals.es5,
|
19
19
|
browser: {
|
20
|
-
|
20
|
+
|
21
|
+
/*
|
22
|
+
* For backward compatibility.
|
23
|
+
* Remove those on the next major release.
|
24
|
+
*/
|
25
|
+
globals: Object.assign(
|
26
|
+
{
|
27
|
+
AutocompleteErrorEvent: false,
|
28
|
+
CDATASection: false,
|
29
|
+
ClientRect: false,
|
30
|
+
ClientRectList: false,
|
31
|
+
CSSAnimation: false,
|
32
|
+
CSSTransition: false,
|
33
|
+
CSSUnknownRule: false,
|
34
|
+
CSSViewportRule: false,
|
35
|
+
Debug: false,
|
36
|
+
DocumentTimeline: false,
|
37
|
+
DOMSettableTokenList: false,
|
38
|
+
ElementTimeControl: false,
|
39
|
+
FederatedCredential: false,
|
40
|
+
FileError: false,
|
41
|
+
HTMLAppletElement: false,
|
42
|
+
HTMLBlockquoteElement: false,
|
43
|
+
HTMLIsIndexElement: false,
|
44
|
+
HTMLKeygenElement: false,
|
45
|
+
HTMLLayerElement: false,
|
46
|
+
IDBEnvironment: false,
|
47
|
+
InputMethodContext: false,
|
48
|
+
MediaKeyError: false,
|
49
|
+
MediaKeyEvent: false,
|
50
|
+
MediaKeys: false,
|
51
|
+
opera: false,
|
52
|
+
PasswordCredential: false,
|
53
|
+
ReadableByteStream: false,
|
54
|
+
SharedKeyframeList: false,
|
55
|
+
showModalDialog: false,
|
56
|
+
SiteBoundCredential: false,
|
57
|
+
SVGAltGlyphDefElement: false,
|
58
|
+
SVGAltGlyphElement: false,
|
59
|
+
SVGAltGlyphItemElement: false,
|
60
|
+
SVGAnimateColorElement: false,
|
61
|
+
SVGAnimatedPathData: false,
|
62
|
+
SVGAnimatedPoints: false,
|
63
|
+
SVGColor: false,
|
64
|
+
SVGColorProfileElement: false,
|
65
|
+
SVGColorProfileRule: false,
|
66
|
+
SVGCSSRule: false,
|
67
|
+
SVGCursorElement: false,
|
68
|
+
SVGDocument: false,
|
69
|
+
SVGElementInstance: false,
|
70
|
+
SVGElementInstanceList: false,
|
71
|
+
SVGEvent: false,
|
72
|
+
SVGExternalResourcesRequired: false,
|
73
|
+
SVGFilterPrimitiveStandardAttributes: false,
|
74
|
+
SVGFitToViewBox: false,
|
75
|
+
SVGFontElement: false,
|
76
|
+
SVGFontFaceElement: false,
|
77
|
+
SVGFontFaceFormatElement: false,
|
78
|
+
SVGFontFaceNameElement: false,
|
79
|
+
SVGFontFaceSrcElement: false,
|
80
|
+
SVGFontFaceUriElement: false,
|
81
|
+
SVGGlyphElement: false,
|
82
|
+
SVGGlyphRefElement: false,
|
83
|
+
SVGHKernElement: false,
|
84
|
+
SVGICCColor: false,
|
85
|
+
SVGLangSpace: false,
|
86
|
+
SVGLocatable: false,
|
87
|
+
SVGMissingGlyphElement: false,
|
88
|
+
SVGPaint: false,
|
89
|
+
SVGPathSeg: false,
|
90
|
+
SVGPathSegArcAbs: false,
|
91
|
+
SVGPathSegArcRel: false,
|
92
|
+
SVGPathSegClosePath: false,
|
93
|
+
SVGPathSegCurvetoCubicAbs: false,
|
94
|
+
SVGPathSegCurvetoCubicRel: false,
|
95
|
+
SVGPathSegCurvetoCubicSmoothAbs: false,
|
96
|
+
SVGPathSegCurvetoCubicSmoothRel: false,
|
97
|
+
SVGPathSegCurvetoQuadraticAbs: false,
|
98
|
+
SVGPathSegCurvetoQuadraticRel: false,
|
99
|
+
SVGPathSegCurvetoQuadraticSmoothAbs: false,
|
100
|
+
SVGPathSegCurvetoQuadraticSmoothRel: false,
|
101
|
+
SVGPathSegLinetoAbs: false,
|
102
|
+
SVGPathSegLinetoHorizontalAbs: false,
|
103
|
+
SVGPathSegLinetoHorizontalRel: false,
|
104
|
+
SVGPathSegLinetoRel: false,
|
105
|
+
SVGPathSegLinetoVerticalAbs: false,
|
106
|
+
SVGPathSegLinetoVerticalRel: false,
|
107
|
+
SVGPathSegList: false,
|
108
|
+
SVGPathSegMovetoAbs: false,
|
109
|
+
SVGPathSegMovetoRel: false,
|
110
|
+
SVGRenderingIntent: false,
|
111
|
+
SVGStylable: false,
|
112
|
+
SVGTests: false,
|
113
|
+
SVGTransformable: false,
|
114
|
+
SVGTRefElement: false,
|
115
|
+
SVGURIReference: false,
|
116
|
+
SVGViewSpec: false,
|
117
|
+
SVGVKernElement: false,
|
118
|
+
SVGZoomAndPan: false,
|
119
|
+
SVGZoomEvent: false,
|
120
|
+
TimeEvent: false,
|
121
|
+
XDomainRequest: false,
|
122
|
+
XMLHttpRequestProgressEvent: false,
|
123
|
+
XPathException: false,
|
124
|
+
XPathNamespace: false,
|
125
|
+
XPathNSResolver: false
|
126
|
+
},
|
127
|
+
globals.browser
|
128
|
+
)
|
21
129
|
},
|
22
130
|
node: {
|
23
|
-
|
131
|
+
|
132
|
+
/*
|
133
|
+
* For backward compatibility.
|
134
|
+
* Remove those on the next major release.
|
135
|
+
*/
|
136
|
+
globals: Object.assign(
|
137
|
+
{ arguments: false, GLOBAL: false, root: false },
|
138
|
+
globals.node
|
139
|
+
),
|
24
140
|
parserOptions: {
|
25
141
|
ecmaFeatures: {
|
26
142
|
globalReturn: true
|
@@ -51,7 +167,15 @@ module.exports = {
|
|
51
167
|
globals: globals.jasmine
|
52
168
|
},
|
53
169
|
jest: {
|
54
|
-
|
170
|
+
|
171
|
+
/*
|
172
|
+
* For backward compatibility.
|
173
|
+
* Remove those on the next major release.
|
174
|
+
*/
|
175
|
+
globals: Object.assign(
|
176
|
+
{ check: false, gen: false },
|
177
|
+
globals.jest
|
178
|
+
)
|
55
179
|
},
|
56
180
|
phantomjs: {
|
57
181
|
globals: globals.phantomjs
|
@@ -96,7 +220,7 @@ module.exports = {
|
|
96
220
|
globals: globals.webextensions
|
97
221
|
},
|
98
222
|
es6: {
|
99
|
-
globals: globals.
|
223
|
+
globals: globals.es2015,
|
100
224
|
parserOptions: {
|
101
225
|
ecmaVersion: 6
|
102
226
|
}
|
package/lib/linter.js
CHANGED
@@ -507,13 +507,13 @@ function getRuleOptions(ruleConfig) {
|
|
507
507
|
* as possible
|
508
508
|
* @param {string} text The text to parse.
|
509
509
|
* @param {Object} providedParserOptions Options to pass to the parser
|
510
|
-
* @param {
|
510
|
+
* @param {Object} parser The parser module
|
511
511
|
* @param {string} filePath The path to the file being parsed.
|
512
512
|
* @returns {{success: false, error: Problem}|{success: true,ast: ASTNode, services: Object}}
|
513
513
|
* An object containing the AST and parser services if parsing was successful, or the error if parsing failed
|
514
514
|
* @private
|
515
515
|
*/
|
516
|
-
function parse(text, providedParserOptions,
|
516
|
+
function parse(text, providedParserOptions, parser, filePath) {
|
517
517
|
|
518
518
|
const parserOptions = Object.assign({}, providedParserOptions, {
|
519
519
|
loc: true,
|
@@ -524,25 +524,6 @@ function parse(text, providedParserOptions, parserName, filePath) {
|
|
524
524
|
filePath
|
525
525
|
});
|
526
526
|
|
527
|
-
let parser;
|
528
|
-
|
529
|
-
try {
|
530
|
-
parser = require(parserName);
|
531
|
-
} catch (ex) {
|
532
|
-
return {
|
533
|
-
success: false,
|
534
|
-
error: {
|
535
|
-
ruleId: null,
|
536
|
-
fatal: true,
|
537
|
-
severity: 2,
|
538
|
-
source: null,
|
539
|
-
message: ex.message,
|
540
|
-
line: 0,
|
541
|
-
column: 0
|
542
|
-
}
|
543
|
-
};
|
544
|
-
}
|
545
|
-
|
546
527
|
/*
|
547
528
|
* Check for parsing errors first. If there's a parsing error, nothing
|
548
529
|
* else can happen. However, a parsing error does not throw an error
|
@@ -706,6 +687,7 @@ module.exports = class Linter {
|
|
706
687
|
this.version = pkg.version;
|
707
688
|
|
708
689
|
this.rules = new Rules();
|
690
|
+
this._parsers = new Map();
|
709
691
|
this.environments = new Environments();
|
710
692
|
}
|
711
693
|
|
@@ -785,10 +767,25 @@ module.exports = class Linter {
|
|
785
767
|
return [];
|
786
768
|
}
|
787
769
|
|
770
|
+
let parser;
|
771
|
+
|
772
|
+
try {
|
773
|
+
parser = this._parsers.get(config.parser) || require(config.parser);
|
774
|
+
} catch (ex) {
|
775
|
+
return [{
|
776
|
+
ruleId: null,
|
777
|
+
fatal: true,
|
778
|
+
severity: 2,
|
779
|
+
source: null,
|
780
|
+
message: ex.message,
|
781
|
+
line: 0,
|
782
|
+
column: 0
|
783
|
+
}];
|
784
|
+
}
|
788
785
|
const parseResult = parse(
|
789
786
|
stripUnicodeBOM(text).replace(astUtils.SHEBANG_MATCHER, (match, captured) => `//${captured}`),
|
790
787
|
config.parserOptions,
|
791
|
-
|
788
|
+
parser,
|
792
789
|
filename
|
793
790
|
);
|
794
791
|
|
@@ -1036,6 +1033,16 @@ module.exports = class Linter {
|
|
1036
1033
|
return this.rules.getAllLoadedRules();
|
1037
1034
|
}
|
1038
1035
|
|
1036
|
+
/**
|
1037
|
+
* Define a new parser module
|
1038
|
+
* @param {any} parserId Name of the parser
|
1039
|
+
* @param {any} parserModule The parser object
|
1040
|
+
* @returns {void}
|
1041
|
+
*/
|
1042
|
+
defineParser(parserId, parserModule) {
|
1043
|
+
this._parsers.set(parserId, parserModule);
|
1044
|
+
}
|
1045
|
+
|
1039
1046
|
/**
|
1040
1047
|
* Performs multiple autofix passes over the text until as many fixes as possible
|
1041
1048
|
* have been applied.
|
package/lib/rules/camelcase.js
CHANGED
@@ -92,34 +92,45 @@ module.exports = {
|
|
92
92
|
}
|
93
93
|
|
94
94
|
// Always report underscored object names
|
95
|
-
if (node.parent.object.type === "Identifier" &&
|
96
|
-
node.parent.object.name === node.name &&
|
97
|
-
isUnderscored(name)) {
|
95
|
+
if (node.parent.object.type === "Identifier" && node.parent.object.name === node.name && isUnderscored(name)) {
|
98
96
|
report(node);
|
99
97
|
|
100
98
|
// Report AssignmentExpressions only if they are the left side of the assignment
|
101
|
-
} else if (effectiveParent.type === "AssignmentExpression" &&
|
102
|
-
isUnderscored(name) &&
|
103
|
-
(effectiveParent.right.type !== "MemberExpression" ||
|
104
|
-
effectiveParent.left.type === "MemberExpression" &&
|
105
|
-
effectiveParent.left.property.name === node.name)) {
|
99
|
+
} else if (effectiveParent.type === "AssignmentExpression" && isUnderscored(name) && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name)) {
|
106
100
|
report(node);
|
107
101
|
}
|
108
102
|
|
109
|
-
|
110
|
-
|
103
|
+
/*
|
104
|
+
* Properties have their own rules, and
|
105
|
+
* AssignmentPattern nodes can be treated like Properties:
|
106
|
+
* e.g.: const { no_camelcased = false } = bar;
|
107
|
+
*/
|
108
|
+
} else if (node.parent.type === "Property" || node.parent.type === "AssignmentPattern") {
|
111
109
|
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
if (node.parent.parent && node.parent.parent.type === "ObjectPattern") {
|
111
|
+
|
112
|
+
if (node.parent.shorthand && node.parent.value.left && isUnderscored(name)) {
|
113
|
+
|
114
|
+
report(node);
|
115
|
+
}
|
116
|
+
|
117
|
+
// prevent checking righthand side of destructured object
|
118
|
+
if (node.parent.key === node && node.parent.value !== node) {
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
|
122
|
+
if (node.parent.value.name && isUnderscored(name)) {
|
123
|
+
report(node);
|
124
|
+
}
|
115
125
|
}
|
116
126
|
|
117
|
-
|
118
|
-
|
127
|
+
// "never" check properties
|
128
|
+
if (properties === "never") {
|
119
129
|
return;
|
120
130
|
}
|
121
131
|
|
122
|
-
|
132
|
+
// don't check right hand side of AssignmentExpression to prevent duplicate warnings
|
133
|
+
if (isUnderscored(name) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && !(node.parent.right === node)) {
|
123
134
|
report(node);
|
124
135
|
}
|
125
136
|
|
package/lib/rules/eol-last.js
CHANGED
@@ -46,6 +46,14 @@ module.exports = {
|
|
46
46
|
CRLF = `\r${LF}`,
|
47
47
|
endsWithNewline = lodash.endsWith(src, LF);
|
48
48
|
|
49
|
+
/*
|
50
|
+
* Empty source is always valid: No content in file so we don't
|
51
|
+
* need to lint for a newline on the last line of content.
|
52
|
+
*/
|
53
|
+
if (!src.length) {
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
|
49
57
|
let mode = context.options[0] || "always",
|
50
58
|
appendCRLF = false;
|
51
59
|
|
@@ -0,0 +1,86 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview enforce the location of arrow function bodies
|
3
|
+
* @author Sharmila Jesupaul
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Rule Definition
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
module.exports = {
|
11
|
+
meta: {
|
12
|
+
docs: {
|
13
|
+
description: "enforce the location of arrow function bodies",
|
14
|
+
category: "Stylistic Issues",
|
15
|
+
recommended: false
|
16
|
+
},
|
17
|
+
fixable: "whitespace",
|
18
|
+
schema: [
|
19
|
+
{
|
20
|
+
enum: ["beside", "below"]
|
21
|
+
}
|
22
|
+
]
|
23
|
+
},
|
24
|
+
|
25
|
+
create(context) {
|
26
|
+
const sourceCode = context.getSourceCode();
|
27
|
+
|
28
|
+
//----------------------------------------------------------------------
|
29
|
+
// Helpers
|
30
|
+
//----------------------------------------------------------------------
|
31
|
+
/**
|
32
|
+
* Gets the applicable preference for a particular keyword
|
33
|
+
* @returns {string} The applicable option for the keyword, e.g. 'beside'
|
34
|
+
*/
|
35
|
+
function getOption() {
|
36
|
+
return context.options[0] || "beside";
|
37
|
+
}
|
38
|
+
|
39
|
+
/**
|
40
|
+
* Validates the location of an arrow function body
|
41
|
+
* @param {ASTNode} node The arrow function body
|
42
|
+
* @param {string} keywordName The applicable keyword name for the arrow function body
|
43
|
+
* @returns {void}
|
44
|
+
*/
|
45
|
+
function validateExpression(node) {
|
46
|
+
const option = getOption();
|
47
|
+
|
48
|
+
let tokenBefore = sourceCode.getTokenBefore(node.body);
|
49
|
+
const hasParens = tokenBefore.value === "(";
|
50
|
+
|
51
|
+
if (node.type === "BlockStatement") {
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
|
55
|
+
let fixerTarget = node.body;
|
56
|
+
|
57
|
+
if (hasParens) {
|
58
|
+
|
59
|
+
// Gets the first token before the function body that is not an open paren
|
60
|
+
tokenBefore = sourceCode.getTokenBefore(node.body, token => token.value !== "(");
|
61
|
+
fixerTarget = sourceCode.getTokenAfter(tokenBefore);
|
62
|
+
}
|
63
|
+
|
64
|
+
if (tokenBefore.loc.end.line === fixerTarget.loc.start.line && option === "below") {
|
65
|
+
context.report({
|
66
|
+
node: fixerTarget,
|
67
|
+
message: "Expected a linebreak before this expression.",
|
68
|
+
fix: fixer => fixer.insertTextBefore(fixerTarget, "\n")
|
69
|
+
});
|
70
|
+
} else if (tokenBefore.loc.end.line !== fixerTarget.loc.start.line && option === "beside") {
|
71
|
+
context.report({
|
72
|
+
node: fixerTarget,
|
73
|
+
message: "Expected no linebreak before this expression.",
|
74
|
+
fix: fixer => fixer.replaceTextRange([tokenBefore.range[1], fixerTarget.range[0]], " ")
|
75
|
+
});
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
//----------------------------------------------------------------------
|
80
|
+
// Public
|
81
|
+
//----------------------------------------------------------------------
|
82
|
+
return {
|
83
|
+
ArrowFunctionExpression: node => validateExpression(node)
|
84
|
+
};
|
85
|
+
}
|
86
|
+
};
|
@@ -8,8 +8,8 @@
|
|
8
8
|
// Helpers
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const DEFAULT_MESSAGE_TEMPLATE = "'{{
|
12
|
-
const CUSTOM_MESSAGE_TEMPLATE = "'{{
|
11
|
+
const DEFAULT_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used.";
|
12
|
+
const CUSTOM_MESSAGE_TEMPLATE = "'{{importSource}}' import is restricted from being used. {{customMessage}}";
|
13
13
|
|
14
14
|
//------------------------------------------------------------------------------
|
15
15
|
// Rule Definition
|
@@ -35,6 +35,12 @@ const arrayOfStringsOrObjects = {
|
|
35
35
|
message: {
|
36
36
|
type: "string",
|
37
37
|
minLength: 1
|
38
|
+
},
|
39
|
+
importNames: {
|
40
|
+
type: "array",
|
41
|
+
items: {
|
42
|
+
type: "string"
|
43
|
+
}
|
38
44
|
}
|
39
45
|
},
|
40
46
|
additionalProperties: false,
|
@@ -81,11 +87,14 @@ module.exports = {
|
|
81
87
|
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
82
88
|
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
83
89
|
|
84
|
-
const restrictedPathMessages = restrictedPaths.reduce((memo,
|
85
|
-
if (typeof
|
86
|
-
memo[
|
90
|
+
const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
|
91
|
+
if (typeof importSource === "string") {
|
92
|
+
memo[importSource] = { message: null };
|
87
93
|
} else {
|
88
|
-
memo[
|
94
|
+
memo[importSource.name] = {
|
95
|
+
message: importSource.message,
|
96
|
+
importNames: importSource.importNames
|
97
|
+
};
|
89
98
|
}
|
90
99
|
return memo;
|
91
100
|
}, {});
|
@@ -95,7 +104,16 @@ module.exports = {
|
|
95
104
|
return {};
|
96
105
|
}
|
97
106
|
|
98
|
-
const
|
107
|
+
const restrictedPatternsMatcher = ignore().add(restrictedPatterns);
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Checks to see if "*" is being used to import everything.
|
111
|
+
* @param {Set.<string>} importNames - Set of import names that are being imported
|
112
|
+
* @returns {boolean} whether everything is imported or not
|
113
|
+
*/
|
114
|
+
function isEverythingImported(importNames) {
|
115
|
+
return importNames.has("*");
|
116
|
+
}
|
99
117
|
|
100
118
|
/**
|
101
119
|
* Report a restricted path.
|
@@ -104,8 +122,8 @@ module.exports = {
|
|
104
122
|
* @private
|
105
123
|
*/
|
106
124
|
function reportPath(node) {
|
107
|
-
const
|
108
|
-
const customMessage = restrictedPathMessages[
|
125
|
+
const importSource = node.source.value.trim();
|
126
|
+
const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
|
109
127
|
const message = customMessage
|
110
128
|
? CUSTOM_MESSAGE_TEMPLATE
|
111
129
|
: DEFAULT_MESSAGE_TEMPLATE;
|
@@ -114,39 +132,130 @@ module.exports = {
|
|
114
132
|
node,
|
115
133
|
message,
|
116
134
|
data: {
|
117
|
-
|
135
|
+
importSource,
|
118
136
|
customMessage
|
119
137
|
}
|
120
138
|
});
|
121
139
|
}
|
122
140
|
|
123
141
|
/**
|
124
|
-
*
|
125
|
-
* @param {
|
142
|
+
* Report a restricted path specifically for patterns.
|
143
|
+
* @param {node} node - representing the restricted path reference
|
144
|
+
* @returns {void}
|
145
|
+
* @private
|
146
|
+
*/
|
147
|
+
function reportPathForPatterns(node) {
|
148
|
+
const importSource = node.source.value.trim();
|
149
|
+
|
150
|
+
context.report({
|
151
|
+
node,
|
152
|
+
message: "'{{importSource}}' import is restricted from being used by a pattern.",
|
153
|
+
data: {
|
154
|
+
importSource
|
155
|
+
}
|
156
|
+
});
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Report a restricted path specifically when using the '*' import.
|
161
|
+
* @param {string} importSource - path of the import
|
162
|
+
* @param {node} node - representing the restricted path reference
|
163
|
+
* @returns {void}
|
164
|
+
* @private
|
165
|
+
*/
|
166
|
+
function reportPathForEverythingImported(importSource, node) {
|
167
|
+
const importNames = restrictedPathMessages[importSource].importNames;
|
168
|
+
|
169
|
+
context.report({
|
170
|
+
node,
|
171
|
+
message: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
|
172
|
+
data: {
|
173
|
+
importSource,
|
174
|
+
importNames
|
175
|
+
}
|
176
|
+
});
|
177
|
+
}
|
178
|
+
|
179
|
+
/**
|
180
|
+
* Check if the given importSource is restricted because '*' is being imported.
|
181
|
+
* @param {string} importSource - path of the import
|
182
|
+
* @param {Set.<string>} importNames - Set of import names that are being imported
|
183
|
+
* @returns {boolean} whether the path is restricted
|
184
|
+
* @private
|
185
|
+
*/
|
186
|
+
function isRestrictedForEverythingImported(importSource, importNames) {
|
187
|
+
return Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource) &&
|
188
|
+
restrictedPathMessages[importSource].importNames &&
|
189
|
+
isEverythingImported(importNames);
|
190
|
+
}
|
191
|
+
|
192
|
+
/**
|
193
|
+
* Check if the given importNames are restricted given a list of restrictedImportNames.
|
194
|
+
* @param {Set.<string>} importNames - Set of import names that are being imported
|
195
|
+
* @param {[string]} restrictedImportNames - array of import names that are restricted for this import
|
196
|
+
* @returns {boolean} whether the objectName is restricted
|
197
|
+
* @private
|
198
|
+
*/
|
199
|
+
function isRestrictedObject(importNames, restrictedImportNames) {
|
200
|
+
return restrictedImportNames.some(restrictedObjectName => (
|
201
|
+
importNames.has(restrictedObjectName)
|
202
|
+
));
|
203
|
+
}
|
204
|
+
|
205
|
+
/**
|
206
|
+
* Check if the given importSource is a restricted path.
|
207
|
+
* @param {string} importSource - path of the import
|
208
|
+
* @param {Set.<string>} importNames - Set of import names that are being imported
|
126
209
|
* @returns {boolean} whether the variable is a restricted path or not
|
127
210
|
* @private
|
128
211
|
*/
|
129
|
-
function isRestrictedPath(
|
130
|
-
|
212
|
+
function isRestrictedPath(importSource, importNames) {
|
213
|
+
let isRestricted = false;
|
214
|
+
|
215
|
+
if (Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
|
216
|
+
if (restrictedPathMessages[importSource].importNames) {
|
217
|
+
isRestricted = isRestrictedObject(importNames, restrictedPathMessages[importSource].importNames);
|
218
|
+
} else {
|
219
|
+
isRestricted = true;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
return isRestricted;
|
224
|
+
}
|
225
|
+
|
226
|
+
/**
|
227
|
+
* Check if the given importSource is restricted by a pattern.
|
228
|
+
* @param {string} importSource - path of the import
|
229
|
+
* @returns {boolean} whether the variable is a restricted pattern or not
|
230
|
+
* @private
|
231
|
+
*/
|
232
|
+
function isRestrictedPattern(importSource) {
|
233
|
+
return restrictedPatterns.length > 0 && restrictedPatternsMatcher.ignores(importSource);
|
131
234
|
}
|
132
235
|
|
133
236
|
return {
|
134
237
|
ImportDeclaration(node) {
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
node,
|
144
|
-
message: "'{{importName}}' import is restricted from being used by a pattern.",
|
145
|
-
data: {
|
146
|
-
importName
|
147
|
-
}
|
148
|
-
});
|
238
|
+
const importSource = node.source.value.trim();
|
239
|
+
const importNames = node.specifiers.reduce((set, specifier) => {
|
240
|
+
if (specifier.type === "ImportDefaultSpecifier") {
|
241
|
+
set.add("default");
|
242
|
+
} else if (specifier.type === "ImportNamespaceSpecifier") {
|
243
|
+
set.add("*");
|
244
|
+
} else {
|
245
|
+
set.add(specifier.imported.name);
|
149
246
|
}
|
247
|
+
return set;
|
248
|
+
}, new Set());
|
249
|
+
|
250
|
+
if (isRestrictedForEverythingImported(importSource, importNames)) {
|
251
|
+
reportPathForEverythingImported(importSource, node);
|
252
|
+
}
|
253
|
+
|
254
|
+
if (isRestrictedPath(importSource, importNames)) {
|
255
|
+
reportPath(node);
|
256
|
+
}
|
257
|
+
if (isRestrictedPattern(importSource)) {
|
258
|
+
reportPathForPatterns(node);
|
150
259
|
}
|
151
260
|
}
|
152
261
|
};
|
@@ -145,7 +145,7 @@ module.exports = {
|
|
145
145
|
* @returns {void}
|
146
146
|
*/
|
147
147
|
function performCheck(leftNode, rightNode, reportNode) {
|
148
|
-
if (rightNode.type !== "MemberExpression") {
|
148
|
+
if (rightNode.type !== "MemberExpression" || rightNode.object.type === "Super") {
|
149
149
|
return;
|
150
150
|
}
|
151
151
|
|
package/lib/rules/semi.js
CHANGED
@@ -32,10 +32,19 @@ module.exports = {
|
|
32
32
|
items: [
|
33
33
|
{
|
34
34
|
enum: ["never"]
|
35
|
+
},
|
36
|
+
{
|
37
|
+
type: "object",
|
38
|
+
properties: {
|
39
|
+
beforeStatementContinuationChars: {
|
40
|
+
enum: ["always", "any", "never"]
|
41
|
+
}
|
42
|
+
},
|
43
|
+
additionalProperties: false
|
35
44
|
}
|
36
45
|
],
|
37
46
|
minItems: 0,
|
38
|
-
maxItems:
|
47
|
+
maxItems: 2
|
39
48
|
},
|
40
49
|
{
|
41
50
|
type: "array",
|
@@ -62,9 +71,10 @@ module.exports = {
|
|
62
71
|
|
63
72
|
const OPT_OUT_PATTERN = /^[-[(/+`]/; // One of [(/+-`
|
64
73
|
const options = context.options[1];
|
65
|
-
const never = context.options[0] === "never"
|
66
|
-
|
67
|
-
|
74
|
+
const never = context.options[0] === "never";
|
75
|
+
const exceptOneLine = Boolean(options && options.omitLastInOneLineBlock);
|
76
|
+
const beforeStatementContinuationChars = (options && options.beforeStatementContinuationChars) || "any";
|
77
|
+
const sourceCode = context.getSourceCode();
|
68
78
|
|
69
79
|
//--------------------------------------------------------------------------
|
70
80
|
// Helpers
|
@@ -114,29 +124,115 @@ module.exports = {
|
|
114
124
|
}
|
115
125
|
|
116
126
|
/**
|
117
|
-
* Check
|
118
|
-
*
|
119
|
-
*
|
120
|
-
|
121
|
-
|
127
|
+
* Check whether a given semicolon token is redandant.
|
128
|
+
* @param {Token} semiToken A semicolon token to check.
|
129
|
+
* @returns {boolean} `true` if the next token is `;` or `}`.
|
130
|
+
*/
|
131
|
+
function isRedundantSemi(semiToken) {
|
132
|
+
const nextToken = sourceCode.getTokenAfter(semiToken);
|
133
|
+
|
134
|
+
return (
|
135
|
+
!nextToken ||
|
136
|
+
astUtils.isClosingBraceToken(nextToken) ||
|
137
|
+
astUtils.isSemicolonToken(nextToken)
|
138
|
+
);
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* Check whether a given token is the closing brace of an arrow function.
|
143
|
+
* @param {Token} lastToken A token to check.
|
144
|
+
* @returns {boolean} `true` if the token is the closing brace of an arrow function.
|
122
145
|
*/
|
123
|
-
function
|
124
|
-
if (!astUtils.
|
146
|
+
function isEndOfArrowBlock(lastToken) {
|
147
|
+
if (!astUtils.isClosingBraceToken(lastToken)) {
|
125
148
|
return false;
|
126
149
|
}
|
150
|
+
const node = sourceCode.getNodeByRangeIndex(lastToken.range[0]);
|
127
151
|
|
128
|
-
|
152
|
+
return (
|
153
|
+
node.type === "BlockStatement" &&
|
154
|
+
node.parent.type === "ArrowFunctionExpression"
|
155
|
+
);
|
156
|
+
}
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Check whether a given node is on the same line with the next token.
|
160
|
+
* @param {Node} node A statement node to check.
|
161
|
+
* @returns {boolean} `true` if the node is on the same line with the next token.
|
162
|
+
*/
|
163
|
+
function isOnSameLineWithNextToken(node) {
|
164
|
+
const prevToken = sourceCode.getLastToken(node, 1);
|
165
|
+
const nextToken = sourceCode.getTokenAfter(node);
|
166
|
+
|
167
|
+
return !!nextToken && astUtils.isTokenOnSameLine(prevToken, nextToken);
|
168
|
+
}
|
169
|
+
|
170
|
+
/**
|
171
|
+
* Check whether a given node can connect the next line if the next line is unreliable.
|
172
|
+
* @param {Node} node A statement node to check.
|
173
|
+
* @returns {boolean} `true` if the node can connect the next line.
|
174
|
+
*/
|
175
|
+
function maybeAsiHazardAfter(node) {
|
176
|
+
const t = node.type;
|
129
177
|
|
130
|
-
if (
|
131
|
-
|
178
|
+
if (t === "DoWhileStatement" ||
|
179
|
+
t === "BreakStatement" ||
|
180
|
+
t === "ContinueStatement" ||
|
181
|
+
t === "DebuggerStatement" ||
|
182
|
+
t === "ImportDeclaration" ||
|
183
|
+
t === "ExportAllDeclaration"
|
184
|
+
) {
|
185
|
+
return false;
|
186
|
+
}
|
187
|
+
if (t === "ReturnStatement") {
|
188
|
+
return Boolean(node.argument);
|
189
|
+
}
|
190
|
+
if (t === "ExportNamedDeclaration") {
|
191
|
+
return Boolean(node.declaration);
|
192
|
+
}
|
193
|
+
if (isEndOfArrowBlock(sourceCode.getLastToken(node, 1))) {
|
194
|
+
return false;
|
132
195
|
}
|
133
196
|
|
134
|
-
|
135
|
-
|
136
|
-
const isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value) && nextToken.value !== "++" && nextToken.value !== "--";
|
137
|
-
const isDivider = (astUtils.isClosingBraceToken(nextToken) || astUtils.isSemicolonToken(nextToken));
|
197
|
+
return true;
|
198
|
+
}
|
138
199
|
|
139
|
-
|
200
|
+
/**
|
201
|
+
* Check whether a given token can connect the previous statement.
|
202
|
+
* @param {Token} token A token to check.
|
203
|
+
* @returns {boolean} `true` if the token is one of `[`, `(`, `/`, `+`, `-`, ```, `++`, and `--`.
|
204
|
+
*/
|
205
|
+
function maybeAsiHazardBefore(token) {
|
206
|
+
return (
|
207
|
+
Boolean(token) &&
|
208
|
+
OPT_OUT_PATTERN.test(token.value) &&
|
209
|
+
token.value !== "++" &&
|
210
|
+
token.value !== "--"
|
211
|
+
);
|
212
|
+
}
|
213
|
+
|
214
|
+
/**
|
215
|
+
* Check if the semicolon of a given node is unnecessary, only true if:
|
216
|
+
* - next token is a valid statement divider (`;` or `}`).
|
217
|
+
* - next token is on a new line and the node is not connectable to the new line.
|
218
|
+
* @param {Node} node A statement node to check.
|
219
|
+
* @returns {boolean} whether the semicolon is unnecessary.
|
220
|
+
*/
|
221
|
+
function canRemoveSemicolon(node) {
|
222
|
+
if (isRedundantSemi(sourceCode.getLastToken(node))) {
|
223
|
+
return true; // `;;` or `;}`
|
224
|
+
}
|
225
|
+
if (isOnSameLineWithNextToken(node)) {
|
226
|
+
return false; // One liner.
|
227
|
+
}
|
228
|
+
if (beforeStatementContinuationChars === "never" && !maybeAsiHazardAfter(node)) {
|
229
|
+
return true; // ASI works. This statement doesn't connect to the next.
|
230
|
+
}
|
231
|
+
if (!maybeAsiHazardBefore(sourceCode.getTokenAfter(node))) {
|
232
|
+
return true; // ASI works. The next token doesn't connect to this statement.
|
233
|
+
}
|
234
|
+
|
235
|
+
return false;
|
140
236
|
}
|
141
237
|
|
142
238
|
/**
|
@@ -145,16 +241,17 @@ module.exports = {
|
|
145
241
|
* @returns {boolean} whether the node is in a one-liner block statement.
|
146
242
|
*/
|
147
243
|
function isOneLinerBlock(node) {
|
244
|
+
const parent = node.parent;
|
148
245
|
const nextToken = sourceCode.getTokenAfter(node);
|
149
246
|
|
150
247
|
if (!nextToken || nextToken.value !== "}") {
|
151
248
|
return false;
|
152
249
|
}
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
250
|
+
return (
|
251
|
+
!!parent &&
|
252
|
+
parent.type === "BlockStatement" &&
|
253
|
+
parent.loc.start.line === parent.loc.end.line
|
254
|
+
);
|
158
255
|
}
|
159
256
|
|
160
257
|
/**
|
@@ -163,21 +260,21 @@ module.exports = {
|
|
163
260
|
* @returns {void}
|
164
261
|
*/
|
165
262
|
function checkForSemicolon(node) {
|
166
|
-
const
|
263
|
+
const isSemi = astUtils.isSemicolonToken(sourceCode.getLastToken(node));
|
167
264
|
|
168
265
|
if (never) {
|
169
|
-
if (
|
266
|
+
if (isSemi && canRemoveSemicolon(node)) {
|
170
267
|
report(node, true);
|
268
|
+
} else if (!isSemi && beforeStatementContinuationChars === "always" && maybeAsiHazardBefore(sourceCode.getTokenAfter(node))) {
|
269
|
+
report(node);
|
171
270
|
}
|
172
271
|
} else {
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
} else {
|
178
|
-
|
179
|
-
report(node, true);
|
180
|
-
}
|
272
|
+
const oneLinerBlock = (exceptOneLine && isOneLinerBlock(node));
|
273
|
+
|
274
|
+
if (isSemi && oneLinerBlock) {
|
275
|
+
report(node, true);
|
276
|
+
} else if (!isSemi && !oneLinerBlock) {
|
277
|
+
report(node);
|
181
278
|
}
|
182
279
|
}
|
183
280
|
}
|
@@ -188,9 +285,7 @@ module.exports = {
|
|
188
285
|
* @returns {void}
|
189
286
|
*/
|
190
287
|
function checkForSemicolonForVariableDeclaration(node) {
|
191
|
-
const
|
192
|
-
parentIndex = ancestors.length - 1,
|
193
|
-
parent = ancestors[parentIndex];
|
288
|
+
const parent = node.parent;
|
194
289
|
|
195
290
|
if ((parent.type !== "ForStatement" || parent.init !== node) &&
|
196
291
|
(!/^For(?:In|Of)Statement/.test(parent.type) || parent.left !== node)
|
package/lib/rules/sort-vars.js
CHANGED
@@ -27,29 +27,64 @@ module.exports = {
|
|
27
27
|
},
|
28
28
|
additionalProperties: false
|
29
29
|
}
|
30
|
-
]
|
30
|
+
],
|
31
|
+
|
32
|
+
fixable: "code"
|
31
33
|
},
|
32
34
|
|
33
35
|
create(context) {
|
34
36
|
|
35
37
|
const configuration = context.options[0] || {},
|
36
|
-
ignoreCase = configuration.ignoreCase || false
|
38
|
+
ignoreCase = configuration.ignoreCase || false,
|
39
|
+
sourceCode = context.getSourceCode();
|
37
40
|
|
38
41
|
return {
|
39
42
|
VariableDeclaration(node) {
|
40
43
|
const idDeclarations = node.declarations.filter(decl => decl.id.type === "Identifier");
|
44
|
+
const getSortableName = ignoreCase ? decl => decl.id.name.toLowerCase() : decl => decl.id.name;
|
45
|
+
const unfixable = idDeclarations.some(decl => decl.init !== null && decl.init.type !== "Literal");
|
46
|
+
let fixed = false;
|
41
47
|
|
42
48
|
idDeclarations.slice(1).reduce((memo, decl) => {
|
43
|
-
|
44
|
-
|
49
|
+
const lastVariableName = getSortableName(memo),
|
50
|
+
currentVariableName = getSortableName(decl);
|
45
51
|
|
46
|
-
if (
|
47
|
-
|
48
|
-
|
49
|
-
|
52
|
+
if (currentVariableName < lastVariableName) {
|
53
|
+
context.report({
|
54
|
+
node: decl,
|
55
|
+
message: "Variables within the same declaration block should be sorted alphabetically.",
|
56
|
+
fix(fixer) {
|
57
|
+
if (unfixable || fixed) {
|
58
|
+
return null;
|
59
|
+
}
|
60
|
+
return fixer.replaceTextRange(
|
61
|
+
[idDeclarations[0].range[0], idDeclarations[idDeclarations.length - 1].range[1]],
|
62
|
+
idDeclarations
|
63
|
+
|
64
|
+
// Clone the idDeclarations array to avoid mutating it
|
65
|
+
.slice()
|
66
|
+
|
67
|
+
// Sort the array into the desired order
|
68
|
+
.sort((declA, declB) => {
|
69
|
+
const aName = getSortableName(declA);
|
70
|
+
const bName = getSortableName(declB);
|
71
|
+
|
72
|
+
return aName > bName ? 1 : -1;
|
73
|
+
})
|
74
|
+
|
75
|
+
// Build a string out of the sorted list of identifier declarations and the text between the originals
|
76
|
+
.reduce((sourceText, identifier, index) => {
|
77
|
+
const textAfterIdentifier = index === idDeclarations.length - 1
|
78
|
+
? ""
|
79
|
+
: sourceCode.getText().slice(idDeclarations[index].range[1], idDeclarations[index + 1].range[0]);
|
80
|
+
|
81
|
+
return sourceText + sourceCode.getText(identifier) + textAfterIdentifier;
|
82
|
+
}, "")
|
50
83
|
|
51
|
-
|
52
|
-
|
84
|
+
);
|
85
|
+
}
|
86
|
+
});
|
87
|
+
fixed = true;
|
53
88
|
return memo;
|
54
89
|
}
|
55
90
|
return decl;
|
@@ -45,8 +45,7 @@ module.exports = {
|
|
45
45
|
const MISSING_SPACE_MESSAGE = "There must be a space inside this paren.",
|
46
46
|
REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.",
|
47
47
|
ALWAYS = context.options[0] === "always",
|
48
|
-
|
49
|
-
exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [],
|
48
|
+
exceptionsArrayOptions = (context.options[1] && context.options[1].exceptions) || [],
|
50
49
|
options = {};
|
51
50
|
let exceptions;
|
52
51
|
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.13.1",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An AST-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -40,7 +40,7 @@
|
|
40
40
|
"concat-stream": "^1.6.0",
|
41
41
|
"cross-spawn": "^5.1.0",
|
42
42
|
"debug": "^3.0.1",
|
43
|
-
"doctrine": "^2.0.
|
43
|
+
"doctrine": "^2.0.2",
|
44
44
|
"eslint-scope": "^3.7.1",
|
45
45
|
"espree": "^3.5.2",
|
46
46
|
"esquery": "^1.0.0",
|
@@ -49,7 +49,7 @@
|
|
49
49
|
"file-entry-cache": "^2.0.0",
|
50
50
|
"functional-red-black-tree": "^1.0.1",
|
51
51
|
"glob": "^7.1.2",
|
52
|
-
"globals": "^
|
52
|
+
"globals": "^11.0.1",
|
53
53
|
"ignore": "^3.3.3",
|
54
54
|
"imurmurhash": "^0.1.4",
|
55
55
|
"inquirer": "^3.0.6",
|