Skip to content

Commit deb4e92

Browse files
author
[Interfaced] Кирилл Дронкин
committed
1.3.0
1 parent e52f10a commit deb4e92

43 files changed

Lines changed: 688 additions & 708 deletions

Some content is hidden

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

.eslintrc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
{
2-
"extends": "interfaced"
2+
"extends": "interfaced",
3+
"overrides": [{
4+
"files": ["test/**"],
5+
"env": {
6+
"mocha": true
7+
}
8+
}]
39
}

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Change log
22

3+
## 1.3.0 (release date: 28.09.2018)
4+
5+
* `jsdoc-type-spacing`: tolerate multiline types
6+
* `lines-around-class`: fixed scope handling for node environment
7+
* `lines-between-statics`: don't group static expressions [BREAKING]
8+
9+
* Handle class and static expressions defined through a variable declaration
10+
311
## 1.2.0 (release date: 30.08.2018)
412

513
* New redefinitions:

lib/ast-utils.js

Lines changed: 125 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,46 @@ const JSDocTypeTokenizer = new JSDocTokenizer({
66
range: true
77
});
88

9+
/**
10+
* @param {ASTNode} node
11+
* @return {boolean}
12+
*/
13+
function isClass(node) {
14+
return node.type === 'ClassDeclaration' || (
15+
(
16+
node.type === 'ExpressionStatement' &&
17+
node.expression.type === 'AssignmentExpression' &&
18+
node.expression.right.type === 'ClassExpression'
19+
) ||
20+
(
21+
node.type === 'VariableDeclaration' &&
22+
node.declarations.length === 1 &&
23+
node.declarations[0].init &&
24+
node.declarations[0].init.type === 'ClassExpression'
25+
)
26+
);
27+
}
28+
929
/**
1030
* @param {ASTNode} node
1131
* @param {SourceCode} sourceCode
1232
* @return {boolean}
1333
*/
1434
function isEnumExpression(node, sourceCode) {
1535
return (
16-
hasJSDocTags(node, ['enum'], sourceCode) &&
17-
node.expression.type === 'AssignmentExpression' &&
18-
node.expression.right.type === 'ObjectExpression' &&
36+
hasJSDocTags(node, ['enum'], sourceCode) && (
37+
(
38+
node.type === 'ExpressionStatement' &&
39+
node.expression.type === 'AssignmentExpression' &&
40+
node.expression.right.type === 'ObjectExpression'
41+
) ||
42+
(
43+
node.type === 'VariableDeclaration' &&
44+
node.declarations.length === 1 &&
45+
node.declarations[0].init &&
46+
node.declarations[0].init.type === 'ObjectExpression'
47+
)
48+
) &&
1949
node.parent.type === 'Program'
2050
);
2151
}
@@ -27,21 +57,33 @@ function isEnumExpression(node, sourceCode) {
2757
*/
2858
function isTypedefExpression(node, sourceCode) {
2959
return (
30-
hasJSDocTags(node, ['typedef'], sourceCode) &&
31-
node.expression.type === 'MemberExpression' &&
60+
hasJSDocTags(node, ['typedef'], sourceCode) && (
61+
(
62+
node.type === 'ExpressionStatement' &&
63+
node.expression.type === 'MemberExpression'
64+
) ||
65+
(
66+
node.type === 'VariableDeclaration' &&
67+
node.declarations.length === 1 &&
68+
node.declarations[0].init === null
69+
)
70+
) &&
3271
node.parent.type === 'Program'
3372
);
3473
}
3574

3675
/**
3776
* @param {ASTNode} node
3877
* @param {SourceCode} sourceCode
39-
* @param {boolean=} isStatic
78+
* @param {{
79+
* isStatic: (boolean|undefined)
80+
* }=} options
4081
* @return {boolean}
4182
*/
42-
function isConstantExpression(node, sourceCode, isStatic = true) {
83+
function isConstantExpression(node, sourceCode, {isStatic = true} = {}) {
4384
return (
4485
hasJSDocTags(node, ['const'], sourceCode) &&
86+
node.type === 'ExpressionStatement' &&
4587
node.expression.type === 'AssignmentExpression' &&
4688
node.expression.left.property.type === 'Identifier' &&
4789
(isStatic ? node.parent.type === 'Program' : true)
@@ -50,16 +92,26 @@ function isConstantExpression(node, sourceCode, isStatic = true) {
5092

5193
/**
5294
* @param {ASTNode} node
95+
* @param {SourceCode} sourceCode
5396
* @return {boolean}
5497
*/
55-
function isClass(node) {
98+
function isPropExpression(node, sourceCode) {
99+
if (node.type !== 'ExpressionStatement') {
100+
return false;
101+
}
102+
103+
if (!/AssignmentExpression|MemberExpression/.test(node.expression.type)) {
104+
return false;
105+
}
106+
107+
const lhs = node.expression.type === 'AssignmentExpression' ?
108+
node.expression.left.object :
109+
node.expression.object;
110+
56111
return (
57-
node.type === 'ClassDeclaration' ||
58-
(
59-
node.type === 'ExpressionStatement' &&
60-
node.expression.type === 'AssignmentExpression' &&
61-
node.expression.right.type === 'ClassExpression'
62-
)
112+
lhs &&
113+
lhs.type === 'ThisExpression' &&
114+
hasJSDocTags(node, ['type', 'const'], sourceCode)
63115
);
64116
}
65117

@@ -90,25 +142,60 @@ function isTypecast(node, sourceCode) {
90142
}
91143

92144
/**
93-
* @param {ASTNode} propExpression
145+
* @param {ASTNode} classNode
94146
* @return {string}
95147
*/
96-
function resolvePropName(propExpression) {
97-
return propExpression.expression.type === 'MemberExpression' ?
98-
propExpression.expression.property.name :
99-
propExpression.expression.left.property.name;
148+
function resolveClassName(classNode) { // eslint-disable-line consistent-return
149+
switch (classNode.type) {
150+
case 'ExpressionStatement':
151+
return classNode.expression.left.type === 'MemberExpression' ?
152+
classNode.expression.left.property.name :
153+
classNode.expression.left.name;
154+
155+
case 'ClassDeclaration':
156+
return classNode.id.name;
157+
158+
case 'VariableDeclaration':
159+
return classNode.declarations[0].id.name;
160+
}
100161
}
101162

102163
/**
103-
* @param {ASTNode} classNode
164+
* @param {ASTNode} enumExpression
104165
* @return {string}
105166
*/
106-
function resolveClassName(classNode) {
107-
return classNode.expression && classNode.expression.type === 'AssignmentExpression' ?
108-
classNode.expression.left.type === 'MemberExpression' ?
109-
classNode.expression.left.property.name :
110-
classNode.expression.left.name :
111-
classNode.id.name;
167+
function resolveEnumName(enumExpression) {
168+
return enumExpression.type === 'ExpressionStatement' ?
169+
enumExpression.expression.left.property.name :
170+
enumExpression.declarations[0].id.name;
171+
}
172+
173+
/**
174+
* @param {ASTNode} typedefExpression
175+
* @return {string}
176+
*/
177+
function resolveTypedefName(typedefExpression) {
178+
return typedefExpression.type === 'ExpressionStatement' ?
179+
typedefExpression.expression.property.name :
180+
typedefExpression.declarations[0].id.name;
181+
}
182+
183+
/**
184+
* @param {ASTNode} constantExpression
185+
* @return {string}
186+
*/
187+
function resolveConstantName(constantExpression) {
188+
return constantExpression.expression.left.property.name;
189+
}
190+
191+
/**
192+
* @param {ASTNode} propExpression
193+
* @return {?string}
194+
*/
195+
function resolvePropName(propExpression) {
196+
return propExpression.expression.type === 'MemberExpression' ?
197+
propExpression.expression.property.name :
198+
propExpression.expression.left.property.name;
112199
}
113200

114201
/**
@@ -157,71 +244,7 @@ function getPropsFromClassConstructor(methodDefinition, sourceCode) {
157244
return [];
158245
}
159246

160-
return methodDefinition.value.body.body.filter((bodyChildNode) => {
161-
if (bodyChildNode.type !== 'ExpressionStatement') {
162-
return false;
163-
}
164-
165-
const leftPart = bodyChildNode.expression.type === 'AssignmentExpression' ?
166-
bodyChildNode.expression.left.object :
167-
bodyChildNode.expression.object;
168-
169-
return (
170-
leftPart &&
171-
leftPart.type === 'ThisExpression' &&
172-
hasJSDocTags(bodyChildNode, ['type', 'const'], sourceCode)
173-
);
174-
});
175-
}
176-
177-
/**
178-
* @param {ASTNode} memberExpression
179-
* @return {ASTNode}
180-
*/
181-
function getMemberExpressionRootIdentifier(memberExpression) {
182-
let object = memberExpression.object;
183-
while (object.type !== 'Identifier') {
184-
object = object.object;
185-
}
186-
187-
return object;
188-
}
189-
190-
/**
191-
* @param {Array<ASTNode>} expressions
192-
* @return {Object<string|symbol, Array<ASTNode>>}
193-
*/
194-
function groupStaticExpressions(expressions) {
195-
const noGroupKey = Symbol();
196-
const groupedStaticExpressions = expressions.reduce((groups, staticExpression) => {
197-
switch (staticExpression.expression.type) {
198-
case 'Identifier':
199-
groups[noGroupKey].push(staticExpression);
200-
201-
break;
202-
203-
case 'MemberExpression':
204-
case 'AssignmentExpression':
205-
const rootIdentifier = getMemberExpressionRootIdentifier(
206-
staticExpression.expression.type === 'AssignmentExpression' ?
207-
staticExpression.expression.left :
208-
staticExpression.expression
209-
);
210-
211-
if (!groups[rootIdentifier.name]) {
212-
groups[rootIdentifier.name] = [];
213-
}
214-
215-
groups[rootIdentifier.name].push(staticExpression);
216-
217-
break;
218-
}
219-
220-
return groups;
221-
}, {[noGroupKey]: []});
222-
223-
return Object.keys(groupedStaticExpressions)
224-
.map((key) => groupedStaticExpressions[key]);
247+
return methodDefinition.value.body.body.filter((node) => isPropExpression(node, sourceCode));
225248
}
226249

227250
/**
@@ -408,17 +431,13 @@ function getJSDocTokenAfter(tokens, targetToken) {
408431
* @param {Array<JSDocTokenWithRange>} tokens
409432
* @param {JSDocTokenWithRange} token
410433
* @param {{
411-
* requiredType: (string|undefined),
412-
* requiredValue: (string|undefined),
434+
* type: (string|undefined),
435+
* value: (string|undefined),
413436
* moveForward: (boolean|undefined)
414437
* }=} options
415438
* @return {?JSDocTokenWithRange}
416439
*/
417-
function findFirstNonWhitespaceSiblingToken(tokens, token, {
418-
requiredType,
419-
requiredValue,
420-
moveForward = true
421-
} = {}) {
440+
function findNonWhitespaceSiblingJSDocToken(tokens, token, {type, value, moveForward = true} = {}) {
422441
let currentToken = token;
423442

424443
while (currentToken) {
@@ -435,8 +454,8 @@ function findFirstNonWhitespaceSiblingToken(tokens, token, {
435454
}
436455

437456
if (
438-
(!requiredType || currentToken.type === requiredType) &&
439-
(!requiredValue || currentToken.value === requiredValue)
457+
(!type || currentToken.type === type) &&
458+
(!value || currentToken.value === value)
440459
) {
441460
return currentToken;
442461
}
@@ -546,16 +565,19 @@ function traverseJSDocType(type, callback) {
546565
}
547566

548567
module.exports = {
568+
isClass,
549569
isEnumExpression,
550570
isTypedefExpression,
551571
isConstantExpression,
552-
isClass,
572+
isPropExpression,
553573
isTypecast,
554574
resolvePropName,
555575
resolveClassName,
576+
resolveEnumName,
577+
resolveTypedefName,
578+
resolveConstantName,
556579
resolveParamNames,
557580
getPropsFromClassConstructor,
558-
groupStaticExpressions,
559581
getJSDocComment,
560582
parseJSDoc,
561583
hasJSDocTags,
@@ -567,8 +589,8 @@ module.exports = {
567589
getJSDocSubtypeTokens,
568590
getJSDocTokenBefore,
569591
getJSDocTokenAfter,
570-
findFirstNonWhitespaceSiblingToken,
571592
getScopeFromJSDoc,
572593
getStaticTypeFromJSDoc,
594+
findNonWhitespaceSiblingJSDocToken,
573595
traverseJSDocType
574596
};

lib/rules/capitalized-enum.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const {visitEnumExpressions} = require('../visitors');
2+
const {resolveEnumName} = require('../ast-utils');
23

34
module.exports = {
45
meta: {
@@ -11,14 +12,13 @@ module.exports = {
1112
* @param {ASTNode} enumExpression
1213
*/
1314
function check(enumExpression) {
14-
const property = enumExpression.expression.left.property;
15-
const propertyName = property.name;
16-
const propertyNameFirstChar = propertyName[0];
15+
const enumName = resolveEnumName(enumExpression);
16+
const enumNameFirstChar = enumName[0];
1717

18-
if (propertyNameFirstChar !== propertyNameFirstChar.toUpperCase()) {
18+
if (enumNameFirstChar !== enumNameFirstChar.toUpperCase()) {
1919
context.report({
20-
node: property,
21-
message: `Enum "${propertyName}" is not capitalized.`
20+
node: enumExpression,
21+
message: `Enum "${enumName}" is not capitalized.`
2222
});
2323
}
2424
}

0 commit comments

Comments
 (0)