Skip to content

Commit 558cc63

Browse files
author
Rebecca Stevens
committed
Merge branch 'rule/prefer-readonly-types' into readonlyset-readonlymap
2 parents 10e77ab + 6c6322f commit 558cc63

29 files changed

+330
-180
lines changed

.eslintrc

+22-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"plugins": [
55
"eslint-plugin",
66
"@typescript-eslint",
7+
"jsdoc",
78
"jest",
89
"prettier",
910
"ts-immutable"
@@ -77,12 +78,29 @@
7778
"@typescript-eslint/no-use-before-define": [
7879
"error",
7980
{
80-
"functions": false,
81-
"classes": false,
81+
"functions": true,
82+
"classes": true,
8283
"variables": true,
83-
"typedefs": false
84+
"typedefs": true
8485
}
85-
]
86+
],
87+
88+
// JSDoc.
89+
"jsdoc/check-alignment": 1,
90+
"jsdoc/check-indentation": 1,
91+
"jsdoc/check-param-names": 1,
92+
"jsdoc/check-tag-names": 1,
93+
"jsdoc/implements-on-classes": 1,
94+
"jsdoc/newline-after-description": 1,
95+
"jsdoc/no-types": 1,
96+
"jsdoc/require-description": 1,
97+
"jsdoc/require-description-complete-sentence": 1,
98+
"jsdoc/require-hyphen-before-param-description": 1,
99+
"jsdoc/require-jsdoc": 1,
100+
"jsdoc/require-param-description": 1,
101+
"jsdoc/require-param-name": 1,
102+
"jsdoc/require-returns-check": 1,
103+
"jsdoc/require-returns-description": 1
86104
},
87105
"overrides": [
88106
// Testing Rules.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"eslint-config-prettier": "^6.0.0",
6060
"eslint-plugin-eslint-plugin": "^2.1.0",
6161
"eslint-plugin-jest": "^22.7.1",
62+
"eslint-plugin-jsdoc": "^15.5.3",
6263
"eslint-plugin-prettier": "^3.1.0",
6364
"glob": "^7.1.4",
6465
"husky": "^2.4.1",

src/common/ignore-options.ts

+109-65
Original file line numberDiff line numberDiff line change
@@ -126,46 +126,27 @@ export const ignoreNewArrayOptionSchema: JSONSchema4 = {
126126
};
127127

128128
/**
129-
* Should the given node be ignored?
129+
* Recursive callback of `getNodeText`.
130+
*
131+
* This function not be called from anywhere else.
130132
*/
131-
export function shouldIgnore(
132-
node: TSESTree.Node,
133-
context: RuleContext<string, BaseOptions>,
134-
options: Partial<IgnoreOptions>
135-
): boolean {
136-
return (
137-
// Ignore if in a function and ignoreLocal is set.
138-
(Boolean(options.ignoreLocal) && inFunction(node)) ||
139-
// Ignore if in a class and ignoreClass is set.
140-
(Boolean(options.ignoreClass) && inClass(node)) ||
141-
// Ignore if in an interface and ignoreInterface is set.
142-
(Boolean(options.ignoreInterface) && inInterface(node)) ||
143-
((texts: ReadonlyArray<string>): boolean =>
144-
texts.length > 0
145-
? // Ignore if ignorePattern is set and a pattern matches.
146-
(options.ignorePattern !== undefined &&
147-
texts.every(text =>
148-
isIgnoredPattern(text, options.ignorePattern!)
149-
)) ||
150-
// Ignore if ignoreAccessorPattern is set and an accessor pattern matches.
151-
(options.ignoreAccessorPattern !== undefined &&
152-
texts.every(text =>
153-
isIgnoredAccessorPattern(text, options.ignoreAccessorPattern!)
154-
))
155-
: false)(getNodeTexts(node, context))
156-
);
157-
}
158-
159-
function getNodeTexts(
133+
function _getNodeText(
160134
node: TSESTree.Node,
161135
context: RuleContext<string, BaseOptions>
162-
): ReadonlyArray<string> {
163-
return (isVariableDeclaration(node)
164-
? node.declarations.flatMap(declarator => getNodeText(declarator, context))
165-
: [getNodeText(node, context)]
166-
).filter(name => name !== undefined) as ReadonlyArray<string>;
136+
): string {
137+
return isIdentifier(node)
138+
? node.name
139+
: isMemberExpression(node)
140+
? `${_getNodeText(node.object, context)}.${_getNodeText(
141+
node.property,
142+
context
143+
)}`
144+
: context.getSourceCode().getText(node);
167145
}
168146

147+
/**
148+
* Get the text of the given node.
149+
*/
169150
function getNodeText(
170151
node: TSESTree.Node,
171152
context: RuleContext<string, BaseOptions>
@@ -183,21 +164,25 @@ function getNodeText(
183164
: _getNodeText(node, context);
184165
}
185166

186-
function _getNodeText(
167+
/**
168+
* Get all the important bits of texts from the given node.
169+
*/
170+
function getNodeTexts(
187171
node: TSESTree.Node,
188172
context: RuleContext<string, BaseOptions>
189-
): string {
190-
return isIdentifier(node)
191-
? node.name
192-
: isMemberExpression(node)
193-
? `${_getNodeText(node.object, context)}.${_getNodeText(
194-
node.property,
195-
context
196-
)}`
197-
: context.getSourceCode().getText(node);
173+
): ReadonlyArray<string> {
174+
return (isVariableDeclaration(node)
175+
? node.declarations.flatMap(declarator => getNodeText(declarator, context))
176+
: [getNodeText(node, context)]
177+
).filter(name => name !== undefined) as ReadonlyArray<string>;
198178
}
199179

200-
function isIgnoredPattern(
180+
/**
181+
* Should the given text be ignore?
182+
*
183+
* Test using the given pattern(s).
184+
*/
185+
function shouldIgnoreViaPattern(
201186
text: string,
202187
ignorePattern: ReadonlyArray<string> | string
203188
): boolean {
@@ -209,21 +194,14 @@ function isIgnoredPattern(
209194
return patterns.some(pattern => new RegExp(pattern).test(text));
210195
}
211196

212-
function isIgnoredAccessorPattern(
213-
text: string,
214-
ignorePattern: ReadonlyArray<string> | string
215-
): boolean {
216-
const patterns: ReadonlyArray<string> = Array.isArray(ignorePattern)
217-
? ignorePattern
218-
: [ignorePattern];
219-
220-
// One or more patterns match?
221-
return patterns.some(pattern =>
222-
findMatch(pattern.split("."), text.split("."))
223-
);
224-
}
225-
226-
function findMatch(
197+
/**
198+
* Recursive callback of `shouldIgnoreViaAccessorPattern`.
199+
*
200+
* This function not be called from anywhere else.
201+
*
202+
* Does the given text match the given pattern.
203+
*/
204+
function accessorPatternMatch(
227205
[pattern, ...remainingPatternParts]: ReadonlyArray<string>,
228206
textParts: ReadonlyArray<string>,
229207
allowExtra: boolean = false
@@ -233,18 +211,84 @@ function findMatch(
233211
: // Match any depth (including 0)?
234212
pattern === "**"
235213
? textParts.length === 0
236-
? findMatch(remainingPatternParts, [], allowExtra)
214+
? accessorPatternMatch(remainingPatternParts, [], allowExtra)
237215
: Array.from({ length: textParts.length })
238216
.map((_element, index) => index)
239217
.some(offset =>
240-
findMatch(remainingPatternParts, textParts.slice(offset), true)
218+
accessorPatternMatch(
219+
remainingPatternParts,
220+
textParts.slice(offset),
221+
true
222+
)
241223
)
242224
: // Match anything?
243225
pattern === "*"
244226
? textParts.length > 0 &&
245-
findMatch(remainingPatternParts, textParts.slice(1), allowExtra)
227+
accessorPatternMatch(
228+
remainingPatternParts,
229+
textParts.slice(1),
230+
allowExtra
231+
)
246232
: // Text matches pattern?
247233
new RegExp("^" + escapeRegExp(pattern).replace(/\\\*/g, ".*") + "$").test(
248234
textParts[0]
249-
) && findMatch(remainingPatternParts, textParts.slice(1), allowExtra);
235+
) &&
236+
accessorPatternMatch(
237+
remainingPatternParts,
238+
textParts.slice(1),
239+
allowExtra
240+
);
241+
}
242+
243+
/**
244+
* Should the given text be ignore?
245+
*
246+
* Test using the given accessor pattern(s).
247+
*/
248+
function shouldIgnoreViaAccessorPattern(
249+
text: string,
250+
ignorePattern: ReadonlyArray<string> | string
251+
): boolean {
252+
const patterns: ReadonlyArray<string> = Array.isArray(ignorePattern)
253+
? ignorePattern
254+
: [ignorePattern];
255+
256+
// One or more patterns match?
257+
return patterns.some(pattern =>
258+
accessorPatternMatch(pattern.split("."), text.split("."))
259+
);
260+
}
261+
262+
/**
263+
* Should the given node be ignored?
264+
*/
265+
export function shouldIgnore(
266+
node: TSESTree.Node,
267+
context: RuleContext<string, BaseOptions>,
268+
options: Partial<IgnoreOptions>
269+
): boolean {
270+
return (
271+
// Ignore if in a function and ignoreLocal is set.
272+
(Boolean(options.ignoreLocal) && inFunction(node)) ||
273+
// Ignore if in a class and ignoreClass is set.
274+
(Boolean(options.ignoreClass) && inClass(node)) ||
275+
// Ignore if in an interface and ignoreInterface is set.
276+
(Boolean(options.ignoreInterface) && inInterface(node)) ||
277+
((texts: ReadonlyArray<string>): boolean =>
278+
texts.length > 0
279+
? // Ignore if ignorePattern is set and a pattern matches.
280+
(options.ignorePattern !== undefined &&
281+
texts.every(text =>
282+
shouldIgnoreViaPattern(text, options.ignorePattern!)
283+
)) ||
284+
// Ignore if ignoreAccessorPattern is set and an accessor pattern matches.
285+
(options.ignoreAccessorPattern !== undefined &&
286+
texts.every(text =>
287+
shouldIgnoreViaAccessorPattern(
288+
text,
289+
options.ignoreAccessorPattern!
290+
)
291+
))
292+
: false)(getNodeTexts(node, context))
293+
);
250294
}

src/configs/external-recommended.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ const config = {
88
{
99
files: ["*.ts", "*.tsx"],
1010
rules: {
11-
"@typescript-eslint/explicit-function-return-type": "warn"
11+
"@typescript-eslint/explicit-function-return-type": [
12+
"error",
13+
{
14+
allowExpressions: true,
15+
allowTypedFunctionExpressions: true,
16+
allowHigherOrderFunctions: true
17+
}
18+
]
1219
}
1320
}
1421
]

src/rules/functional-parameters.ts

+25-19
Original file line numberDiff line numberDiff line change
@@ -84,27 +84,10 @@ const meta: RuleMetaData<keyof typeof errorMessages> = {
8484
};
8585

8686
/**
87-
* Check if the given function node has a reset parameter this rule.
87+
* Get the rest parameter violations.
8888
*/
89-
function checkFunction(
90-
node:
91-
| TSESTree.FunctionDeclaration
92-
| TSESTree.FunctionExpression
93-
| TSESTree.ArrowFunctionExpression,
94-
context: RuleContext<keyof typeof errorMessages, Options>,
95-
options: Options
96-
): RuleResult<keyof typeof errorMessages, Options> {
97-
return {
98-
context,
99-
descriptors: [
100-
...getRestParamViolations(options.allowRestParameter, node),
101-
...getParamCountViolations(options.enforceParameterCount, node)
102-
]
103-
};
104-
}
105-
10689
function getRestParamViolations(
107-
allowRestParameter: boolean,
90+
allowRestParameter: Options["allowRestParameter"],
10891
node:
10992
| TSESTree.FunctionDeclaration
11093
| TSESTree.FunctionExpression
@@ -122,6 +105,9 @@ function getRestParamViolations(
122105
: [];
123106
}
124107

108+
/**
109+
* Get the parameter count violations.
110+
*/
125111
function getParamCountViolations(
126112
enforceParameterCount: Options["enforceParameterCount"],
127113
node:
@@ -146,6 +132,26 @@ function getParamCountViolations(
146132
: [];
147133
}
148134

135+
/**
136+
* Check if the given function node has a reset parameter this rule.
137+
*/
138+
function checkFunction(
139+
node:
140+
| TSESTree.FunctionDeclaration
141+
| TSESTree.FunctionExpression
142+
| TSESTree.ArrowFunctionExpression,
143+
context: RuleContext<keyof typeof errorMessages, Options>,
144+
options: Options
145+
): RuleResult<keyof typeof errorMessages, Options> {
146+
return {
147+
context,
148+
descriptors: [
149+
...getRestParamViolations(options.allowRestParameter, node),
150+
...getParamCountViolations(options.enforceParameterCount, node)
151+
]
152+
};
153+
}
154+
149155
/**
150156
* Check if the given identifier is for the "arguments" keyword.
151157
*/

0 commit comments

Comments
 (0)