eslint-rule-forge 0.3.2 → 0.5.0
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/README.md +47 -40
- package/dist/bindings.d.mts +4 -5
- package/dist/bindings.d.mts.map +1 -1
- package/dist/bindings.mjs +0 -1
- package/dist/bindings.mjs.map +1 -1
- package/dist/comments.d.mts +10 -0
- package/dist/comments.d.mts.map +1 -0
- package/dist/comments.mjs +11 -0
- package/dist/comments.mjs.map +1 -0
- package/dist/imports.d.mts +68 -8
- package/dist/imports.d.mts.map +1 -1
- package/dist/imports.mjs +202 -6
- package/dist/imports.mjs.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -1
- package/dist/negation.d.mts +8 -9
- package/dist/negation.d.mts.map +1 -1
- package/dist/negation.mjs +18 -18
- package/dist/negation.mjs.map +1 -1
- package/dist/rules/prefer-array-is-array.d.mts.map +1 -1
- package/dist/rules/prefer-array-is-array.mjs +13 -19
- package/dist/rules/prefer-array-is-array.mjs.map +1 -1
- package/dist/rules/prefer-is-non-null-object.d.mts.map +1 -1
- package/dist/rules/prefer-is-non-null-object.mjs +75 -76
- package/dist/rules/prefer-is-non-null-object.mjs.map +1 -1
- package/dist/rules/prefer-is-record-and-has-key.d.mts.map +1 -1
- package/dist/rules/prefer-is-record-and-has-key.mjs +32 -44
- package/dist/rules/prefer-is-record-and-has-key.mjs.map +1 -1
- package/dist/rules/prefer-safe-parse.d.mts +10 -7
- package/dist/rules/prefer-safe-parse.d.mts.map +1 -1
- package/dist/rules/prefer-safe-parse.mjs +50 -34
- package/dist/rules/prefer-safe-parse.mjs.map +1 -1
- package/dist/statements.d.mts +12 -0
- package/dist/statements.d.mts.map +1 -0
- package/dist/statements.mjs +39 -0
- package/dist/statements.mjs.map +1 -0
- package/dist/type-wrappers.d.mts +3 -3
- package/package.json +5 -5
- package/src/bindings.mts +4 -5
- package/src/comments.mts +23 -0
- package/src/imports.mts +363 -19
- package/src/index.mts +2 -0
- package/src/negation.mts +36 -37
- package/src/rules/prefer-array-is-array.mts +23 -36
- package/src/rules/prefer-is-non-null-object.mts +107 -112
- package/src/rules/prefer-is-record-and-has-key.mts +47 -71
- package/src/rules/prefer-safe-parse.mts +92 -77
- package/src/statements.mts +57 -0
- package/src/type-wrappers.mts +3 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
|
|
2
2
|
import * as ts from 'typescript';
|
|
3
|
-
import {
|
|
3
|
+
import { hasForeignBinding } from '../bindings.mjs';
|
|
4
|
+
import { bindValueImports } from '../imports.mjs';
|
|
4
5
|
import { getArgumentText } from '../parentheses.mjs';
|
|
5
6
|
import { isIdentifierNamed, skipTypeWrappers, typeHoldsAtEveryLayer, } from '../type-wrappers.mjs';
|
|
6
7
|
|
|
@@ -11,6 +12,7 @@ import { isIdentifierNamed, skipTypeWrappers, typeHoldsAtEveryLayer, } from '../
|
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
|
|
14
16
|
export const createPreferSafeParseInt = (config) => createSafeParseRule(config, 'useSafeParseInt', {
|
|
15
17
|
messages: { useSafeParseInt: messageText(config) },
|
|
16
18
|
description: `Replace \`parseInt(x)\` or \`Number.parseInt(x, 10)\` with \`Result.unwrapOkOr(${config.namespace}.${config.method}(x), Number.NaN)\` from ${config.moduleName}.`,
|
|
@@ -33,6 +35,8 @@ export const createPreferSafeParseInt = (config) => createSafeParseRule(config,
|
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
|
|
39
|
+
|
|
36
40
|
export const createPreferSafeParseFloat = (config) => createSafeParseRule(config, 'useSafeParseFloat', {
|
|
37
41
|
messages: { useSafeParseFloat: messageText(config) },
|
|
38
42
|
description: `Replace \`parseFloat(x)\`, \`Number.parseFloat(x)\`, or \`Number(x)\` (when x is a string) with \`Result.unwrapOkOr(${config.namespace}.${config.method}(x), Number.NaN)\` from ${config.moduleName}.`,
|
|
@@ -43,24 +47,34 @@ export const createPreferSafeParseFloat = (config) => createSafeParseRule(config
|
|
|
43
47
|
isGlobalCall(callee, 'Number'),
|
|
44
48
|
});
|
|
45
49
|
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
const isStringType = (type) => {
|
|
56
|
+
const parts = type.isUnion() ? type.types : [type];
|
|
57
|
+
return (parts.length > 0 &&
|
|
58
|
+
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0));
|
|
59
|
+
};
|
|
46
60
|
const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { messages, description, isTarget, }) => {
|
|
47
|
-
const parseFunction = `${namespace}.${method}`;
|
|
48
61
|
|
|
49
62
|
const requiredImports = [namespace, 'Result'].toSorted();
|
|
50
63
|
return {
|
|
51
64
|
meta: {
|
|
52
65
|
type: 'suggestion',
|
|
53
66
|
docs: { description },
|
|
54
|
-
|
|
67
|
+
hasSuggestions: true,
|
|
55
68
|
schema: [],
|
|
56
|
-
messages
|
|
69
|
+
messages: {
|
|
70
|
+
...messages,
|
|
71
|
+
replaceWithSafeParse: `Replace with \`Result.unwrapOkOr(${namespace}.${method}({{argName}}), Number.NaN)\`.`,
|
|
72
|
+
},
|
|
57
73
|
defaultOptions: [],
|
|
58
74
|
},
|
|
59
75
|
create: (context) => {
|
|
60
76
|
const sourceCode = context.sourceCode;
|
|
61
|
-
const
|
|
62
|
-
const moduleImports = getImportDeclarations(program, moduleName);
|
|
63
|
-
const mut_nodesToFix = [];
|
|
77
|
+
const mut_reports = [];
|
|
64
78
|
return {
|
|
65
79
|
CallExpression: (node) => {
|
|
66
80
|
if (!isTarget(skipTypeWrappers(node.callee), node.arguments)) {
|
|
@@ -68,7 +82,6 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
|
|
|
68
82
|
}
|
|
69
83
|
const firstArg = node.arguments[0];
|
|
70
84
|
|
|
71
|
-
|
|
72
85
|
if (firstArg === undefined ||
|
|
73
86
|
firstArg.type === AST_NODE_TYPES.SpreadElement) {
|
|
74
87
|
return;
|
|
@@ -83,30 +96,43 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
|
|
|
83
96
|
if (!typeHoldsAtEveryLayer(sourceCode, firstArg, isStringType)) {
|
|
84
97
|
return;
|
|
85
98
|
}
|
|
86
|
-
|
|
99
|
+
mut_reports.push({ node, argExpression: firstArg });
|
|
87
100
|
},
|
|
88
101
|
'Program:exit': () => {
|
|
89
|
-
const
|
|
90
|
-
const
|
|
102
|
+
const binding = bindValueImports(sourceCode, moduleName, requiredImports);
|
|
103
|
+
const localNameOf = (name) => binding?.localNames[requiredImports.indexOf(name)];
|
|
104
|
+
const namespaceName = localNameOf(namespace);
|
|
105
|
+
const resultName = localNameOf('Result');
|
|
106
|
+
|
|
91
107
|
|
|
92
108
|
|
|
93
109
|
|
|
94
|
-
|
|
110
|
+
|
|
111
|
+
for (const { node, argExpression } of mut_reports) {
|
|
95
112
|
const argText = getArgumentText(sourceCode, argExpression);
|
|
113
|
+
const data = {
|
|
114
|
+
original: sourceCode.getText(node),
|
|
115
|
+
argName: argText,
|
|
116
|
+
};
|
|
96
117
|
context.report({
|
|
97
118
|
node,
|
|
98
119
|
messageId,
|
|
99
|
-
data
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
data,
|
|
121
|
+
suggest: binding === undefined ||
|
|
122
|
+
namespaceName === undefined ||
|
|
123
|
+
resultName === undefined ||
|
|
124
|
+
[namespaceName, resultName].some((name) => hasForeignBinding(sourceCode, node, name, moduleName))
|
|
125
|
+
? []
|
|
126
|
+
: [
|
|
127
|
+
{
|
|
128
|
+
messageId: 'replaceWithSafeParse',
|
|
129
|
+
data,
|
|
130
|
+
fix: (fixer) => [
|
|
131
|
+
...binding.edits(fixer),
|
|
132
|
+
fixer.replaceText(node, `${resultName}.unwrapOkOr(${namespaceName}.${method}(${argText}), Number.NaN)`),
|
|
133
|
+
],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
110
136
|
});
|
|
111
137
|
}
|
|
112
138
|
},
|
|
@@ -114,7 +140,7 @@ const createSafeParseRule = ({ moduleName, namespace, method }, messageId, { mes
|
|
|
114
140
|
},
|
|
115
141
|
};
|
|
116
142
|
};
|
|
117
|
-
const messageText = ({ moduleName, namespace, method, }) => `Replace \`{{original}}\` with \`Result.unwrapOkOr(${namespace}.${method}({{argName}}), Number.NaN)\` from ${moduleName}.`;
|
|
143
|
+
const messageText = ({ moduleName, namespace, method, }) => `Replace \`{{original}}\` with \`Result.unwrapOkOr(${namespace}.${method}({{argName}}), Number.NaN)\` from ${moduleName}. It parses some strings differently from the call it replaces, so check the input before applying it.`;
|
|
118
144
|
|
|
119
145
|
const isGlobalCall = (callee, name) => callee.type === AST_NODE_TYPES.Identifier && callee.name === name;
|
|
120
146
|
|
|
@@ -126,14 +152,4 @@ const isNumberMethod = (callee, name) => callee.type === AST_NODE_TYPES.MemberEx
|
|
|
126
152
|
isIdentifierNamed(callee.object, 'Number') &&
|
|
127
153
|
callee.property.type === AST_NODE_TYPES.Identifier &&
|
|
128
154
|
callee.property.name === name;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const isStringType = (type) => {
|
|
135
|
-
const parts = type.isUnion() ? type.types : [type];
|
|
136
|
-
return (parts.length > 0 &&
|
|
137
|
-
parts.every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0));
|
|
138
|
-
};
|
|
139
155
|
//# sourceMappingURL=prefer-safe-parse.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefer-safe-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,GAGf,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"prefer-safe-parse.mjs","sourceRoot":"","sources":["../../src/rules/prefer-safe-parse.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
+
/**
|
|
4
|
+
* The statement next to `node` (`offset` 1) or before it (-1) in the statement
|
|
5
|
+
* list `node` is one of: the program's, a block's, a class static block's, a
|
|
6
|
+
* namespace's or a `case`'s. What an `export` declares (or, for
|
|
7
|
+
* `export default`, the expression it exports) is read as the `export`
|
|
8
|
+
* statement. `undefined` when there is none, or when `node` is not in a
|
|
9
|
+
* statement list (an arrow function's expression body, a `for` initializer).
|
|
10
|
+
*/
|
|
11
|
+
export declare const siblingOf: (node: DeepReadonly<TSESTree.Node>, offset: 1 | -1) => DeepReadonly<TSESTree.Node> | undefined;
|
|
12
|
+
//# sourceMappingURL=statements.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.d.mts","sourceRoot":"","sources":["../src/statements.mts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,SACd,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,UACzB,CAAC,GAAG,CAAC,CAAC,KACb,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,SAmBhC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const siblingOf = (node, offset) => {
|
|
11
|
+
const { parent } = node;
|
|
12
|
+
const statement = (parent?.type === AST_NODE_TYPES.ExportNamedDeclaration ||
|
|
13
|
+
parent?.type === AST_NODE_TYPES.ExportDefaultDeclaration) &&
|
|
14
|
+
parent.declaration === node
|
|
15
|
+
? parent
|
|
16
|
+
: node;
|
|
17
|
+
const list = statementListOf(statement);
|
|
18
|
+
if (list === undefined) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const index = list.indexOf(statement);
|
|
22
|
+
return index === -1 ? undefined : list[index + offset];
|
|
23
|
+
};
|
|
24
|
+
const statementListOf = (node) => {
|
|
25
|
+
const { parent } = node;
|
|
26
|
+
if (parent === undefined) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (parent.type === AST_NODE_TYPES.Program ||
|
|
30
|
+
parent.type === AST_NODE_TYPES.BlockStatement ||
|
|
31
|
+
parent.type === AST_NODE_TYPES.StaticBlock ||
|
|
32
|
+
parent.type === AST_NODE_TYPES.TSModuleBlock) {
|
|
33
|
+
return parent.body;
|
|
34
|
+
}
|
|
35
|
+
return parent.type === AST_NODE_TYPES.SwitchCase
|
|
36
|
+
? parent.consequent
|
|
37
|
+
: undefined;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=statements.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statements.mjs","sourceRoot":"","sources":["../src/statements.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,0BAA0B,CAAC;AAGzE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,IAAiC,EACjC,MAAc,EAC2B,EAAE;IAC3C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,MAAM,SAAS,GACb,CAAC,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,sBAAsB;QACrD,MAAM,EAAE,IAAI,KAAK,cAAc,CAAC,wBAAwB,CAAC;QAC3D,MAAM,CAAC,WAAW,KAAK,IAAI;QACzB,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,IAAI,CAAC;IAEX,MAAM,IAAI,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAExC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEtC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;AACzD,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACtB,IAAiC,EACmB,EAAE;IACtD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAExB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IACE,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,OAAO;QACtC,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,cAAc;QAC7C,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,WAAW;QAC1C,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,aAAa,EAC5C,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,UAAU;QAC9C,CAAC,CAAC,MAAM,CAAC,UAAU;QACnB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC,CAAC"}
|
package/dist/type-wrappers.d.mts
CHANGED
|
@@ -51,9 +51,9 @@ export declare const isIdentifierNamed: (node: DeepReadonly<TSESTree.Node>, name
|
|
|
51
51
|
* Whether `holds` is true of the type of every layer of type wrappers around
|
|
52
52
|
* `node` (see {@link typeWrapperLayers}), outermost to innermost; `false`
|
|
53
53
|
* without type information. A widening cast (`s as string | number`) is the
|
|
54
|
-
* author saying the value may be more than it is, and is respected; a
|
|
55
|
-
*
|
|
56
|
-
*
|
|
54
|
+
* author saying the value may be more than it is, and is respected; a narrowing
|
|
55
|
+
* one (`s!`, `v as unknown as string`) cannot vouch for what the value's own
|
|
56
|
+
* type does not, and the fix, which keeps the wrapper, has to
|
|
57
57
|
* type-check at every layer too.
|
|
58
58
|
*/
|
|
59
59
|
export declare const typeHoldsAtEveryLayer: (sourceCode: TSESLint.SourceCode, node: TSESTree.Node, holds: (type: ts.Type, typeChecker: ts.TypeChecker) => boolean) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-rule-forge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Helpers for writing typescript-eslint rules that see through type wrappers and parentheses, and resolve what a file imports.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,13 +41,13 @@
|
|
|
41
41
|
"@typescript-eslint/rule-tester": "8.72.0",
|
|
42
42
|
"dedent": "1.7.2",
|
|
43
43
|
"eslint": "10.13.0",
|
|
44
|
-
"eslint-config-typed": "
|
|
45
|
-
"eslint-plugin-ts-fortress": "1.3.
|
|
46
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
44
|
+
"eslint-config-typed": "7.3.0",
|
|
45
|
+
"eslint-plugin-ts-fortress": "1.3.12",
|
|
46
|
+
"eslint-plugin-ts-type-forge": "0.8.17",
|
|
47
47
|
"prettier": "3.9.10",
|
|
48
48
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
49
49
|
"prettier-plugin-packagejson": "3.0.2",
|
|
50
|
-
"ts-data-forge": "14.10.
|
|
50
|
+
"ts-data-forge": "14.10.1",
|
|
51
51
|
"ts-repo-utils": "10.7.1"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
package/src/bindings.mts
CHANGED
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Whether `name`, read at `node`, resolves to something this file writes down
|
|
12
|
-
*
|
|
11
|
+
* Whether `name`, read at `node`, resolves to something this file writes down —
|
|
12
|
+
* a declaration, a parameter, an import — rather than to a global or a
|
|
13
13
|
* standard-library type of the same name.
|
|
14
14
|
*
|
|
15
15
|
* The scope manager makes an implicit variable for every reference it cannot
|
|
@@ -29,9 +29,8 @@ export const isLocallyBound = (
|
|
|
29
29
|
/**
|
|
30
30
|
* Whether `name`, read at `node`, resolves to a binding that is not an import
|
|
31
31
|
* from `moduleName` — a declaration, a parameter, or an import from another
|
|
32
|
-
* module. A fix that makes code at `node` refer to `moduleName`'s export
|
|
33
|
-
*
|
|
34
|
-
* instead.
|
|
32
|
+
* module. A fix that makes code at `node` refer to `moduleName`'s export `name`
|
|
33
|
+
* has to give up then, because the name would refer to that binding instead.
|
|
35
34
|
*
|
|
36
35
|
* The innermost binding decides: an import from `moduleName` at the top of the
|
|
37
36
|
* file does not help a name a function shadows around `node`.
|
package/src/comments.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
import type { DeepReadonly } from 'ts-type-forge';
|
|
3
|
+
|
|
4
|
+
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Whether a comment inside `node` lies within one of `ranges`, which a fix
|
|
8
|
+
* would delete along with it. Such a fix is dropped instead of the comment.
|
|
9
|
+
* Only comments inside `node` are looked at, so each range has to lie within
|
|
10
|
+
* it.
|
|
11
|
+
*/
|
|
12
|
+
export const hasCommentWithin = (
|
|
13
|
+
sourceCode: TSESLint.SourceCode,
|
|
14
|
+
node: TSESTree.Node,
|
|
15
|
+
ranges: DeepReadonly<TSESTree.Range[]>,
|
|
16
|
+
): boolean =>
|
|
17
|
+
sourceCode
|
|
18
|
+
.getCommentsInside(node)
|
|
19
|
+
.some((comment) =>
|
|
20
|
+
ranges.some(
|
|
21
|
+
([start, end]) => start <= comment.range[0] && comment.range[1] <= end,
|
|
22
|
+
),
|
|
23
|
+
);
|