@trackunit/eslint-plugin-trackunit 0.4.65 → 0.4.67
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 +8 -0
- package/README.md +1 -2
- package/package.json +1 -1
- package/src/lib/config/index.d.ts +21 -0
- package/src/lib/config/plugins.d.ts +7 -0
- package/src/lib/config/presets/base.d.ts +14 -0
- package/src/lib/config/presets/react.d.ts +7 -0
- package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.d.ts +14 -0
- package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js +542 -0
- package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js.map +1 -0
- package/src/lib/rules-map.d.ts +7 -0
- package/src/lib/rules-map.js +2 -0
- package/src/lib/rules-map.js.map +1 -1
- package/src/lib/utils/ast-utils.d.ts +4 -0
- package/src/lib/utils/ast-utils.js +74 -21
- package/src/lib/utils/ast-utils.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.4.67 (2026-05-01)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for eslint-plugin-trackunit to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 0.4.66 (2026-05-01)
|
|
6
|
+
|
|
7
|
+
This was a version bump only for eslint-plugin-trackunit to align it with other projects, there were no code changes.
|
|
8
|
+
|
|
1
9
|
## 0.4.65 (2026-05-01)
|
|
2
10
|
|
|
3
11
|
This was a version bump only for eslint-plugin-trackunit to align it with other projects, there were no code changes.
|
package/README.md
CHANGED
|
@@ -52,7 +52,6 @@ All custom rules are enabled automatically through the presets under the `@track
|
|
|
52
52
|
|
|
53
53
|
### React & JSX
|
|
54
54
|
|
|
55
|
-
|
|
56
55
|
| Rule | Severity | Auto-fix | Description |
|
|
57
56
|
| ------------------------------------------------------ | -------- | -------- | ------------------------------------------------------------------------------------------ |
|
|
58
57
|
| `@trackunit/no-template-strings-in-classname-prop` | — | — | Disallows template literals in `className`. Use `twMerge()` or `cvaMerge()` instead. |
|
|
@@ -63,9 +62,9 @@ All custom rules are enabled automatically through the presets under the `@track
|
|
|
63
62
|
| `@trackunit/prefer-mouse-event-handler-in-react-props` | — | — | Enforces `MouseEventHandler<T>` typing for `onClick*` props. |
|
|
64
63
|
| `@trackunit/prefer-event-specific-callback-naming` | — | — | Enforces event-specific naming (e.g. `onClickClose` over `onClose`) for click handlers. |
|
|
65
64
|
| `@trackunit/require-optional-prop-initialization` | — | — | Requires optional component props to be initialized inside the component. |
|
|
65
|
+
| `@trackunit/require-component-prop-contracts` | — | — | Requires public component props to satisfy configured prop/interface contracts. |
|
|
66
66
|
| `@trackunit/require-list-item-virtualization-props` | — | — | Requires `VirtualizationListItemProps` on list items inside `<List>`. |
|
|
67
67
|
|
|
68
|
-
|
|
69
68
|
### Testing
|
|
70
69
|
|
|
71
70
|
|
package/package.json
CHANGED
|
@@ -58,6 +58,13 @@ export declare const configs: {
|
|
|
58
58
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
59
59
|
name: string;
|
|
60
60
|
};
|
|
61
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
62
|
+
requiredProps?: ReadonlyArray<string>;
|
|
63
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
64
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
65
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
66
|
+
name: string;
|
|
67
|
+
};
|
|
61
68
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
62
69
|
name: string;
|
|
63
70
|
};
|
|
@@ -223,6 +230,13 @@ export declare const configs: {
|
|
|
223
230
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
224
231
|
name: string;
|
|
225
232
|
};
|
|
233
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
234
|
+
requiredProps?: ReadonlyArray<string>;
|
|
235
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
236
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
237
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
238
|
+
name: string;
|
|
239
|
+
};
|
|
226
240
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
227
241
|
name: string;
|
|
228
242
|
};
|
|
@@ -321,6 +335,13 @@ export declare const configs: {
|
|
|
321
335
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
322
336
|
name: string;
|
|
323
337
|
};
|
|
338
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
339
|
+
requiredProps?: ReadonlyArray<string>;
|
|
340
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
341
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
342
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
343
|
+
name: string;
|
|
344
|
+
};
|
|
324
345
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
325
346
|
name: string;
|
|
326
347
|
};
|
|
@@ -76,6 +76,13 @@ export declare const localRulesPlugin: {
|
|
|
76
76
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
77
77
|
name: string;
|
|
78
78
|
};
|
|
79
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
80
|
+
requiredProps?: ReadonlyArray<string>;
|
|
81
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
82
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
83
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
84
|
+
name: string;
|
|
85
|
+
};
|
|
79
86
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
80
87
|
name: string;
|
|
81
88
|
};
|
|
@@ -58,6 +58,13 @@ export declare const base: (import("eslint").Linter.FlatConfig<import("eslint").
|
|
|
58
58
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
59
59
|
name: string;
|
|
60
60
|
};
|
|
61
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
62
|
+
requiredProps?: ReadonlyArray<string>;
|
|
63
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
64
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
65
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
66
|
+
name: string;
|
|
67
|
+
};
|
|
61
68
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
62
69
|
name: string;
|
|
63
70
|
};
|
|
@@ -223,6 +230,13 @@ export declare const base: (import("eslint").Linter.FlatConfig<import("eslint").
|
|
|
223
230
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
224
231
|
name: string;
|
|
225
232
|
};
|
|
233
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
234
|
+
requiredProps?: ReadonlyArray<string>;
|
|
235
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
236
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
237
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
238
|
+
name: string;
|
|
239
|
+
};
|
|
226
240
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
227
241
|
name: string;
|
|
228
242
|
};
|
|
@@ -57,6 +57,13 @@ export declare const reactPreset: ({
|
|
|
57
57
|
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
58
58
|
name: string;
|
|
59
59
|
};
|
|
60
|
+
"require-component-prop-contracts": import("@typescript-eslint/utils/ts-eslint").RuleModule<"missingPropContracts", [{
|
|
61
|
+
requiredProps?: ReadonlyArray<string>;
|
|
62
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
63
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
64
|
+
}], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
65
|
+
name: string;
|
|
66
|
+
};
|
|
60
67
|
"prefer-field-components": import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferFieldComponent", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
|
61
68
|
name: string;
|
|
62
69
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ESLintUtils } from "@typescript-eslint/utils";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
type Options = [
|
|
4
|
+
{
|
|
5
|
+
requiredProps?: ReadonlyArray<string>;
|
|
6
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
7
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
8
|
+
}
|
|
9
|
+
];
|
|
10
|
+
export declare const checkerTypeHasRequiredInterface: (type: ts.Type, requiredInterface: string, checker: ts.TypeChecker, visitedTypeNames?: Set<string>) => boolean;
|
|
11
|
+
export declare const requireComponentPropContracts: ESLintUtils.RuleModule<"missingPropContracts", Options, unknown, ESLintUtils.RuleListener> & {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireComponentPropContracts = exports.checkerTypeHasRequiredInterface = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const utils_1 = require("@typescript-eslint/utils");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
7
|
+
const path = tslib_1.__importStar(require("path"));
|
|
8
|
+
const ts = tslib_1.__importStar(require("typescript"));
|
|
9
|
+
const ast_utils_1 = require("../../utils/ast-utils");
|
|
10
|
+
const nx_utils_1 = require("../../utils/nx-utils");
|
|
11
|
+
const createRule = utils_1.ESLintUtils.RuleCreator(name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`);
|
|
12
|
+
const componentWrapperNames = new Set(["forwardRef", "memo"]);
|
|
13
|
+
const publicEntrypointFileNames = ["index.ts", "index.tsx"];
|
|
14
|
+
const getTypeSymbolInfo = (type) => {
|
|
15
|
+
try {
|
|
16
|
+
return {
|
|
17
|
+
symbolName: type.symbol.getName(),
|
|
18
|
+
declarations: type.symbol.getDeclarations() ?? [],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return {
|
|
23
|
+
symbolName: undefined,
|
|
24
|
+
declarations: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const getTypeReferenceName = (typeName) => {
|
|
29
|
+
if (typeName.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
30
|
+
return typeName.name;
|
|
31
|
+
}
|
|
32
|
+
if (typeName.type === utils_1.AST_NODE_TYPES.TSQualifiedName) {
|
|
33
|
+
return typeName.right.name;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
const getCallExpressionName = (node) => {
|
|
38
|
+
const { callee } = node;
|
|
39
|
+
if (callee.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
40
|
+
return callee.name;
|
|
41
|
+
}
|
|
42
|
+
if (callee.type === utils_1.AST_NODE_TYPES.MemberExpression && callee.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
43
|
+
return callee.property.name;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
};
|
|
47
|
+
const isPascalCaseName = (name) => /^[A-Z]/.test(name);
|
|
48
|
+
const normalizeFilePath = (filePath) => path.normalize(filePath);
|
|
49
|
+
const getProjectRoot = (projectJsonPath) => path.dirname(projectJsonPath);
|
|
50
|
+
const getPublicEntrypointPaths = (projectRoot) => publicEntrypointFileNames.map(fileName => path.join(projectRoot, "src", fileName));
|
|
51
|
+
const getModulePathCandidates = (fromFilePath, moduleSpecifier) => {
|
|
52
|
+
const modulePath = path.resolve(path.dirname(fromFilePath), moduleSpecifier);
|
|
53
|
+
return [
|
|
54
|
+
modulePath,
|
|
55
|
+
`${modulePath}.ts`,
|
|
56
|
+
`${modulePath}.tsx`,
|
|
57
|
+
path.join(modulePath, "index.ts"),
|
|
58
|
+
path.join(modulePath, "index.tsx"),
|
|
59
|
+
];
|
|
60
|
+
};
|
|
61
|
+
const moduleSpecifierTargetsFile = (fromFilePath, moduleSpecifier, targetFilePath) => {
|
|
62
|
+
if (!moduleSpecifier.startsWith(".")) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const normalizedTargetFilePath = normalizeFilePath(targetFilePath);
|
|
66
|
+
return getModulePathCandidates(fromFilePath, moduleSpecifier).some(candidatePath => normalizeFilePath(candidatePath) === normalizedTargetFilePath);
|
|
67
|
+
};
|
|
68
|
+
const getSourceExportName = (specifier) => {
|
|
69
|
+
if (specifier.propertyName?.text === "default") {
|
|
70
|
+
return specifier.name.text;
|
|
71
|
+
}
|
|
72
|
+
return specifier.propertyName?.text ?? specifier.name.text;
|
|
73
|
+
};
|
|
74
|
+
const getPublicExportedNamesForFile = (projectRoot, filePath) => {
|
|
75
|
+
const result = {
|
|
76
|
+
exportsAll: false,
|
|
77
|
+
names: new Set(),
|
|
78
|
+
};
|
|
79
|
+
for (const entrypointPath of getPublicEntrypointPaths(projectRoot)) {
|
|
80
|
+
let sourceText;
|
|
81
|
+
try {
|
|
82
|
+
sourceText = fs.readFileSync(entrypointPath, "utf8");
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const sourceFile = ts.createSourceFile(entrypointPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
88
|
+
for (const statement of sourceFile.statements) {
|
|
89
|
+
if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (!ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (!moduleSpecifierTargetsFile(entrypointPath, statement.moduleSpecifier.text, filePath)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (!statement.exportClause) {
|
|
99
|
+
result.exportsAll = true;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (ts.isNamedExports(statement.exportClause)) {
|
|
103
|
+
statement.exportClause.elements.forEach(specifier => {
|
|
104
|
+
result.names.add(getSourceExportName(specifier));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
};
|
|
111
|
+
const isEntrypointFile = (projectRoot, filePath) => {
|
|
112
|
+
const normalizedFilePath = normalizeFilePath(filePath);
|
|
113
|
+
return getPublicEntrypointPaths(projectRoot).some(entrypointPath => normalizeFilePath(entrypointPath) === normalizedFilePath);
|
|
114
|
+
};
|
|
115
|
+
const isComponentWrapperCallExpression = (node) => {
|
|
116
|
+
const firstArgument = node.arguments[0];
|
|
117
|
+
const callExpressionName = getCallExpressionName(node);
|
|
118
|
+
if (!callExpressionName || !componentWrapperNames.has(callExpressionName)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return (firstArgument?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
122
|
+
firstArgument?.type === utils_1.AST_NODE_TYPES.FunctionExpression);
|
|
123
|
+
};
|
|
124
|
+
const getWrappedComponentFunction = (node) => {
|
|
125
|
+
if (!isComponentWrapperCallExpression(node)) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const firstArgument = node.arguments[0];
|
|
129
|
+
return firstArgument &&
|
|
130
|
+
(firstArgument.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
131
|
+
firstArgument.type === utils_1.AST_NODE_TYPES.FunctionExpression)
|
|
132
|
+
? firstArgument
|
|
133
|
+
: null;
|
|
134
|
+
};
|
|
135
|
+
const getHeritageName = (heritage) => {
|
|
136
|
+
const { expression } = heritage;
|
|
137
|
+
if (expression.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
138
|
+
return expression.name;
|
|
139
|
+
}
|
|
140
|
+
if (expression.type === utils_1.AST_NODE_TYPES.MemberExpression && expression.property.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
141
|
+
return expression.property.name;
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
};
|
|
145
|
+
const getParameterTypeAnnotation = (parameter) => {
|
|
146
|
+
if (!parameter) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
if (parameter.type === utils_1.AST_NODE_TYPES.Identifier || parameter.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
|
|
150
|
+
return parameter.typeAnnotation?.typeAnnotation ?? null;
|
|
151
|
+
}
|
|
152
|
+
if (parameter.type === utils_1.AST_NODE_TYPES.AssignmentPattern) {
|
|
153
|
+
const { left } = parameter;
|
|
154
|
+
if (left.type === utils_1.AST_NODE_TYPES.Identifier || left.type === utils_1.AST_NODE_TYPES.ObjectPattern) {
|
|
155
|
+
return left.typeAnnotation?.typeAnnotation ?? null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
};
|
|
160
|
+
const getFunctionPropsType = (node) => getParameterTypeAnnotation(node.params[0]);
|
|
161
|
+
const getPropsTypeFromCallExpression = (node) => {
|
|
162
|
+
const typeArguments = node.typeArguments?.params ?? [];
|
|
163
|
+
const firstArgument = node.arguments[0];
|
|
164
|
+
if (firstArgument?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression ||
|
|
165
|
+
firstArgument?.type === utils_1.AST_NODE_TYPES.FunctionExpression) {
|
|
166
|
+
const parameterType = getParameterTypeAnnotation(firstArgument.params[0]);
|
|
167
|
+
if (parameterType) {
|
|
168
|
+
return parameterType;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (getCallExpressionName(node) === "forwardRef") {
|
|
172
|
+
return typeArguments[1] ?? null;
|
|
173
|
+
}
|
|
174
|
+
return typeArguments[0] ?? null;
|
|
175
|
+
};
|
|
176
|
+
const getPropsTypeFromVariableDeclarator = (node) => {
|
|
177
|
+
const { init } = node;
|
|
178
|
+
if (!init) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
if (init.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
182
|
+
return getFunctionPropsType(init);
|
|
183
|
+
}
|
|
184
|
+
if (init.type === utils_1.AST_NODE_TYPES.CallExpression) {
|
|
185
|
+
return getPropsTypeFromCallExpression(init);
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
};
|
|
189
|
+
const isExportedDeclaration = (node) => {
|
|
190
|
+
const parent = node.parent;
|
|
191
|
+
if (!parent) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
if (parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration ||
|
|
195
|
+
parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
const grandParent = parent.parent;
|
|
199
|
+
return grandParent?.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration;
|
|
200
|
+
};
|
|
201
|
+
const typeHasRequiredInterface = (typeNode, requiredInterface, declarations, visitedTypeNames = new Set()) => {
|
|
202
|
+
switch (typeNode.type) {
|
|
203
|
+
case utils_1.AST_NODE_TYPES.TSTypeReference: {
|
|
204
|
+
const referenceName = getTypeReferenceName(typeNode.typeName);
|
|
205
|
+
if (!referenceName) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
if (referenceName === requiredInterface) {
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
if (visitedTypeNames.has(referenceName)) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
visitedTypeNames.add(referenceName);
|
|
215
|
+
const interfaceDeclaration = declarations.interfaces.get(referenceName);
|
|
216
|
+
if (interfaceDeclaration) {
|
|
217
|
+
return interfaceExtendsRequiredInterface(interfaceDeclaration, requiredInterface, declarations, visitedTypeNames);
|
|
218
|
+
}
|
|
219
|
+
const typeAlias = declarations.typeAliases.get(referenceName);
|
|
220
|
+
if (typeAlias) {
|
|
221
|
+
return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
case utils_1.AST_NODE_TYPES.TSIntersectionType:
|
|
226
|
+
return typeNode.types.some(part => typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames)));
|
|
227
|
+
case utils_1.AST_NODE_TYPES.TSUnionType:
|
|
228
|
+
return typeNode.types.every(part => typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames)));
|
|
229
|
+
default:
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
const interfaceExtendsRequiredInterface = (declaration, requiredInterface, declarations, visitedTypeNames) => {
|
|
234
|
+
return declaration.extends.some(heritage => {
|
|
235
|
+
const heritageName = getHeritageName(heritage);
|
|
236
|
+
if (!heritageName) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
if (heritageName === requiredInterface) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
if (visitedTypeNames.has(heritageName)) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
visitedTypeNames.add(heritageName);
|
|
246
|
+
const interfaceDeclaration = declarations.interfaces.get(heritageName);
|
|
247
|
+
if (interfaceDeclaration) {
|
|
248
|
+
return interfaceExtendsRequiredInterface(interfaceDeclaration, requiredInterface, declarations, visitedTypeNames);
|
|
249
|
+
}
|
|
250
|
+
const typeAlias = declarations.typeAliases.get(heritageName);
|
|
251
|
+
if (typeAlias) {
|
|
252
|
+
return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
const interfaceHasRequiredProp = (declaration, requiredProp, declarations, visitedTypeNames) => {
|
|
258
|
+
const hasOwnProp = declaration.body.body.some(member => {
|
|
259
|
+
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
return member.key.type === utils_1.AST_NODE_TYPES.Identifier && member.key.name === requiredProp;
|
|
263
|
+
});
|
|
264
|
+
if (hasOwnProp) {
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
return declaration.extends.some(heritage => {
|
|
268
|
+
const heritageName = getHeritageName(heritage);
|
|
269
|
+
if (!heritageName || visitedTypeNames.has(heritageName)) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
visitedTypeNames.add(heritageName);
|
|
273
|
+
const interfaceDeclaration = declarations.interfaces.get(heritageName);
|
|
274
|
+
if (interfaceDeclaration) {
|
|
275
|
+
return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);
|
|
276
|
+
}
|
|
277
|
+
const typeAlias = declarations.typeAliases.get(heritageName);
|
|
278
|
+
if (typeAlias) {
|
|
279
|
+
return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);
|
|
280
|
+
}
|
|
281
|
+
return false;
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
const typeLiteralHasRequiredProp = (typeNode, requiredProp) => {
|
|
285
|
+
return typeNode.members.some(member => {
|
|
286
|
+
if (member.type !== utils_1.AST_NODE_TYPES.TSPropertySignature) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
return member.key.type === utils_1.AST_NODE_TYPES.Identifier && member.key.name === requiredProp;
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
const typeHasRequiredProp = (typeNode, requiredProp, declarations, visitedTypeNames = new Set()) => {
|
|
293
|
+
switch (typeNode.type) {
|
|
294
|
+
case utils_1.AST_NODE_TYPES.TSTypeLiteral:
|
|
295
|
+
return typeLiteralHasRequiredProp(typeNode, requiredProp);
|
|
296
|
+
case utils_1.AST_NODE_TYPES.TSTypeReference: {
|
|
297
|
+
const referenceName = getTypeReferenceName(typeNode.typeName);
|
|
298
|
+
if (!referenceName || visitedTypeNames.has(referenceName)) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
visitedTypeNames.add(referenceName);
|
|
302
|
+
const interfaceDeclaration = declarations.interfaces.get(referenceName);
|
|
303
|
+
if (interfaceDeclaration) {
|
|
304
|
+
return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);
|
|
305
|
+
}
|
|
306
|
+
const typeAlias = declarations.typeAliases.get(referenceName);
|
|
307
|
+
if (typeAlias) {
|
|
308
|
+
return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);
|
|
309
|
+
}
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
case utils_1.AST_NODE_TYPES.TSIntersectionType:
|
|
313
|
+
return typeNode.types.some(part => typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames)));
|
|
314
|
+
case utils_1.AST_NODE_TYPES.TSUnionType:
|
|
315
|
+
return typeNode.types.every(part => typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames)));
|
|
316
|
+
default:
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const getTypeCheckerContext = (context) => {
|
|
321
|
+
try {
|
|
322
|
+
const services = utils_1.ESLintUtils.getParserServices(context);
|
|
323
|
+
return {
|
|
324
|
+
checker: services.program.getTypeChecker(),
|
|
325
|
+
services,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
const checkerTypeHasRequiredInterface = (type, requiredInterface, checker, visitedTypeNames = new Set()) => {
|
|
333
|
+
if (type.isUnion()) {
|
|
334
|
+
return type.types.every(part => (0, exports.checkerTypeHasRequiredInterface)(part, requiredInterface, checker, new Set()));
|
|
335
|
+
}
|
|
336
|
+
if (type.isIntersection()) {
|
|
337
|
+
return type.types.some(part => (0, exports.checkerTypeHasRequiredInterface)(part, requiredInterface, checker, new Set(visitedTypeNames)));
|
|
338
|
+
}
|
|
339
|
+
const { symbolName, declarations } = getTypeSymbolInfo(type);
|
|
340
|
+
const aliasSymbolName = type.aliasSymbol?.getName();
|
|
341
|
+
if (symbolName === requiredInterface || aliasSymbolName === requiredInterface) {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
const visitKey = aliasSymbolName ?? symbolName;
|
|
345
|
+
if (visitKey) {
|
|
346
|
+
if (visitedTypeNames.has(visitKey)) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
visitedTypeNames.add(visitKey);
|
|
350
|
+
}
|
|
351
|
+
if (type.aliasTypeArguments?.some(typeArgument => (0, exports.checkerTypeHasRequiredInterface)(typeArgument, requiredInterface, checker))) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
if (type.isClassOrInterface()) {
|
|
355
|
+
const baseTypes = checker.getBaseTypes(type);
|
|
356
|
+
if (baseTypes.some(baseType => (0, exports.checkerTypeHasRequiredInterface)(baseType, requiredInterface, checker, visitedTypeNames))) {
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return declarations.some(declaration => {
|
|
361
|
+
if (!ts.isInterfaceDeclaration(declaration) || !declaration.heritageClauses) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
return declaration.heritageClauses.some(heritageClause => heritageClause.types.some(heritageType => {
|
|
365
|
+
const heritageInterfaceType = checker.getTypeAtLocation(heritageType);
|
|
366
|
+
return (0, exports.checkerTypeHasRequiredInterface)(heritageInterfaceType, requiredInterface, checker, visitedTypeNames);
|
|
367
|
+
}));
|
|
368
|
+
});
|
|
369
|
+
};
|
|
370
|
+
exports.checkerTypeHasRequiredInterface = checkerTypeHasRequiredInterface;
|
|
371
|
+
const checkerTypeHasRequiredProp = (type, requiredProp, checker) => {
|
|
372
|
+
if (type.isUnion()) {
|
|
373
|
+
return type.types.every(part => checkerTypeHasRequiredProp(part, requiredProp, checker));
|
|
374
|
+
}
|
|
375
|
+
return Boolean(type.getProperty(requiredProp));
|
|
376
|
+
};
|
|
377
|
+
const getCheckerType = (typeNode, typeCheckerContext) => {
|
|
378
|
+
if (!typeCheckerContext) {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
const tsNode = typeCheckerContext.services.esTreeNodeToTSNodeMap.get(typeNode);
|
|
382
|
+
return typeCheckerContext.checker.getTypeAtLocation(tsNode);
|
|
383
|
+
};
|
|
384
|
+
exports.requireComponentPropContracts = createRule({
|
|
385
|
+
name: "require-component-prop-contracts",
|
|
386
|
+
meta: {
|
|
387
|
+
type: "problem",
|
|
388
|
+
docs: {
|
|
389
|
+
description: "Require exported React component props to include configured prop names or extend configured interfaces.",
|
|
390
|
+
},
|
|
391
|
+
schema: [
|
|
392
|
+
{
|
|
393
|
+
type: "object",
|
|
394
|
+
properties: {
|
|
395
|
+
requiredProps: {
|
|
396
|
+
type: "array",
|
|
397
|
+
items: { type: "string" },
|
|
398
|
+
description: "Prop names every exported component props type must include.",
|
|
399
|
+
},
|
|
400
|
+
requiredInterfaces: {
|
|
401
|
+
type: "array",
|
|
402
|
+
items: { type: "string" },
|
|
403
|
+
description: "Interface names every exported component props type must reference or extend.",
|
|
404
|
+
},
|
|
405
|
+
restrictToComponentsWithJsxReturn: {
|
|
406
|
+
type: "boolean",
|
|
407
|
+
description: "When true, only enforce for components that return intrinsic JSX. Defaults to false (all components).",
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
additionalProperties: false,
|
|
411
|
+
},
|
|
412
|
+
],
|
|
413
|
+
messages: {
|
|
414
|
+
missingPropContracts: "Public component '{{componentName}}' props must satisfy these contracts: {{missingContracts}}.",
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
defaultOptions: [
|
|
418
|
+
{
|
|
419
|
+
requiredProps: [],
|
|
420
|
+
requiredInterfaces: [],
|
|
421
|
+
restrictToComponentsWithJsxReturn: false,
|
|
422
|
+
},
|
|
423
|
+
],
|
|
424
|
+
create(context, [options]) {
|
|
425
|
+
const filename = context.filename;
|
|
426
|
+
if (!filename.endsWith(".tsx")) {
|
|
427
|
+
return {};
|
|
428
|
+
}
|
|
429
|
+
const projectMetadata = (0, nx_utils_1.getProjectMetadata)(filename);
|
|
430
|
+
if (!projectMetadata) {
|
|
431
|
+
return {};
|
|
432
|
+
}
|
|
433
|
+
const requiredProps = options.requiredProps ?? [];
|
|
434
|
+
const requiredInterfaces = options.requiredInterfaces ?? [];
|
|
435
|
+
const restrictToComponentsWithJsxReturn = options.restrictToComponentsWithJsxReturn ?? false;
|
|
436
|
+
if (requiredProps.length === 0 && requiredInterfaces.length === 0) {
|
|
437
|
+
return {};
|
|
438
|
+
}
|
|
439
|
+
const declarations = {
|
|
440
|
+
interfaces: new Map(),
|
|
441
|
+
typeAliases: new Map(),
|
|
442
|
+
};
|
|
443
|
+
const typeCheckerContext = getTypeCheckerContext(context);
|
|
444
|
+
const exportedIdentifiers = new Set();
|
|
445
|
+
const componentCandidates = [];
|
|
446
|
+
const projectRoot = getProjectRoot(projectMetadata.projectJsonPath);
|
|
447
|
+
const publicExports = getPublicExportedNamesForFile(projectRoot, filename);
|
|
448
|
+
const isCurrentFileEntrypoint = isEntrypointFile(projectRoot, filename);
|
|
449
|
+
const isExportedComponentName = (componentName, node) => {
|
|
450
|
+
if (!isPascalCaseName(componentName) ||
|
|
451
|
+
(!isExportedDeclaration(node) && !exportedIdentifiers.has(componentName))) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
return isCurrentFileEntrypoint || publicExports.exportsAll || publicExports.names.has(componentName);
|
|
455
|
+
};
|
|
456
|
+
const checkCandidate = (candidate) => {
|
|
457
|
+
const checkerType = candidate.propsType ? getCheckerType(candidate.propsType, typeCheckerContext) : null;
|
|
458
|
+
const missingProps = requiredProps.filter(requiredProp => !candidate.propsType ||
|
|
459
|
+
(checkerType && typeCheckerContext
|
|
460
|
+
? !checkerTypeHasRequiredProp(checkerType, requiredProp, typeCheckerContext.checker)
|
|
461
|
+
: !typeHasRequiredProp(candidate.propsType, requiredProp, declarations, new Set())));
|
|
462
|
+
const missingInterfaces = requiredInterfaces.filter(requiredInterface => !candidate.propsType ||
|
|
463
|
+
(checkerType && typeCheckerContext
|
|
464
|
+
? !(0, exports.checkerTypeHasRequiredInterface)(checkerType, requiredInterface, typeCheckerContext.checker)
|
|
465
|
+
: !typeHasRequiredInterface(candidate.propsType, requiredInterface, declarations, new Set())));
|
|
466
|
+
const missingContracts = [...missingProps, ...missingInterfaces];
|
|
467
|
+
if (missingContracts.length === 0) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
context.report({
|
|
471
|
+
node: candidate.node,
|
|
472
|
+
messageId: "missingPropContracts",
|
|
473
|
+
data: {
|
|
474
|
+
componentName: candidate.componentName,
|
|
475
|
+
missingContracts: missingContracts.join(", "),
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
};
|
|
479
|
+
return {
|
|
480
|
+
ExportNamedDeclaration(node) {
|
|
481
|
+
for (const specifier of node.specifiers) {
|
|
482
|
+
if (specifier.local.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
483
|
+
exportedIdentifiers.add(specifier.local.name);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
ExportDefaultDeclaration(node) {
|
|
488
|
+
if (node.declaration.type === utils_1.AST_NODE_TYPES.Identifier) {
|
|
489
|
+
exportedIdentifiers.add(node.declaration.name);
|
|
490
|
+
}
|
|
491
|
+
},
|
|
492
|
+
TSInterfaceDeclaration(node) {
|
|
493
|
+
declarations.interfaces.set(node.id.name, node);
|
|
494
|
+
},
|
|
495
|
+
TSTypeAliasDeclaration(node) {
|
|
496
|
+
declarations.typeAliases.set(node.id.name, node);
|
|
497
|
+
},
|
|
498
|
+
FunctionDeclaration(node) {
|
|
499
|
+
const componentName = node.id?.name;
|
|
500
|
+
const returnsIntrinsicJsx = (0, ast_utils_1.functionReturnsIntrinsicJSX)(node) === true;
|
|
501
|
+
if (!componentName ||
|
|
502
|
+
!(0, ast_utils_1.isReactComponent)(node) ||
|
|
503
|
+
(restrictToComponentsWithJsxReturn && !returnsIntrinsicJsx) ||
|
|
504
|
+
!isExportedComponentName(componentName, node)) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
componentCandidates.push({
|
|
508
|
+
componentName,
|
|
509
|
+
node,
|
|
510
|
+
propsType: getFunctionPropsType(node),
|
|
511
|
+
});
|
|
512
|
+
},
|
|
513
|
+
VariableDeclarator(node) {
|
|
514
|
+
if (node.id.type !== utils_1.AST_NODE_TYPES.Identifier) {
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const { init } = node;
|
|
518
|
+
const wrappedComponentFunction = init?.type === utils_1.AST_NODE_TYPES.CallExpression ? getWrappedComponentFunction(init) : null;
|
|
519
|
+
const isComponent = init?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression
|
|
520
|
+
? (0, ast_utils_1.isReactComponent)(init)
|
|
521
|
+
: wrappedComponentFunction !== null;
|
|
522
|
+
const returnsJsx = init?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression
|
|
523
|
+
? (0, ast_utils_1.functionReturnsIntrinsicJSX)(init) === true
|
|
524
|
+
: wrappedComponentFunction !== null && (0, ast_utils_1.functionReturnsIntrinsicJSX)(wrappedComponentFunction) === true;
|
|
525
|
+
if (!isComponent ||
|
|
526
|
+
(restrictToComponentsWithJsxReturn && !returnsJsx) ||
|
|
527
|
+
!isExportedComponentName(node.id.name, node)) {
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
componentCandidates.push({
|
|
531
|
+
componentName: node.id.name,
|
|
532
|
+
node,
|
|
533
|
+
propsType: getPropsTypeFromVariableDeclarator(node),
|
|
534
|
+
});
|
|
535
|
+
},
|
|
536
|
+
"Program:exit"() {
|
|
537
|
+
componentCandidates.forEach(checkCandidate);
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
//# sourceMappingURL=require-component-prop-contracts.js.map
|
package/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-component-prop-contracts.js","sourceRoot":"","sources":["../../../../../../../../libs/eslint/plugin-trackunit/src/lib/rules/require-component-prop-contracts/require-component-prop-contracts.ts"],"names":[],"mappings":"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","sourcesContent":["import { AST_NODE_TYPES, ESLintUtils, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as ts from \"typescript\";\nimport { functionReturnsIntrinsicJSX, isReactComponent } from \"../../utils/ast-utils\";\nimport { getProjectMetadata } from \"../../utils/nx-utils\";\n\nconst createRule = ESLintUtils.RuleCreator(\n name => `https://github.com/trackunit/manager/blob/main/libs/eslint/plugin-trackunit/src/lib/rules/${name}/${name}.ts`\n);\n\ntype Options = [\n {\n requiredProps?: ReadonlyArray<string>;\n requiredInterfaces?: ReadonlyArray<string>;\n restrictToComponentsWithJsxReturn?: boolean;\n },\n];\n\ntype MessageIds = \"missingPropContracts\";\n\ntype ComponentCandidate = {\n componentName: string;\n node: TSESTree.Node;\n propsType: TSESTree.TypeNode | null;\n};\n\ntype TypeDeclarationMaps = {\n interfaces: Map<string, TSESTree.TSInterfaceDeclaration>;\n typeAliases: Map<string, TSESTree.TSTypeAliasDeclaration>;\n};\n\ntype TypeCheckerContext = {\n checker: ts.TypeChecker;\n services: ReturnType<typeof ESLintUtils.getParserServices>;\n};\n\nconst componentWrapperNames = new Set([\"forwardRef\", \"memo\"]);\n\nconst publicEntrypointFileNames = [\"index.ts\", \"index.tsx\"];\n\ntype TypeSymbolInfo = {\n symbolName: string | undefined;\n declarations: Array<ts.Declaration>;\n};\n\nconst getTypeSymbolInfo = (type: ts.Type): TypeSymbolInfo => {\n try {\n return {\n symbolName: type.symbol.getName(),\n declarations: type.symbol.getDeclarations() ?? [],\n };\n } catch {\n return {\n symbolName: undefined,\n declarations: [],\n };\n }\n};\n\nconst getTypeReferenceName = (typeName: TSESTree.EntityName): string | null => {\n if (typeName.type === AST_NODE_TYPES.Identifier) {\n return typeName.name;\n }\n\n if (typeName.type === AST_NODE_TYPES.TSQualifiedName) {\n return typeName.right.name;\n }\n\n return null;\n};\n\nconst getCallExpressionName = (node: TSESTree.CallExpression): string | null => {\n const { callee } = node;\n\n if (callee.type === AST_NODE_TYPES.Identifier) {\n return callee.name;\n }\n\n if (callee.type === AST_NODE_TYPES.MemberExpression && callee.property.type === AST_NODE_TYPES.Identifier) {\n return callee.property.name;\n }\n\n return null;\n};\n\nconst isPascalCaseName = (name: string): boolean => /^[A-Z]/.test(name);\n\nconst normalizeFilePath = (filePath: string): string => path.normalize(filePath);\n\nconst getProjectRoot = (projectJsonPath: string): string => path.dirname(projectJsonPath);\n\nconst getPublicEntrypointPaths = (projectRoot: string): Array<string> =>\n publicEntrypointFileNames.map(fileName => path.join(projectRoot, \"src\", fileName));\n\nconst getModulePathCandidates = (fromFilePath: string, moduleSpecifier: string): Array<string> => {\n const modulePath = path.resolve(path.dirname(fromFilePath), moduleSpecifier);\n\n return [\n modulePath,\n `${modulePath}.ts`,\n `${modulePath}.tsx`,\n path.join(modulePath, \"index.ts\"),\n path.join(modulePath, \"index.tsx\"),\n ];\n};\n\nconst moduleSpecifierTargetsFile = (fromFilePath: string, moduleSpecifier: string, targetFilePath: string): boolean => {\n if (!moduleSpecifier.startsWith(\".\")) {\n return false;\n }\n\n const normalizedTargetFilePath = normalizeFilePath(targetFilePath);\n return getModulePathCandidates(fromFilePath, moduleSpecifier).some(\n candidatePath => normalizeFilePath(candidatePath) === normalizedTargetFilePath\n );\n};\n\nconst getSourceExportName = (specifier: ts.ExportSpecifier): string => {\n if (specifier.propertyName?.text === \"default\") {\n return specifier.name.text;\n }\n\n return specifier.propertyName?.text ?? specifier.name.text;\n};\n\nconst getPublicExportedNamesForFile = (\n projectRoot: string,\n filePath: string\n): { exportsAll: boolean; names: Set<string> } => {\n const result = {\n exportsAll: false,\n names: new Set<string>(),\n };\n\n for (const entrypointPath of getPublicEntrypointPaths(projectRoot)) {\n let sourceText: string;\n try {\n sourceText = fs.readFileSync(entrypointPath, \"utf8\");\n } catch {\n continue;\n }\n\n const sourceFile = ts.createSourceFile(entrypointPath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n\n for (const statement of sourceFile.statements) {\n if (!ts.isExportDeclaration(statement) || !statement.moduleSpecifier) {\n continue;\n }\n\n if (!ts.isStringLiteral(statement.moduleSpecifier)) {\n continue;\n }\n\n if (!moduleSpecifierTargetsFile(entrypointPath, statement.moduleSpecifier.text, filePath)) {\n continue;\n }\n\n if (!statement.exportClause) {\n result.exportsAll = true;\n continue;\n }\n\n if (ts.isNamedExports(statement.exportClause)) {\n statement.exportClause.elements.forEach(specifier => {\n result.names.add(getSourceExportName(specifier));\n });\n }\n }\n }\n\n return result;\n};\n\nconst isEntrypointFile = (projectRoot: string, filePath: string): boolean => {\n const normalizedFilePath = normalizeFilePath(filePath);\n return getPublicEntrypointPaths(projectRoot).some(\n entrypointPath => normalizeFilePath(entrypointPath) === normalizedFilePath\n );\n};\n\nconst isComponentWrapperCallExpression = (node: TSESTree.CallExpression): boolean => {\n const firstArgument = node.arguments[0];\n const callExpressionName = getCallExpressionName(node);\n\n if (!callExpressionName || !componentWrapperNames.has(callExpressionName)) {\n return false;\n }\n\n return (\n firstArgument?.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument?.type === AST_NODE_TYPES.FunctionExpression\n );\n};\n\nconst getWrappedComponentFunction = (\n node: TSESTree.CallExpression\n): TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression | null => {\n if (!isComponentWrapperCallExpression(node)) {\n return null;\n }\n\n const firstArgument = node.arguments[0];\n return firstArgument &&\n (firstArgument.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument.type === AST_NODE_TYPES.FunctionExpression)\n ? firstArgument\n : null;\n};\n\nconst getHeritageName = (heritage: TSESTree.TSInterfaceHeritage): string | null => {\n const { expression } = heritage;\n\n if (expression.type === AST_NODE_TYPES.Identifier) {\n return expression.name;\n }\n\n if (expression.type === AST_NODE_TYPES.MemberExpression && expression.property.type === AST_NODE_TYPES.Identifier) {\n return expression.property.name;\n }\n\n return null;\n};\n\nconst getParameterTypeAnnotation = (parameter: TSESTree.Parameter | undefined): TSESTree.TypeNode | null => {\n if (!parameter) {\n return null;\n }\n\n if (parameter.type === AST_NODE_TYPES.Identifier || parameter.type === AST_NODE_TYPES.ObjectPattern) {\n return parameter.typeAnnotation?.typeAnnotation ?? null;\n }\n\n if (parameter.type === AST_NODE_TYPES.AssignmentPattern) {\n const { left } = parameter;\n if (left.type === AST_NODE_TYPES.Identifier || left.type === AST_NODE_TYPES.ObjectPattern) {\n return left.typeAnnotation?.typeAnnotation ?? null;\n }\n }\n\n return null;\n};\n\nconst getFunctionPropsType = (\n node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): TSESTree.TypeNode | null => getParameterTypeAnnotation(node.params[0]);\n\nconst getPropsTypeFromCallExpression = (node: TSESTree.CallExpression): TSESTree.TypeNode | null => {\n const typeArguments = node.typeArguments?.params ?? [];\n const firstArgument = node.arguments[0];\n\n if (\n firstArgument?.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n firstArgument?.type === AST_NODE_TYPES.FunctionExpression\n ) {\n const parameterType = getParameterTypeAnnotation(firstArgument.params[0]);\n if (parameterType) {\n return parameterType;\n }\n }\n\n if (getCallExpressionName(node) === \"forwardRef\") {\n return typeArguments[1] ?? null;\n }\n\n return typeArguments[0] ?? null;\n};\n\nconst getPropsTypeFromVariableDeclarator = (node: TSESTree.VariableDeclarator): TSESTree.TypeNode | null => {\n const { init } = node;\n\n if (!init) {\n return null;\n }\n\n if (init.type === AST_NODE_TYPES.ArrowFunctionExpression) {\n return getFunctionPropsType(init);\n }\n\n if (init.type === AST_NODE_TYPES.CallExpression) {\n return getPropsTypeFromCallExpression(init);\n }\n\n return null;\n};\n\nconst isExportedDeclaration = (node: TSESTree.Node): boolean => {\n const parent = node.parent;\n if (!parent) {\n return false;\n }\n\n if (\n parent.type === AST_NODE_TYPES.ExportNamedDeclaration ||\n parent.type === AST_NODE_TYPES.ExportDefaultDeclaration\n ) {\n return true;\n }\n\n const grandParent = parent.parent;\n return grandParent?.type === AST_NODE_TYPES.ExportNamedDeclaration;\n};\n\nconst typeHasRequiredInterface = (\n typeNode: TSESTree.TypeNode,\n requiredInterface: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames = new Set<string>()\n): boolean => {\n switch (typeNode.type) {\n case AST_NODE_TYPES.TSTypeReference: {\n const referenceName = getTypeReferenceName(typeNode.typeName);\n if (!referenceName) {\n return false;\n }\n\n if (referenceName === requiredInterface) {\n return true;\n }\n\n if (visitedTypeNames.has(referenceName)) {\n return false;\n }\n\n visitedTypeNames.add(referenceName);\n\n const interfaceDeclaration = declarations.interfaces.get(referenceName);\n if (interfaceDeclaration) {\n return interfaceExtendsRequiredInterface(\n interfaceDeclaration,\n requiredInterface,\n declarations,\n visitedTypeNames\n );\n }\n\n const typeAlias = declarations.typeAliases.get(referenceName);\n if (typeAlias) {\n return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);\n }\n\n return false;\n }\n\n case AST_NODE_TYPES.TSIntersectionType:\n return typeNode.types.some(part =>\n typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames))\n );\n\n case AST_NODE_TYPES.TSUnionType:\n return typeNode.types.every(part =>\n typeHasRequiredInterface(part, requiredInterface, declarations, new Set(visitedTypeNames))\n );\n\n default:\n return false;\n }\n};\n\nconst interfaceExtendsRequiredInterface = (\n declaration: TSESTree.TSInterfaceDeclaration,\n requiredInterface: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames: Set<string>\n): boolean => {\n return declaration.extends.some(heritage => {\n const heritageName = getHeritageName(heritage);\n if (!heritageName) {\n return false;\n }\n\n if (heritageName === requiredInterface) {\n return true;\n }\n\n if (visitedTypeNames.has(heritageName)) {\n return false;\n }\n\n visitedTypeNames.add(heritageName);\n\n const interfaceDeclaration = declarations.interfaces.get(heritageName);\n if (interfaceDeclaration) {\n return interfaceExtendsRequiredInterface(interfaceDeclaration, requiredInterface, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(heritageName);\n if (typeAlias) {\n return typeHasRequiredInterface(typeAlias.typeAnnotation, requiredInterface, declarations, visitedTypeNames);\n }\n\n return false;\n });\n};\n\nconst interfaceHasRequiredProp = (\n declaration: TSESTree.TSInterfaceDeclaration,\n requiredProp: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames: Set<string>\n): boolean => {\n const hasOwnProp = declaration.body.body.some(member => {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return false;\n }\n\n return member.key.type === AST_NODE_TYPES.Identifier && member.key.name === requiredProp;\n });\n\n if (hasOwnProp) {\n return true;\n }\n\n return declaration.extends.some(heritage => {\n const heritageName = getHeritageName(heritage);\n if (!heritageName || visitedTypeNames.has(heritageName)) {\n return false;\n }\n\n visitedTypeNames.add(heritageName);\n\n const interfaceDeclaration = declarations.interfaces.get(heritageName);\n if (interfaceDeclaration) {\n return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(heritageName);\n if (typeAlias) {\n return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);\n }\n\n return false;\n });\n};\n\nconst typeLiteralHasRequiredProp = (typeNode: TSESTree.TSTypeLiteral, requiredProp: string): boolean => {\n return typeNode.members.some(member => {\n if (member.type !== AST_NODE_TYPES.TSPropertySignature) {\n return false;\n }\n\n return member.key.type === AST_NODE_TYPES.Identifier && member.key.name === requiredProp;\n });\n};\n\nconst typeHasRequiredProp = (\n typeNode: TSESTree.TypeNode,\n requiredProp: string,\n declarations: TypeDeclarationMaps,\n visitedTypeNames = new Set<string>()\n): boolean => {\n switch (typeNode.type) {\n case AST_NODE_TYPES.TSTypeLiteral:\n return typeLiteralHasRequiredProp(typeNode, requiredProp);\n\n case AST_NODE_TYPES.TSTypeReference: {\n const referenceName = getTypeReferenceName(typeNode.typeName);\n if (!referenceName || visitedTypeNames.has(referenceName)) {\n return false;\n }\n\n visitedTypeNames.add(referenceName);\n\n const interfaceDeclaration = declarations.interfaces.get(referenceName);\n if (interfaceDeclaration) {\n return interfaceHasRequiredProp(interfaceDeclaration, requiredProp, declarations, visitedTypeNames);\n }\n\n const typeAlias = declarations.typeAliases.get(referenceName);\n if (typeAlias) {\n return typeHasRequiredProp(typeAlias.typeAnnotation, requiredProp, declarations, visitedTypeNames);\n }\n\n return false;\n }\n\n case AST_NODE_TYPES.TSIntersectionType:\n return typeNode.types.some(part =>\n typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames))\n );\n\n case AST_NODE_TYPES.TSUnionType:\n return typeNode.types.every(part =>\n typeHasRequiredProp(part, requiredProp, declarations, new Set(visitedTypeNames))\n );\n\n default:\n return false;\n }\n};\n\nconst getTypeCheckerContext = (context: TSESLint.RuleContext<MessageIds, Options>): TypeCheckerContext | null => {\n try {\n const services = ESLintUtils.getParserServices(context);\n return {\n checker: services.program.getTypeChecker(),\n services,\n };\n } catch {\n return null;\n }\n};\n\nexport const checkerTypeHasRequiredInterface = (\n type: ts.Type,\n requiredInterface: string,\n checker: ts.TypeChecker,\n visitedTypeNames = new Set<string>()\n): boolean => {\n if (type.isUnion()) {\n return type.types.every(part => checkerTypeHasRequiredInterface(part, requiredInterface, checker, new Set()));\n }\n\n if (type.isIntersection()) {\n return type.types.some(part =>\n checkerTypeHasRequiredInterface(part, requiredInterface, checker, new Set(visitedTypeNames))\n );\n }\n\n const { symbolName, declarations } = getTypeSymbolInfo(type);\n const aliasSymbolName = type.aliasSymbol?.getName();\n\n if (symbolName === requiredInterface || aliasSymbolName === requiredInterface) {\n return true;\n }\n\n const visitKey = aliasSymbolName ?? symbolName;\n if (visitKey) {\n if (visitedTypeNames.has(visitKey)) {\n return false;\n }\n visitedTypeNames.add(visitKey);\n }\n\n if (\n type.aliasTypeArguments?.some(typeArgument =>\n checkerTypeHasRequiredInterface(typeArgument, requiredInterface, checker)\n )\n ) {\n return true;\n }\n\n if (type.isClassOrInterface()) {\n const baseTypes = checker.getBaseTypes(type);\n if (\n baseTypes.some(baseType =>\n checkerTypeHasRequiredInterface(baseType, requiredInterface, checker, visitedTypeNames)\n )\n ) {\n return true;\n }\n }\n\n return declarations.some(declaration => {\n if (!ts.isInterfaceDeclaration(declaration) || !declaration.heritageClauses) {\n return false;\n }\n\n return declaration.heritageClauses.some(heritageClause =>\n heritageClause.types.some(heritageType => {\n const heritageInterfaceType = checker.getTypeAtLocation(heritageType);\n return checkerTypeHasRequiredInterface(heritageInterfaceType, requiredInterface, checker, visitedTypeNames);\n })\n );\n });\n};\n\nconst checkerTypeHasRequiredProp = (type: ts.Type, requiredProp: string, checker: ts.TypeChecker): boolean => {\n if (type.isUnion()) {\n return type.types.every(part => checkerTypeHasRequiredProp(part, requiredProp, checker));\n }\n\n return Boolean(type.getProperty(requiredProp));\n};\n\nconst getCheckerType = (typeNode: TSESTree.TypeNode, typeCheckerContext: TypeCheckerContext | null): ts.Type | null => {\n if (!typeCheckerContext) {\n return null;\n }\n\n const tsNode = typeCheckerContext.services.esTreeNodeToTSNodeMap.get(typeNode);\n return typeCheckerContext.checker.getTypeAtLocation(tsNode);\n};\n\nexport const requireComponentPropContracts = createRule<Options, MessageIds>({\n name: \"require-component-prop-contracts\",\n meta: {\n type: \"problem\",\n docs: {\n description:\n \"Require exported React component props to include configured prop names or extend configured interfaces.\",\n },\n schema: [\n {\n type: \"object\",\n properties: {\n requiredProps: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Prop names every exported component props type must include.\",\n },\n requiredInterfaces: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Interface names every exported component props type must reference or extend.\",\n },\n restrictToComponentsWithJsxReturn: {\n type: \"boolean\",\n description:\n \"When true, only enforce for components that return intrinsic JSX. Defaults to false (all components).\",\n },\n },\n additionalProperties: false,\n },\n ],\n messages: {\n missingPropContracts:\n \"Public component '{{componentName}}' props must satisfy these contracts: {{missingContracts}}.\",\n },\n },\n defaultOptions: [\n {\n requiredProps: [],\n requiredInterfaces: [],\n restrictToComponentsWithJsxReturn: false,\n },\n ],\n create(context, [options]) {\n const filename = context.filename;\n if (!filename.endsWith(\".tsx\")) {\n return {};\n }\n\n const projectMetadata = getProjectMetadata(filename);\n if (!projectMetadata) {\n return {};\n }\n\n const requiredProps = options.requiredProps ?? [];\n const requiredInterfaces = options.requiredInterfaces ?? [];\n const restrictToComponentsWithJsxReturn = options.restrictToComponentsWithJsxReturn ?? false;\n if (requiredProps.length === 0 && requiredInterfaces.length === 0) {\n return {};\n }\n\n const declarations: TypeDeclarationMaps = {\n interfaces: new Map(),\n typeAliases: new Map(),\n };\n const typeCheckerContext = getTypeCheckerContext(context);\n const exportedIdentifiers = new Set<string>();\n const componentCandidates: Array<ComponentCandidate> = [];\n const projectRoot = getProjectRoot(projectMetadata.projectJsonPath);\n const publicExports = getPublicExportedNamesForFile(projectRoot, filename);\n const isCurrentFileEntrypoint = isEntrypointFile(projectRoot, filename);\n\n const isExportedComponentName = (componentName: string, node: TSESTree.Node): boolean => {\n if (\n !isPascalCaseName(componentName) ||\n (!isExportedDeclaration(node) && !exportedIdentifiers.has(componentName))\n ) {\n return false;\n }\n\n return isCurrentFileEntrypoint || publicExports.exportsAll || publicExports.names.has(componentName);\n };\n\n const checkCandidate = (candidate: ComponentCandidate): void => {\n const checkerType = candidate.propsType ? getCheckerType(candidate.propsType, typeCheckerContext) : null;\n const missingProps = requiredProps.filter(\n requiredProp =>\n !candidate.propsType ||\n (checkerType && typeCheckerContext\n ? !checkerTypeHasRequiredProp(checkerType, requiredProp, typeCheckerContext.checker)\n : !typeHasRequiredProp(candidate.propsType, requiredProp, declarations, new Set()))\n );\n const missingInterfaces = requiredInterfaces.filter(\n requiredInterface =>\n !candidate.propsType ||\n (checkerType && typeCheckerContext\n ? !checkerTypeHasRequiredInterface(checkerType, requiredInterface, typeCheckerContext.checker)\n : !typeHasRequiredInterface(candidate.propsType, requiredInterface, declarations, new Set()))\n );\n const missingContracts = [...missingProps, ...missingInterfaces];\n\n if (missingContracts.length === 0) {\n return;\n }\n\n context.report({\n node: candidate.node,\n messageId: \"missingPropContracts\",\n data: {\n componentName: candidate.componentName,\n missingContracts: missingContracts.join(\", \"),\n },\n });\n };\n\n return {\n ExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration) {\n for (const specifier of node.specifiers) {\n if (specifier.local.type === AST_NODE_TYPES.Identifier) {\n exportedIdentifiers.add(specifier.local.name);\n }\n }\n },\n\n ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration) {\n if (node.declaration.type === AST_NODE_TYPES.Identifier) {\n exportedIdentifiers.add(node.declaration.name);\n }\n },\n\n TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration) {\n declarations.interfaces.set(node.id.name, node);\n },\n\n TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration) {\n declarations.typeAliases.set(node.id.name, node);\n },\n\n FunctionDeclaration(node: TSESTree.FunctionDeclaration) {\n const componentName = node.id?.name;\n const returnsIntrinsicJsx = functionReturnsIntrinsicJSX(node) === true;\n if (\n !componentName ||\n !isReactComponent(node) ||\n (restrictToComponentsWithJsxReturn && !returnsIntrinsicJsx) ||\n !isExportedComponentName(componentName, node)\n ) {\n return;\n }\n\n componentCandidates.push({\n componentName,\n node,\n propsType: getFunctionPropsType(node),\n });\n },\n\n VariableDeclarator(node: TSESTree.VariableDeclarator) {\n if (node.id.type !== AST_NODE_TYPES.Identifier) {\n return;\n }\n\n const { init } = node;\n const wrappedComponentFunction =\n init?.type === AST_NODE_TYPES.CallExpression ? getWrappedComponentFunction(init) : null;\n const isComponent =\n init?.type === AST_NODE_TYPES.ArrowFunctionExpression\n ? isReactComponent(init)\n : wrappedComponentFunction !== null;\n const returnsJsx =\n init?.type === AST_NODE_TYPES.ArrowFunctionExpression\n ? functionReturnsIntrinsicJSX(init) === true\n : wrappedComponentFunction !== null && functionReturnsIntrinsicJSX(wrappedComponentFunction) === true;\n\n if (\n !isComponent ||\n (restrictToComponentsWithJsxReturn && !returnsJsx) ||\n !isExportedComponentName(node.id.name, node)\n ) {\n return;\n }\n\n componentCandidates.push({\n componentName: node.id.name,\n node,\n propsType: getPropsTypeFromVariableDeclarator(node),\n });\n },\n\n \"Program:exit\"() {\n componentCandidates.forEach(checkCandidate);\n },\n };\n },\n});\n"]}
|
package/src/lib/rules-map.d.ts
CHANGED
|
@@ -54,6 +54,13 @@ export declare const rulesMap: {
|
|
|
54
54
|
}], unknown, ESLintUtils.RuleListener> & {
|
|
55
55
|
name: string;
|
|
56
56
|
};
|
|
57
|
+
"require-component-prop-contracts": ESLintUtils.RuleModule<"missingPropContracts", [{
|
|
58
|
+
requiredProps?: ReadonlyArray<string>;
|
|
59
|
+
requiredInterfaces?: ReadonlyArray<string>;
|
|
60
|
+
restrictToComponentsWithJsxReturn?: boolean;
|
|
61
|
+
}], unknown, ESLintUtils.RuleListener> & {
|
|
62
|
+
name: string;
|
|
63
|
+
};
|
|
57
64
|
"prefer-field-components": ESLintUtils.RuleModule<"preferFieldComponent", [], unknown, ESLintUtils.RuleListener> & {
|
|
58
65
|
name: string;
|
|
59
66
|
};
|
package/src/lib/rules-map.js
CHANGED
|
@@ -13,6 +13,7 @@ const prefer_event_specific_callback_naming_1 = require("./rules/prefer-event-sp
|
|
|
13
13
|
const prefer_field_components_1 = require("./rules/prefer-field-components/prefer-field-components");
|
|
14
14
|
const prefer_mouse_event_handler_in_react_props_1 = require("./rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props");
|
|
15
15
|
const require_classname_alternatives_1 = require("./rules/require-classname-alternatives/require-classname-alternatives");
|
|
16
|
+
const require_component_prop_contracts_1 = require("./rules/require-component-prop-contracts/require-component-prop-contracts");
|
|
16
17
|
const require_list_item_virtualization_props_1 = require("./rules/require-list-item-virtualization-props/require-list-item-virtualization-props");
|
|
17
18
|
const require_optional_prop_initialization_1 = require("./rules/require-optional-prop-initialization/require-optional-prop-initialization");
|
|
18
19
|
exports.rulesMap = {
|
|
@@ -28,6 +29,7 @@ exports.rulesMap = {
|
|
|
28
29
|
"prefer-mouse-event-handler-in-react-props": prefer_mouse_event_handler_in_react_props_1.preferMouseEventHandlerInReactProps,
|
|
29
30
|
"prefer-event-specific-callback-naming": prefer_event_specific_callback_naming_1.preferEventSpecificCallbackNaming,
|
|
30
31
|
"require-optional-prop-initialization": require_optional_prop_initialization_1.requireOptionalPropInitialization,
|
|
32
|
+
"require-component-prop-contracts": require_component_prop_contracts_1.requireComponentPropContracts,
|
|
31
33
|
"prefer-field-components": prefer_field_components_1.preferFieldComponents,
|
|
32
34
|
"require-list-item-virtualization-props": require_list_item_virtualization_props_1.requireListItemVirtualizationProps,
|
|
33
35
|
};
|
package/src/lib/rules-map.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules-map.js","sourceRoot":"","sources":["../../../../../../libs/eslint/plugin-trackunit/src/lib/rules-map.ts"],"names":[],"mappings":";;;AACA,6HAAqH;AACrH,qJAA6I;AAC7I,wGAAkG;AAClG,6KAAmK;AACnK,qJAA4I;AAC5I,+IAAmI;AACnI,qGAAgG;AAChG,iHAA4G;AAC5G,+IAAwI;AACxI,qGAAgG;AAChG,2JAAkJ;AAClJ,0HAAqH;AACrH,kJAA2I;AAC3I,4IAAsI;AAEzH,QAAA,QAAQ,GAAG;IACtB,iCAAiC,EAAE,4DAA0B;IAC7D,0BAA0B,EAAE,gDAAqB;IACjD,yBAAyB,EAAE,+CAAqB;IAChD,iDAAiD,EAAE,0FAAwC;IAC3F,yCAAyC,EAAE,4EAAkC;IAC7E,uCAAuC,EAAE,oEAA4B;IACrE,gCAAgC,EAAE,6DAA4B;IAC9D,yCAAyC,EAAE,2EAAiC;IAC5E,6BAA6B,EAAE,uDAAyB;IACxD,2CAA2C,EAAE,+EAAmC;IAChF,uCAAuC,EAAE,yEAAiC;IAC1E,sCAAsC,EAAE,wEAAiC;IACzE,yBAAyB,EAAE,+CAAqB;IAChD,wCAAwC,EAAE,2EAAkC;CACI,CAAC","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { cvaMergeBaseClassesAsArray } from \"./rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array\";\nimport { designGuidelineButtonIconSizeMatch } from \"./rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match\";\nimport { noInternalBarrelFiles } from \"./rules/no-internal-barrel-files/no-internal-barrel-files\";\nimport { noInternalGraphqlWhenTaggedWithGqlPublic } from \"./rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public\";\nimport { noJestMockTrackunitReactCoreHooks } from \"./rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks\";\nimport { noTemplateStringsInClassName } from \"./rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop\";\nimport { noTypescriptAssertion } from \"./rules/no-typescript-assertion/no-typescript-assertion\";\nimport { preferDestructuredImports } from \"./rules/prefer-destructured-imports/prefer-destructured-imports\";\nimport { preferEventSpecificCallbackNaming } from \"./rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming\";\nimport { preferFieldComponents } from \"./rules/prefer-field-components/prefer-field-components\";\nimport { preferMouseEventHandlerInReactProps } from \"./rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props\";\nimport { requireClassnameAlternatives } from \"./rules/require-classname-alternatives/require-classname-alternatives\";\nimport { requireListItemVirtualizationProps } from \"./rules/require-list-item-virtualization-props/require-list-item-virtualization-props\";\nimport { requireOptionalPropInitialization } from \"./rules/require-optional-prop-initialization/require-optional-prop-initialization\";\n\nexport const rulesMap = {\n \"cva-merge-base-classes-as-array\": cvaMergeBaseClassesAsArray,\n \"no-internal-barrel-files\": noInternalBarrelFiles,\n \"no-typescript-assertion\": noTypescriptAssertion,\n \"no-internal-graphql-when-tagged-with-gql-public\": noInternalGraphqlWhenTaggedWithGqlPublic,\n \"design-guideline-button-icon-size-match\": designGuidelineButtonIconSizeMatch,\n \"no-template-strings-in-classname-prop\": noTemplateStringsInClassName,\n \"require-classname-alternatives\": requireClassnameAlternatives,\n \"no-jest-mock-trackunit-react-core-hooks\": noJestMockTrackunitReactCoreHooks,\n \"prefer-destructured-imports\": preferDestructuredImports,\n \"prefer-mouse-event-handler-in-react-props\": preferMouseEventHandlerInReactProps,\n \"prefer-event-specific-callback-naming\": preferEventSpecificCallbackNaming,\n \"require-optional-prop-initialization\": requireOptionalPropInitialization,\n \"prefer-field-components\": preferFieldComponents,\n \"require-list-item-virtualization-props\": requireListItemVirtualizationProps,\n} satisfies Record<string, ESLintUtils.RuleModule<string, ReadonlyArray<unknown>>>;\n"]}
|
|
1
|
+
{"version":3,"file":"rules-map.js","sourceRoot":"","sources":["../../../../../../libs/eslint/plugin-trackunit/src/lib/rules-map.ts"],"names":[],"mappings":";;;AACA,6HAAqH;AACrH,qJAA6I;AAC7I,wGAAkG;AAClG,6KAAmK;AACnK,qJAA4I;AAC5I,+IAAmI;AACnI,qGAAgG;AAChG,iHAA4G;AAC5G,+IAAwI;AACxI,qGAAgG;AAChG,2JAAkJ;AAClJ,0HAAqH;AACrH,gIAA0H;AAC1H,kJAA2I;AAC3I,4IAAsI;AAEzH,QAAA,QAAQ,GAAG;IACtB,iCAAiC,EAAE,4DAA0B;IAC7D,0BAA0B,EAAE,gDAAqB;IACjD,yBAAyB,EAAE,+CAAqB;IAChD,iDAAiD,EAAE,0FAAwC;IAC3F,yCAAyC,EAAE,4EAAkC;IAC7E,uCAAuC,EAAE,oEAA4B;IACrE,gCAAgC,EAAE,6DAA4B;IAC9D,yCAAyC,EAAE,2EAAiC;IAC5E,6BAA6B,EAAE,uDAAyB;IACxD,2CAA2C,EAAE,+EAAmC;IAChF,uCAAuC,EAAE,yEAAiC;IAC1E,sCAAsC,EAAE,wEAAiC;IACzE,kCAAkC,EAAE,gEAA6B;IACjE,yBAAyB,EAAE,+CAAqB;IAChD,wCAAwC,EAAE,2EAAkC;CACI,CAAC","sourcesContent":["import { ESLintUtils } from \"@typescript-eslint/utils\";\nimport { cvaMergeBaseClassesAsArray } from \"./rules/cva-merge-base-classes-as-array/cva-merge-base-classes-as-array\";\nimport { designGuidelineButtonIconSizeMatch } from \"./rules/design-guideline-button-icon-size-match/design-guideline-button-icon-size-match\";\nimport { noInternalBarrelFiles } from \"./rules/no-internal-barrel-files/no-internal-barrel-files\";\nimport { noInternalGraphqlWhenTaggedWithGqlPublic } from \"./rules/no-internal-graphql-when-tagged-with-gql-public/no-internal-graphql-when-tagged-with-gql-public\";\nimport { noJestMockTrackunitReactCoreHooks } from \"./rules/no-jest-mock-trackunit-react-core-hooks/no-jest-mock-trackunit-react-core-hooks\";\nimport { noTemplateStringsInClassName } from \"./rules/no-template-strings-in-classname-prop/no-template-strings-in-classname-prop\";\nimport { noTypescriptAssertion } from \"./rules/no-typescript-assertion/no-typescript-assertion\";\nimport { preferDestructuredImports } from \"./rules/prefer-destructured-imports/prefer-destructured-imports\";\nimport { preferEventSpecificCallbackNaming } from \"./rules/prefer-event-specific-callback-naming/prefer-event-specific-callback-naming\";\nimport { preferFieldComponents } from \"./rules/prefer-field-components/prefer-field-components\";\nimport { preferMouseEventHandlerInReactProps } from \"./rules/prefer-mouse-event-handler-in-react-props/prefer-mouse-event-handler-in-react-props\";\nimport { requireClassnameAlternatives } from \"./rules/require-classname-alternatives/require-classname-alternatives\";\nimport { requireComponentPropContracts } from \"./rules/require-component-prop-contracts/require-component-prop-contracts\";\nimport { requireListItemVirtualizationProps } from \"./rules/require-list-item-virtualization-props/require-list-item-virtualization-props\";\nimport { requireOptionalPropInitialization } from \"./rules/require-optional-prop-initialization/require-optional-prop-initialization\";\n\nexport const rulesMap = {\n \"cva-merge-base-classes-as-array\": cvaMergeBaseClassesAsArray,\n \"no-internal-barrel-files\": noInternalBarrelFiles,\n \"no-typescript-assertion\": noTypescriptAssertion,\n \"no-internal-graphql-when-tagged-with-gql-public\": noInternalGraphqlWhenTaggedWithGqlPublic,\n \"design-guideline-button-icon-size-match\": designGuidelineButtonIconSizeMatch,\n \"no-template-strings-in-classname-prop\": noTemplateStringsInClassName,\n \"require-classname-alternatives\": requireClassnameAlternatives,\n \"no-jest-mock-trackunit-react-core-hooks\": noJestMockTrackunitReactCoreHooks,\n \"prefer-destructured-imports\": preferDestructuredImports,\n \"prefer-mouse-event-handler-in-react-props\": preferMouseEventHandlerInReactProps,\n \"prefer-event-specific-callback-naming\": preferEventSpecificCallbackNaming,\n \"require-optional-prop-initialization\": requireOptionalPropInitialization,\n \"require-component-prop-contracts\": requireComponentPropContracts,\n \"prefer-field-components\": preferFieldComponents,\n \"require-list-item-virtualization-props\": requireListItemVirtualizationProps,\n} satisfies Record<string, ESLintUtils.RuleModule<string, ReadonlyArray<unknown>>>;\n"]}
|
|
@@ -16,6 +16,9 @@ export declare const isParameterInitialized: (functionBody: Array<TSESTree.State
|
|
|
16
16
|
* Check if a parameter is used within the function body
|
|
17
17
|
*/
|
|
18
18
|
export declare const isParameterUsedInFunction: (context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>, functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression, paramName: string) => boolean;
|
|
19
|
+
type FunctionLikeNode = TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;
|
|
20
|
+
export declare const functionReturnsJSX: (node: FunctionLikeNode) => boolean;
|
|
21
|
+
export declare const functionReturnsIntrinsicJSX: (node: FunctionLikeNode) => boolean;
|
|
19
22
|
/**
|
|
20
23
|
* Check if a function is likely a React component based on naming and JSX usage
|
|
21
24
|
*/
|
|
@@ -83,3 +86,4 @@ export declare const isIdentifierFromParameter: (identifier: TSESTree.Identifier
|
|
|
83
86
|
* // isIdentifierFromRenderPropCallback(onClose) => false
|
|
84
87
|
*/
|
|
85
88
|
export declare const isIdentifierFromRenderPropCallback: (identifier: TSESTree.Identifier, context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>) => boolean;
|
|
89
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isIdentifierFromRenderPropCallback = exports.isIdentifierFromParameter = exports.isParameterOnlyUsedInJSX = exports.isReactComponent = exports.isParameterUsedInFunction = exports.isParameterInitialized = exports.hasExistingBodyInitializations = exports.isParameterExplicitlyDestructured = void 0;
|
|
3
|
+
exports.isIdentifierFromRenderPropCallback = exports.isIdentifierFromParameter = exports.isParameterOnlyUsedInJSX = exports.isReactComponent = exports.functionReturnsIntrinsicJSX = exports.functionReturnsJSX = exports.isParameterUsedInFunction = exports.isParameterInitialized = exports.hasExistingBodyInitializations = exports.isParameterExplicitlyDestructured = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
/**
|
|
6
6
|
* Utility functions for analyzing AST nodes and function structure in ESLint rules.
|
|
@@ -22,6 +22,8 @@ const utils_1 = require("@typescript-eslint/utils");
|
|
|
22
22
|
*
|
|
23
23
|
* ## JSX/React Specific
|
|
24
24
|
* - `isReactComponent()` - Check if function is likely a React component
|
|
25
|
+
* - `functionReturnsJSX()` - Check if function body returns JSX
|
|
26
|
+
* - `functionReturnsIntrinsicJSX()` - Check if function body returns intrinsic JSX tags (e.g. `div`, `span`)
|
|
25
27
|
* - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes
|
|
26
28
|
*/
|
|
27
29
|
/**
|
|
@@ -230,6 +232,76 @@ const getParameterRestUsage = (context, functionNode, paramName) => {
|
|
|
230
232
|
}
|
|
231
233
|
return { isUsedViaRest: false };
|
|
232
234
|
};
|
|
235
|
+
const jsxTagNameIsIntrinsic = (name) => name.type === utils_1.AST_NODE_TYPES.JSXIdentifier && /^[a-z]/.test(name.name);
|
|
236
|
+
const nodeContainsJSX = (node) => {
|
|
237
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXElement) {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
240
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXFragment) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
if (node.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
|
|
244
|
+
return nodeContainsJSX(node.consequent) || nodeContainsJSX(node.alternate);
|
|
245
|
+
}
|
|
246
|
+
if (node.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
|
|
247
|
+
return nodeContainsJSX(node.left) || nodeContainsJSX(node.right);
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
};
|
|
251
|
+
const nodeContainsIntrinsicJSX = (node) => {
|
|
252
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXElement) {
|
|
253
|
+
if (jsxTagNameIsIntrinsic(node.openingElement.name)) {
|
|
254
|
+
return true;
|
|
255
|
+
}
|
|
256
|
+
return node.children.some(child => {
|
|
257
|
+
if (child.type === utils_1.AST_NODE_TYPES.JSXElement || child.type === utils_1.AST_NODE_TYPES.JSXFragment) {
|
|
258
|
+
return nodeContainsIntrinsicJSX(child);
|
|
259
|
+
}
|
|
260
|
+
if (child.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
261
|
+
child.expression.type !== utils_1.AST_NODE_TYPES.JSXEmptyExpression) {
|
|
262
|
+
return nodeContainsIntrinsicJSX(child.expression);
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
if (node.type === utils_1.AST_NODE_TYPES.JSXFragment) {
|
|
268
|
+
return node.children.some(child => {
|
|
269
|
+
if (child.type === utils_1.AST_NODE_TYPES.JSXElement || child.type === utils_1.AST_NODE_TYPES.JSXFragment) {
|
|
270
|
+
return nodeContainsIntrinsicJSX(child);
|
|
271
|
+
}
|
|
272
|
+
if (child.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer &&
|
|
273
|
+
child.expression.type !== utils_1.AST_NODE_TYPES.JSXEmptyExpression) {
|
|
274
|
+
return nodeContainsIntrinsicJSX(child.expression);
|
|
275
|
+
}
|
|
276
|
+
return false;
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (node.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
|
|
280
|
+
return nodeContainsIntrinsicJSX(node.consequent) || nodeContainsIntrinsicJSX(node.alternate);
|
|
281
|
+
}
|
|
282
|
+
if (node.type === utils_1.AST_NODE_TYPES.LogicalExpression) {
|
|
283
|
+
return nodeContainsIntrinsicJSX(node.left) || nodeContainsIntrinsicJSX(node.right);
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
};
|
|
287
|
+
const functionReturnsJSX = (node) => {
|
|
288
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
289
|
+
return node.body.body.some(statement => statement.type === utils_1.AST_NODE_TYPES.ReturnStatement &&
|
|
290
|
+
statement.argument !== null &&
|
|
291
|
+
nodeContainsJSX(statement.argument));
|
|
292
|
+
}
|
|
293
|
+
return nodeContainsJSX(node.body);
|
|
294
|
+
};
|
|
295
|
+
exports.functionReturnsJSX = functionReturnsJSX;
|
|
296
|
+
const functionReturnsIntrinsicJSX = (node) => {
|
|
297
|
+
if (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
298
|
+
return node.body.body.some(statement => statement.type === utils_1.AST_NODE_TYPES.ReturnStatement &&
|
|
299
|
+
statement.argument !== null &&
|
|
300
|
+
nodeContainsIntrinsicJSX(statement.argument));
|
|
301
|
+
}
|
|
302
|
+
return nodeContainsIntrinsicJSX(node.body);
|
|
303
|
+
};
|
|
304
|
+
exports.functionReturnsIntrinsicJSX = functionReturnsIntrinsicJSX;
|
|
233
305
|
/**
|
|
234
306
|
* Check if a function is likely a React component based on naming and JSX usage
|
|
235
307
|
*/
|
|
@@ -240,26 +312,7 @@ const isReactComponent = (node) => {
|
|
|
240
312
|
if (functionName && startsWithUppercase.test(functionName)) {
|
|
241
313
|
return true;
|
|
242
314
|
}
|
|
243
|
-
|
|
244
|
-
const hasJSXReturn = (body) => {
|
|
245
|
-
if (body.type === utils_1.AST_NODE_TYPES.JSXElement || body.type === utils_1.AST_NODE_TYPES.JSXFragment) {
|
|
246
|
-
return true;
|
|
247
|
-
}
|
|
248
|
-
// Handle conditional expressions that contain JSX: condition ? <JSX /> : null
|
|
249
|
-
if (body.type === utils_1.AST_NODE_TYPES.ConditionalExpression) {
|
|
250
|
-
return hasJSXReturn(body.consequent) || hasJSXReturn(body.alternate);
|
|
251
|
-
}
|
|
252
|
-
if (body.type === utils_1.AST_NODE_TYPES.BlockStatement) {
|
|
253
|
-
return body.body.some(stmt => {
|
|
254
|
-
if (stmt.type === utils_1.AST_NODE_TYPES.ReturnStatement && stmt.argument) {
|
|
255
|
-
return hasJSXReturn(stmt.argument);
|
|
256
|
-
}
|
|
257
|
-
return false;
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
return false;
|
|
261
|
-
};
|
|
262
|
-
return hasJSXReturn(node.body);
|
|
315
|
+
return (0, exports.functionReturnsJSX)(node);
|
|
263
316
|
};
|
|
264
317
|
exports.isReactComponent = isReactComponent;
|
|
265
318
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/ast-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ASTUtils, AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for analyzing AST nodes and function structure in ESLint rules.\n *\n * ## Core Utilities\n * - `isInParameterList()` - Check if a node is in a function's parameter list\n *\n * ## Parameter Analysis (Parameter → Usage)\n * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured\n * - `isParameterInitialized()` - Check if parameter has a default value\n * - `isParameterUsedInFunction()` - Check if parameter is used in function body\n * - `getParameterRestUsage()` - Get info about parameter accessed via rest params\n * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body\n *\n * ## Identifier Origin Analysis (Usage → Origin)\n * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)\n * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter\n * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter\n *\n * ## JSX/React Specific\n * - `isReactComponent()` - Check if function is likely a React component\n * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes\n */\n\n/**\n * Helper function to check if a node is in the parameter list\n */\nconst isInParameterList = (\n node: TSESTree.Node,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): boolean => {\n let current = node.parent;\n while (current) {\n // Check if current node is one of the function parameters\n const isParam = functionNode.params.some(param => param === current);\n if (isParam) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\n\n/**\n * Check if a parameter is explicitly destructured in the parameter list\n * (vs. captured in rest parameters like ...restOptions)\n */\nexport const isParameterExplicitlyDestructured = (parameter: TSESTree.Parameter, paramName: string): boolean => {\n if (parameter.type !== AST_NODE_TYPES.ObjectPattern) {\n return false;\n }\n\n // Check if the parameter is explicitly listed in the destructuring\n return parameter.properties.some(property => {\n if (property.type === AST_NODE_TYPES.Property && property.key.type === AST_NODE_TYPES.Identifier) {\n return property.key.name === paramName;\n }\n return false;\n });\n};\n\n/**\n * Check if there are any existing parameter initializations in the function body\n */\nexport const hasExistingBodyInitializations = (functionBody: Array<TSESTree.Statement>): boolean => {\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern &&\n stmt.declarations[0].id.properties.some(\n prop => prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.AssignmentPattern\n )\n ) {\n return true;\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a parameter is initialized in the function body or parameter defaults\n */\nexport const isParameterInitialized = (\n functionBody: Array<TSESTree.Statement>,\n paramName: string,\n parameter?: TSESTree.Parameter\n): boolean => {\n // First check if the parameter has a default value in the parameter destructuring\n if (parameter && parameter.type === AST_NODE_TYPES.ObjectPattern) {\n for (const property of parameter.properties) {\n if (property.type === AST_NODE_TYPES.Property && property.value.type === AST_NODE_TYPES.AssignmentPattern) {\n // Handle both identifier keys (paramName) and string literal keys (\"param-name\")\n const keyName =\n property.key.type === AST_NODE_TYPES.Identifier\n ? property.key.name\n : property.key.type === AST_NODE_TYPES.Literal && typeof property.key.value === \"string\"\n ? property.key.value\n : null;\n\n if (keyName === paramName) {\n return true; // Found default value in parameter: {paramName = defaultValue}\n }\n }\n }\n }\n\n // Then check for initialization patterns in the function body\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern\n ) {\n const pattern = stmt.declarations[0].id;\n for (const property of pattern.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === paramName &&\n property.value.type === AST_NODE_TYPES.AssignmentPattern\n ) {\n return true;\n }\n }\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.Identifier &&\n stmt.declarations[0].id.name === paramName &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is used within the function body\n */\nexport const isParameterUsedInFunction = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (variable) {\n // Check if the variable has any references (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n // Exclude the parameter declaration itself\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n // Additional check: if the variable is only referenced in object literal shorthand property names\n // (like { placement: result.placement }), it's not actually using the parameter variable\n const actualUsageReferences = references.filter(ref => {\n const parent = ref.identifier.parent;\n\n // Skip if this is just a property key in an object literal\n // Example: { placement: result.placement } - the first 'placement' is just a key, not usage\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === ref.identifier &&\n parent.value !== ref.identifier &&\n !parent.shorthand\n ) {\n return false;\n }\n\n return true;\n });\n\n if (actualUsageReferences.length > 0) {\n return true;\n }\n }\n\n // If direct variable reference not found, check for member access on rest parameters\n // e.g., rest.paramName, params.paramName, etc.\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n // Look for rest elements in both direct params and inside object patterns\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return false;\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is accessed via rest parameters (e.g., rest.paramName)\n * and return information about the rest parameter usage\n */\nconst getParameterRestUsage = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): { isUsedViaRest: boolean; restParamName?: string; restParam?: TSESTree.Parameter } | null => {\n // Look for rest elements in both direct params and inside object patterns\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return { isUsedViaRest: false };\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return {\n isUsedViaRest: true,\n restParamName: restParam.name,\n restParam: restParam.param,\n };\n }\n }\n\n return { isUsedViaRest: false };\n};\n\n/**\n * Check if a function is likely a React component based on naming and JSX usage\n */\nexport const isReactComponent = (node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression): boolean => {\n // Check if function name starts with uppercase (React convention)\n const functionName = node.type === AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;\n const startsWithUppercase = /^[A-Z]/;\n if (functionName && startsWithUppercase.test(functionName)) {\n return true;\n }\n\n // Check if the function returns JSX\n const hasJSXReturn = (body: TSESTree.Node): boolean => {\n if (body.type === AST_NODE_TYPES.JSXElement || body.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n // Handle conditional expressions that contain JSX: condition ? <JSX /> : null\n if (body.type === AST_NODE_TYPES.ConditionalExpression) {\n return hasJSXReturn(body.consequent) || hasJSXReturn(body.alternate);\n }\n if (body.type === AST_NODE_TYPES.BlockStatement) {\n return body.body.some(stmt => {\n if (stmt.type === AST_NODE_TYPES.ReturnStatement && stmt.argument) {\n return hasJSXReturn(stmt.argument);\n }\n return false;\n });\n }\n return false;\n };\n\n return hasJSXReturn(node.body);\n};\n\n/**\n * Check if a parameter is only used in JSX attributes (pass-through to child components)\n * and nowhere else in the function body\n */\nexport const isParameterOnlyUsedInJSX = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (!variable) {\n return false;\n }\n\n // Get all references to the parameter (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n if (references.length === 0) {\n return false;\n }\n\n // Check if all references are only in JSX attribute expressions\n const allReferencesAreJSXAttributes = references.every(ref => {\n const identifier = ref.identifier;\n let current = identifier.parent;\n\n // Walk up the AST to find if this identifier is used in a JSX attribute\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions\n while (current) {\n // Check if we're in a JSX attribute expression: <Component prop={value} />\n if (current.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const jsxParent = current.parent;\n if (jsxParent.type === AST_NODE_TYPES.JSXAttribute) {\n return true;\n }\n }\n\n // Check if we're in a JSX spread attribute: <Component {...props} />\n if (current.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n return true;\n }\n\n // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)\n // These are acceptable for pass-through props since they're tracking the JSX usage\n if (current.type === AST_NODE_TYPES.ArrayExpression) {\n const callParent = current.parent;\n if (\n callParent.type === AST_NODE_TYPES.CallExpression &&\n callParent.callee.type === AST_NODE_TYPES.Identifier &&\n (callParent.callee.name.startsWith(\"use\") ||\n callParent.callee.name === \"useMemo\" ||\n callParent.callee.name === \"useCallback\" ||\n callParent.callee.name === \"useEffect\")\n ) {\n return true; // Allow dependency array usage\n }\n }\n\n // Stop if we reach certain node types that indicate we're not in JSX context\n if (\n current.type === AST_NODE_TYPES.VariableDeclarator ||\n current.type === AST_NODE_TYPES.AssignmentExpression ||\n current.type === AST_NODE_TYPES.CallExpression ||\n current.type === AST_NODE_TYPES.LogicalExpression ||\n current.type === AST_NODE_TYPES.ConditionalExpression ||\n current.type === AST_NODE_TYPES.BinaryExpression\n ) {\n return false;\n }\n\n if (!current.parent) {\n break;\n }\n current = current.parent;\n }\n\n return false;\n });\n\n return allReferencesAreJSXAttributes;\n};\n\n// ============================================================\n// Identifier Origin Analysis (traces usage back to definition)\n// ============================================================\n\n/**\n * Result of tracing an identifier back to its origin.\n * Used to distinguish between different ways an identifier can come from a function parameter.\n */\nexport type ParameterOriginResult =\n | {\n isFromParameter: true;\n /**\n * How the identifier relates to the parameter:\n * - \"direct-parameter\": Direct parameter, e.g., `(onClose) => ...`\n * - \"destructured-in-signature\": Destructured in function signature, e.g., `({ onClose }) => ...`\n * - \"destructured-in-body\": Destructured in function body, e.g., `const { onClose } = props`\n */\n originType: \"direct-parameter\" | \"destructured-in-signature\" | \"destructured-in-body\";\n }\n | { isFromParameter: false };\n\n/**\n * Checks if a variable is a function parameter.\n */\nconst isVariableAParameter = (variable: { defs: ReadonlyArray<{ type: string }> }): boolean => {\n return variable.defs.some(def => def.type === \"Parameter\");\n};\n\n/**\n * Traces an identifier back to determine if it originates from a function parameter.\n * Returns detailed information about how the identifier relates to the parameter.\n *\n * This is used to distinguish between:\n * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature\n * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body\n * - Direct parameter: `(onClose) => ...` - direct-parameter\n * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter\n * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns ParameterOriginResult with isFromParameter and originType if applicable\n * @example\n * // Direct parameter\n * const MyComponent = (onClose) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"direct-parameter\" }\n * @example\n * // Destructured in signature\n * const MyComponent = ({ onClose }) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-signature\" }\n * @example\n * // Destructured in body\n * const MyComponent = (props) => {\n * const { onClose } = props;\n * return <button onClick={onClose} />;\n * };\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-body\" }\n * @example\n * // Not from parameter (internal function)\n * const MyComponent = () => {\n * const handleClose = () => {};\n * return <button onClick={handleClose} />;\n * };\n * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }\n */\nconst getIdentifierParameterOrigin = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): ParameterOriginResult => {\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return { isFromParameter: false };\n }\n\n // Check the variable's definitions\n for (const definition of variable.defs) {\n // Check if defined as a direct function parameter\n if (definition.type === \"Parameter\") {\n // Direct parameter: (onClose) => ...\n return { isFromParameter: true, originType: \"direct-parameter\" };\n }\n\n // Check for destructured variable in body: const { onClose } = props\n // definition.type is \"Variable\" and definition.node is VariableDeclarator\n if (definition.type === \"Variable\") {\n const declarator = definition.node;\n\n // Check if the left side is an ObjectPattern (destructuring)\n if (declarator.id.type === AST_NODE_TYPES.ObjectPattern) {\n const init = declarator.init;\n\n // Check if destructured from an identifier that is a parameter\n if (init?.type === AST_NODE_TYPES.Identifier) {\n const initScope = context.sourceCode.getScope(init);\n const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;\n\n if (initVariable && isVariableAParameter(initVariable)) {\n return { isFromParameter: true, originType: \"destructured-in-body\" };\n }\n }\n }\n }\n\n // Check if it's a destructured parameter directly in function signature\n // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...\n if (definition.node.type === AST_NODE_TYPES.Property) {\n // Check direct parent - should be ObjectPattern for destructured props\n const objectPattern = definition.node.parent;\n if (objectPattern.type !== AST_NODE_TYPES.ObjectPattern) {\n continue;\n }\n\n // Check if this ObjectPattern is a function parameter\n const objectPatternParent = objectPattern.parent;\n\n if (\n objectPatternParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n // Check if the ObjectPattern is in the params\n const isParam = objectPatternParent.params.includes(objectPattern);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n\n // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...\n if (objectPatternParent.type === AST_NODE_TYPES.AssignmentPattern) {\n const assignmentParent = objectPatternParent.parent;\n\n if (\n assignmentParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n const isParam = assignmentParent.params.includes(objectPatternParent);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n }\n }\n }\n\n return { isFromParameter: false };\n};\n\n/**\n * Checks if an identifier originates from a function parameter.\n * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.\n *\n * Use this when you only need to know if an identifier comes from a parameter,\n * without needing to know how it was destructured.\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier originates from a function parameter\n * @see getIdentifierParameterOrigin for detailed origin information\n */\nexport const isIdentifierFromParameter = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => getIdentifierParameterOrigin(identifier, context).isFromParameter;\n\n/**\n * Checks if an identifier's parameter comes from a render prop callback.\n *\n * Render prop pattern: `{callback => <Component onClick={callback} />}`\n *\n * The function detects when:\n * 1. The identifier comes from a parameter\n * 2. That parameter's function is inside a JSXExpressionContainer\n * 3. Which is a child of a JSXElement (render prop pattern)\n *\n * This is used to distinguish between:\n * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged\n * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier comes from a render prop callback parameter\n * @example\n * // Render prop callback - returns true\n * <MoreMenu>\n * {close => <MenuItem onClick={close} />}\n * </MoreMenu>\n * // isIdentifierFromRenderPropCallback(close) => true\n * @example\n * // React component prop - returns false\n * const Modal = ({ onClose }) => <button onClick={onClose} />;\n * // isIdentifierFromRenderPropCallback(onClose) => false\n */\nexport const isIdentifierFromRenderPropCallback = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // First check if it even comes from a parameter\n if (!isIdentifierFromParameter(identifier, context)) {\n return false;\n }\n\n // Get the variable that this identifier resolves to\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return false;\n }\n\n // Check each definition of this variable\n for (const definition of variable.defs) {\n if (definition.type !== \"Parameter\") {\n continue;\n }\n\n // Find the function that contains this parameter by walking up from the definition node\n let functionNode:\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n | TSESTree.FunctionDeclaration\n | null = null;\n\n let current: TSESTree.Node | undefined = definition.node;\n do {\n if (\n current.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n functionNode = current;\n break;\n }\n current = current.parent;\n } while (current !== undefined);\n\n if (!functionNode) {\n continue;\n }\n\n // Check if the function is inside a JSXExpressionContainer (render prop pattern)\n // Pattern: <Component>{callback => ...}</Component>\n const parent = functionNode.parent;\n if (parent.type === AST_NODE_TYPES.JSXExpressionContainer) {\n // Verify the JSXExpressionContainer is a child of a JSXElement\n const jsxContainerParent = parent.parent;\n if (\n jsxContainerParent.type === AST_NODE_TYPES.JSXElement ||\n jsxContainerParent.type === AST_NODE_TYPES.JSXFragment\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"ast-utils.js","sourceRoot":"","sources":["../../../../../../../libs/eslint/plugin-trackunit/src/lib/utils/ast-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { ASTUtils, AST_NODE_TYPES, TSESLint, TSESTree } from \"@typescript-eslint/utils\";\n\n/**\n * Utility functions for analyzing AST nodes and function structure in ESLint rules.\n *\n * ## Core Utilities\n * - `isInParameterList()` - Check if a node is in a function's parameter list\n *\n * ## Parameter Analysis (Parameter → Usage)\n * - `isParameterExplicitlyDestructured()` - Check if parameter is explicitly destructured\n * - `isParameterInitialized()` - Check if parameter has a default value\n * - `isParameterUsedInFunction()` - Check if parameter is used in function body\n * - `getParameterRestUsage()` - Get info about parameter accessed via rest params\n * - `hasExistingBodyInitializations()` - Check for initialization patterns in function body\n *\n * ## Identifier Origin Analysis (Usage → Origin)\n * - `getIdentifierParameterOrigin()` - Trace identifier back to see if it's from a parameter (rich return)\n * - `isIdentifierFromParameter()` - Boolean helper to check if identifier is from a parameter\n * - `isIdentifierFromRenderPropCallback()` - Check if identifier is from a render prop callback parameter\n *\n * ## JSX/React Specific\n * - `isReactComponent()` - Check if function is likely a React component\n * - `functionReturnsJSX()` - Check if function body returns JSX\n * - `functionReturnsIntrinsicJSX()` - Check if function body returns intrinsic JSX tags (e.g. `div`, `span`)\n * - `isParameterOnlyUsedInJSX()` - Check if parameter is only used in JSX attributes\n */\n\n/**\n * Helper function to check if a node is in the parameter list\n */\nconst isInParameterList = (\n node: TSESTree.Node,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression\n): boolean => {\n let current = node.parent;\n while (current) {\n // Check if current node is one of the function parameters\n const isParam = functionNode.params.some(param => param === current);\n if (isParam) {\n return true;\n }\n current = current.parent;\n }\n return false;\n};\n\n/**\n * Check if a parameter is explicitly destructured in the parameter list\n * (vs. captured in rest parameters like ...restOptions)\n */\nexport const isParameterExplicitlyDestructured = (parameter: TSESTree.Parameter, paramName: string): boolean => {\n if (parameter.type !== AST_NODE_TYPES.ObjectPattern) {\n return false;\n }\n\n // Check if the parameter is explicitly listed in the destructuring\n return parameter.properties.some(property => {\n if (property.type === AST_NODE_TYPES.Property && property.key.type === AST_NODE_TYPES.Identifier) {\n return property.key.name === paramName;\n }\n return false;\n });\n};\n\n/**\n * Check if there are any existing parameter initializations in the function body\n */\nexport const hasExistingBodyInitializations = (functionBody: Array<TSESTree.Statement>): boolean => {\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern &&\n stmt.declarations[0].id.properties.some(\n prop => prop.type === AST_NODE_TYPES.Property && prop.value.type === AST_NODE_TYPES.AssignmentPattern\n )\n ) {\n return true;\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n return false;\n};\n\n/**\n * Check if a parameter is initialized in the function body or parameter defaults\n */\nexport const isParameterInitialized = (\n functionBody: Array<TSESTree.Statement>,\n paramName: string,\n parameter?: TSESTree.Parameter\n): boolean => {\n // First check if the parameter has a default value in the parameter destructuring\n if (parameter && parameter.type === AST_NODE_TYPES.ObjectPattern) {\n for (const property of parameter.properties) {\n if (property.type === AST_NODE_TYPES.Property && property.value.type === AST_NODE_TYPES.AssignmentPattern) {\n // Handle both identifier keys (paramName) and string literal keys (\"param-name\")\n const keyName =\n property.key.type === AST_NODE_TYPES.Identifier\n ? property.key.name\n : property.key.type === AST_NODE_TYPES.Literal && typeof property.key.value === \"string\"\n ? property.key.value\n : null;\n\n if (keyName === paramName) {\n return true; // Found default value in parameter: {paramName = defaultValue}\n }\n }\n }\n }\n\n // Then check for initialization patterns in the function body\n for (const stmt of functionBody) {\n // Check for destructuring with defaults: const { param = defaultValue } = params\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.ObjectPattern\n ) {\n const pattern = stmt.declarations[0].id;\n for (const property of pattern.properties) {\n if (\n property.type === AST_NODE_TYPES.Property &&\n property.key.type === AST_NODE_TYPES.Identifier &&\n property.key.name === paramName &&\n property.value.type === AST_NODE_TYPES.AssignmentPattern\n ) {\n return true;\n }\n }\n }\n\n // Check for variable declarations with defaults: const param = params.param ?? defaultValue\n if (\n stmt.type === AST_NODE_TYPES.VariableDeclaration &&\n stmt.declarations.length === 1 &&\n stmt.declarations[0].id.type === AST_NODE_TYPES.Identifier &&\n stmt.declarations[0].id.name === paramName &&\n stmt.declarations[0].init?.type === AST_NODE_TYPES.LogicalExpression &&\n (stmt.declarations[0].init.operator === \"??\" || stmt.declarations[0].init.operator === \"||\")\n ) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is used within the function body\n */\nexport const isParameterUsedInFunction = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for more robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (variable) {\n // Check if the variable has any references (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n // Exclude the parameter declaration itself\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n // Additional check: if the variable is only referenced in object literal shorthand property names\n // (like { placement: result.placement }), it's not actually using the parameter variable\n const actualUsageReferences = references.filter(ref => {\n const parent = ref.identifier.parent;\n\n // Skip if this is just a property key in an object literal\n // Example: { placement: result.placement } - the first 'placement' is just a key, not usage\n if (\n parent.type === AST_NODE_TYPES.Property &&\n parent.key === ref.identifier &&\n parent.value !== ref.identifier &&\n !parent.shorthand\n ) {\n return false;\n }\n\n return true;\n });\n\n if (actualUsageReferences.length > 0) {\n return true;\n }\n }\n\n // If direct variable reference not found, check for member access on rest parameters\n // e.g., rest.paramName, params.paramName, etc.\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n // Look for rest elements in both direct params and inside object patterns\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return false;\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return true;\n }\n }\n\n return false;\n};\n\n/**\n * Check if a parameter is accessed via rest parameters (e.g., rest.paramName)\n * and return information about the rest parameter usage\n */\nconst getParameterRestUsage = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): { isUsedViaRest: boolean; restParamName?: string; restParam?: TSESTree.Parameter } | null => {\n // Look for rest elements in both direct params and inside object patterns\n const restParameters: Array<{ name: string; param: TSESTree.Parameter }> = [];\n\n functionNode.params.forEach(param => {\n if (param.type === AST_NODE_TYPES.RestElement && param.argument.type === AST_NODE_TYPES.Identifier) {\n // Direct rest parameter: (...rest: Params)\n restParameters.push({ name: param.argument.name, param });\n } else if (param.type === AST_NODE_TYPES.ObjectPattern) {\n // Look for rest elements inside object patterns: ({ param1, ...rest }: Params)\n param.properties.forEach(property => {\n if (property.type === AST_NODE_TYPES.RestElement && property.argument.type === AST_NODE_TYPES.Identifier) {\n restParameters.push({ name: property.argument.name, param });\n }\n });\n }\n });\n\n if (restParameters.length === 0) {\n return { isUsedViaRest: false };\n }\n\n // Check if the function body contains rest.paramName patterns\n const functionText = context.sourceCode.getText(functionNode);\n\n for (const restParam of restParameters) {\n const pattern = new RegExp(`\\\\b${restParam.name}\\\\.${paramName}\\\\b`);\n if (pattern.test(functionText)) {\n return {\n isUsedViaRest: true,\n restParamName: restParam.name,\n restParam: restParam.param,\n };\n }\n }\n\n return { isUsedViaRest: false };\n};\n\ntype FunctionLikeNode = TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression;\n\nconst jsxTagNameIsIntrinsic = (name: TSESTree.JSXTagNameExpression): boolean =>\n name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/.test(name.name);\n\nconst nodeContainsJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return true;\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsJSX(node.consequent) || nodeContainsJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsJSX(node.left) || nodeContainsJSX(node.right);\n }\n\n return false;\n};\n\nconst nodeContainsIntrinsicJSX = (node: TSESTree.Node): boolean => {\n if (node.type === AST_NODE_TYPES.JSXElement) {\n if (jsxTagNameIsIntrinsic(node.openingElement.name)) {\n return true;\n }\n\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.JSXFragment) {\n return node.children.some(child => {\n if (child.type === AST_NODE_TYPES.JSXElement || child.type === AST_NODE_TYPES.JSXFragment) {\n return nodeContainsIntrinsicJSX(child);\n }\n\n if (\n child.type === AST_NODE_TYPES.JSXExpressionContainer &&\n child.expression.type !== AST_NODE_TYPES.JSXEmptyExpression\n ) {\n return nodeContainsIntrinsicJSX(child.expression);\n }\n\n return false;\n });\n }\n\n if (node.type === AST_NODE_TYPES.ConditionalExpression) {\n return nodeContainsIntrinsicJSX(node.consequent) || nodeContainsIntrinsicJSX(node.alternate);\n }\n\n if (node.type === AST_NODE_TYPES.LogicalExpression) {\n return nodeContainsIntrinsicJSX(node.left) || nodeContainsIntrinsicJSX(node.right);\n }\n\n return false;\n};\n\nexport const functionReturnsJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsJSX(statement.argument)\n );\n }\n\n return nodeContainsJSX(node.body);\n};\n\nexport const functionReturnsIntrinsicJSX = (node: FunctionLikeNode): boolean => {\n if (node.body.type === AST_NODE_TYPES.BlockStatement) {\n return node.body.body.some(\n statement =>\n statement.type === AST_NODE_TYPES.ReturnStatement &&\n statement.argument !== null &&\n nodeContainsIntrinsicJSX(statement.argument)\n );\n }\n\n return nodeContainsIntrinsicJSX(node.body);\n};\n\n/**\n * Check if a function is likely a React component based on naming and JSX usage\n */\nexport const isReactComponent = (node: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression): boolean => {\n // Check if function name starts with uppercase (React convention)\n const functionName = node.type === AST_NODE_TYPES.FunctionDeclaration ? node.id?.name : null;\n const startsWithUppercase = /^[A-Z]/;\n if (functionName && startsWithUppercase.test(functionName)) {\n return true;\n }\n\n return functionReturnsJSX(node);\n};\n\n/**\n * Check if a parameter is only used in JSX attributes (pass-through to child components)\n * and nowhere else in the function body\n */\nexport const isParameterOnlyUsedInJSX = (\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>,\n functionNode: TSESTree.FunctionDeclaration | TSESTree.ArrowFunctionExpression,\n paramName: string\n): boolean => {\n // Use TypeScript-ESLint's built-in findVariable utility for robust variable detection\n const scope = context.sourceCode.getScope(functionNode);\n const variable = ASTUtils.findVariable(scope, paramName);\n\n if (!variable) {\n return false;\n }\n\n // Get all references to the parameter (excluding the parameter definition)\n const references = variable.references.filter(ref => {\n const refNode = ref.identifier;\n return !isInParameterList(refNode, functionNode);\n });\n\n if (references.length === 0) {\n return false;\n }\n\n // Check if all references are only in JSX attribute expressions\n const allReferencesAreJSXAttributes = references.every(ref => {\n const identifier = ref.identifier;\n let current = identifier.parent;\n\n // Walk up the AST to find if this identifier is used in a JSX attribute\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, @typescript-eslint/strict-boolean-expressions\n while (current) {\n // Check if we're in a JSX attribute expression: <Component prop={value} />\n if (current.type === AST_NODE_TYPES.JSXExpressionContainer) {\n const jsxParent = current.parent;\n if (jsxParent.type === AST_NODE_TYPES.JSXAttribute) {\n return true;\n }\n }\n\n // Check if we're in a JSX spread attribute: <Component {...props} />\n if (current.type === AST_NODE_TYPES.JSXSpreadAttribute) {\n return true;\n }\n\n // Allow dependency arrays for React hooks (useEffect, useMemo, useCallback, etc.)\n // These are acceptable for pass-through props since they're tracking the JSX usage\n if (current.type === AST_NODE_TYPES.ArrayExpression) {\n const callParent = current.parent;\n if (\n callParent.type === AST_NODE_TYPES.CallExpression &&\n callParent.callee.type === AST_NODE_TYPES.Identifier &&\n (callParent.callee.name.startsWith(\"use\") ||\n callParent.callee.name === \"useMemo\" ||\n callParent.callee.name === \"useCallback\" ||\n callParent.callee.name === \"useEffect\")\n ) {\n return true; // Allow dependency array usage\n }\n }\n\n // Stop if we reach certain node types that indicate we're not in JSX context\n if (\n current.type === AST_NODE_TYPES.VariableDeclarator ||\n current.type === AST_NODE_TYPES.AssignmentExpression ||\n current.type === AST_NODE_TYPES.CallExpression ||\n current.type === AST_NODE_TYPES.LogicalExpression ||\n current.type === AST_NODE_TYPES.ConditionalExpression ||\n current.type === AST_NODE_TYPES.BinaryExpression\n ) {\n return false;\n }\n\n if (!current.parent) {\n break;\n }\n current = current.parent;\n }\n\n return false;\n });\n\n return allReferencesAreJSXAttributes;\n};\n\n// ============================================================\n// Identifier Origin Analysis (traces usage back to definition)\n// ============================================================\n\n/**\n * Result of tracing an identifier back to its origin.\n * Used to distinguish between different ways an identifier can come from a function parameter.\n */\nexport type ParameterOriginResult =\n | {\n isFromParameter: true;\n /**\n * How the identifier relates to the parameter:\n * - \"direct-parameter\": Direct parameter, e.g., `(onClose) => ...`\n * - \"destructured-in-signature\": Destructured in function signature, e.g., `({ onClose }) => ...`\n * - \"destructured-in-body\": Destructured in function body, e.g., `const { onClose } = props`\n */\n originType: \"direct-parameter\" | \"destructured-in-signature\" | \"destructured-in-body\";\n }\n | { isFromParameter: false };\n\n/**\n * Checks if a variable is a function parameter.\n */\nconst isVariableAParameter = (variable: { defs: ReadonlyArray<{ type: string }> }): boolean => {\n return variable.defs.some(def => def.type === \"Parameter\");\n};\n\n/**\n * Traces an identifier back to determine if it originates from a function parameter.\n * Returns detailed information about how the identifier relates to the parameter.\n *\n * This is used to distinguish between:\n * - Props passed through: `({ onClose }) => <button onClick={onClose} />` - destructured-in-signature\n * - Props destructured in body: `(props) => { const { onClose } = props; }` - destructured-in-body\n * - Direct parameter: `(onClose) => ...` - direct-parameter\n * - Internal functions: `const handleClose = () => {}; <button onClick={handleClose} />` - not from parameter\n * - Hook results: `const { mutate } = useMutation(); <button onClick={mutate} />` - not from parameter\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns ParameterOriginResult with isFromParameter and originType if applicable\n * @example\n * // Direct parameter\n * const MyComponent = (onClose) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"direct-parameter\" }\n * @example\n * // Destructured in signature\n * const MyComponent = ({ onClose }) => <button onClick={onClose} />;\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-signature\" }\n * @example\n * // Destructured in body\n * const MyComponent = (props) => {\n * const { onClose } = props;\n * return <button onClick={onClose} />;\n * };\n * // getIdentifierParameterOrigin(onClose) => { isFromParameter: true, originType: \"destructured-in-body\" }\n * @example\n * // Not from parameter (internal function)\n * const MyComponent = () => {\n * const handleClose = () => {};\n * return <button onClick={handleClose} />;\n * };\n * // getIdentifierParameterOrigin(handleClose) => { isFromParameter: false }\n */\nconst getIdentifierParameterOrigin = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): ParameterOriginResult => {\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return { isFromParameter: false };\n }\n\n // Check the variable's definitions\n for (const definition of variable.defs) {\n // Check if defined as a direct function parameter\n if (definition.type === \"Parameter\") {\n // Direct parameter: (onClose) => ...\n return { isFromParameter: true, originType: \"direct-parameter\" };\n }\n\n // Check for destructured variable in body: const { onClose } = props\n // definition.type is \"Variable\" and definition.node is VariableDeclarator\n if (definition.type === \"Variable\") {\n const declarator = definition.node;\n\n // Check if the left side is an ObjectPattern (destructuring)\n if (declarator.id.type === AST_NODE_TYPES.ObjectPattern) {\n const init = declarator.init;\n\n // Check if destructured from an identifier that is a parameter\n if (init?.type === AST_NODE_TYPES.Identifier) {\n const initScope = context.sourceCode.getScope(init);\n const initVariable = initScope.references.find(ref => ref.identifier === init)?.resolved;\n\n if (initVariable && isVariableAParameter(initVariable)) {\n return { isFromParameter: true, originType: \"destructured-in-body\" };\n }\n }\n }\n }\n\n // Check if it's a destructured parameter directly in function signature\n // Pattern: ({ onClose }) => ... or ({ onClose }: Props) => ...\n if (definition.node.type === AST_NODE_TYPES.Property) {\n // Check direct parent - should be ObjectPattern for destructured props\n const objectPattern = definition.node.parent;\n if (objectPattern.type !== AST_NODE_TYPES.ObjectPattern) {\n continue;\n }\n\n // Check if this ObjectPattern is a function parameter\n const objectPatternParent = objectPattern.parent;\n\n if (\n objectPatternParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionExpression ||\n objectPatternParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n // Check if the ObjectPattern is in the params\n const isParam = objectPatternParent.params.includes(objectPattern);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n\n // Also check for AssignmentPattern wrapper: ({ onClose = defaultFn }) => ...\n if (objectPatternParent.type === AST_NODE_TYPES.AssignmentPattern) {\n const assignmentParent = objectPatternParent.parent;\n\n if (\n assignmentParent.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionExpression ||\n assignmentParent.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n const isParam = assignmentParent.params.includes(objectPatternParent);\n if (isParam) {\n return { isFromParameter: true, originType: \"destructured-in-signature\" };\n }\n }\n }\n }\n }\n\n return { isFromParameter: false };\n};\n\n/**\n * Checks if an identifier originates from a function parameter.\n * This is a simplified boolean helper that wraps `getIdentifierParameterOrigin`.\n *\n * Use this when you only need to know if an identifier comes from a parameter,\n * without needing to know how it was destructured.\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier originates from a function parameter\n * @see getIdentifierParameterOrigin for detailed origin information\n */\nexport const isIdentifierFromParameter = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => getIdentifierParameterOrigin(identifier, context).isFromParameter;\n\n/**\n * Checks if an identifier's parameter comes from a render prop callback.\n *\n * Render prop pattern: `{callback => <Component onClick={callback} />}`\n *\n * The function detects when:\n * 1. The identifier comes from a parameter\n * 2. That parameter's function is inside a JSXExpressionContainer\n * 3. Which is a child of a JSXElement (render prop pattern)\n *\n * This is used to distinguish between:\n * - React component props: `const Modal = ({ onClose }) => ...` - should be flagged\n * - Render prop callbacks: `<MoreMenu>{close => <MenuItem onClick={close} />}</MoreMenu>` - should NOT be flagged\n *\n * @param identifier - The identifier node to check\n * @param context - The ESLint rule context\n * @returns true if the identifier comes from a render prop callback parameter\n * @example\n * // Render prop callback - returns true\n * <MoreMenu>\n * {close => <MenuItem onClick={close} />}\n * </MoreMenu>\n * // isIdentifierFromRenderPropCallback(close) => true\n * @example\n * // React component prop - returns false\n * const Modal = ({ onClose }) => <button onClick={onClose} />;\n * // isIdentifierFromRenderPropCallback(onClose) => false\n */\nexport const isIdentifierFromRenderPropCallback = (\n identifier: TSESTree.Identifier,\n context: TSESLint.RuleContext<string, ReadonlyArray<unknown>>\n): boolean => {\n // First check if it even comes from a parameter\n if (!isIdentifierFromParameter(identifier, context)) {\n return false;\n }\n\n // Get the variable that this identifier resolves to\n const scope = context.sourceCode.getScope(identifier);\n const variable = scope.references.find(ref => ref.identifier === identifier)?.resolved;\n\n if (!variable) {\n return false;\n }\n\n // Check each definition of this variable\n for (const definition of variable.defs) {\n if (definition.type !== \"Parameter\") {\n continue;\n }\n\n // Find the function that contains this parameter by walking up from the definition node\n let functionNode:\n | TSESTree.ArrowFunctionExpression\n | TSESTree.FunctionExpression\n | TSESTree.FunctionDeclaration\n | null = null;\n\n let current: TSESTree.Node | undefined = definition.node;\n do {\n if (\n current.type === AST_NODE_TYPES.ArrowFunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionExpression ||\n current.type === AST_NODE_TYPES.FunctionDeclaration\n ) {\n functionNode = current;\n break;\n }\n current = current.parent;\n } while (current !== undefined);\n\n if (!functionNode) {\n continue;\n }\n\n // Check if the function is inside a JSXExpressionContainer (render prop pattern)\n // Pattern: <Component>{callback => ...}</Component>\n const parent = functionNode.parent;\n if (parent.type === AST_NODE_TYPES.JSXExpressionContainer) {\n // Verify the JSXExpressionContainer is a child of a JSXElement\n const jsxContainerParent = parent.parent;\n if (\n jsxContainerParent.type === AST_NODE_TYPES.JSXElement ||\n jsxContainerParent.type === AST_NODE_TYPES.JSXFragment\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n"]}
|