eslint-plugin-no-excess-properties 0.0.8 → 0.0.9
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/dist/index.d.ts +1 -1
- package/dist/object-literal.d.ts +1 -1
- package/dist/object-literal.js +85 -46
- package/dist/object-literal.js.map +1 -1
- package/package.json +1 -1
- package/src/object-literal.test.ts +94 -22
- package/src/object-literal.ts +126 -54
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ declare const plugin: {
|
|
|
14
14
|
version: string;
|
|
15
15
|
};
|
|
16
16
|
rules: {
|
|
17
|
-
"object-literal": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noExcessProperties", [], import("./object-literal").PluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
17
|
+
"object-literal": import("@typescript-eslint/utils/ts-eslint").RuleModule<"noExcessProperties" | "noExcessProperty", [], import("./object-literal").PluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
20
|
export = plugin;
|
package/dist/object-literal.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export interface PluginDocs {
|
|
|
4
4
|
recommended?: boolean;
|
|
5
5
|
requiresTypeChecking?: boolean;
|
|
6
6
|
}
|
|
7
|
-
declare const noExcessProperties: ESLintUtils.RuleModule<"noExcessProperties", [], PluginDocs, ESLintUtils.RuleListener>;
|
|
7
|
+
declare const noExcessProperties: ESLintUtils.RuleModule<"noExcessProperties" | "noExcessProperty", [], PluginDocs, ESLintUtils.RuleListener>;
|
|
8
8
|
export default noExcessProperties;
|
package/dist/object-literal.js
CHANGED
|
@@ -44,57 +44,95 @@ function isObjectLiteral(type) {
|
|
|
44
44
|
return (type.symbol !== undefined &&
|
|
45
45
|
tsutils.isSymbolFlagSet(type.symbol, typescript_1.default.SymbolFlags.ObjectLiteral));
|
|
46
46
|
}
|
|
47
|
-
function
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
function isChildNode(node, parentNode) {
|
|
48
|
+
let parent = node;
|
|
49
|
+
do {
|
|
50
|
+
parent = parent.parent;
|
|
51
|
+
if (parent === parentNode) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
} while (parent);
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
function splitTypes(types) {
|
|
58
|
+
const result = {
|
|
59
|
+
advancedTypes: [[], []],
|
|
60
|
+
basicTypes: [],
|
|
61
|
+
};
|
|
62
|
+
for (const type of types) {
|
|
63
|
+
const callSignatures = type.getCallSignatures();
|
|
64
|
+
if (callSignatures.length === 1) {
|
|
65
|
+
result.advancedTypes[0].push(callSignatures[0].getReturnType());
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const arrayType = type.getNumberIndexType();
|
|
69
|
+
if (arrayType && type.symbol?.name === "Array") {
|
|
70
|
+
result.advancedTypes[1].push(arrayType);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
result.basicTypes.push(type);
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function report(properties, parentNode, context, services) {
|
|
78
|
+
const propertyNodes = properties.map((p) => p.valueDeclaration
|
|
79
|
+
? services.tsNodeToESTreeNodeMap.get(p.valueDeclaration)
|
|
80
|
+
: null);
|
|
81
|
+
if (propertyNodes.every((p) => p && isChildNode(p, parentNode))) {
|
|
82
|
+
for (let i = 0; i < properties.length; i++) {
|
|
83
|
+
context.report({
|
|
84
|
+
data: { excessPropertyName: properties[i].name },
|
|
85
|
+
messageId: "noExcessProperty",
|
|
86
|
+
node: propertyNodes[i] ?? parentNode,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
52
90
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
91
|
+
if (properties.length > 1) {
|
|
92
|
+
context.report({
|
|
93
|
+
data: { excessPropertyNames: properties.map((p) => p.name).join(", ") },
|
|
94
|
+
messageId: "noExcessProperties",
|
|
95
|
+
node: parentNode,
|
|
96
|
+
});
|
|
97
|
+
return;
|
|
57
98
|
}
|
|
58
|
-
|
|
99
|
+
context.report({
|
|
100
|
+
data: { excessPropertyName: properties[0].name },
|
|
101
|
+
messageId: "noExcessProperty",
|
|
102
|
+
node: parentNode,
|
|
103
|
+
});
|
|
59
104
|
}
|
|
60
|
-
function compareTypes(
|
|
61
|
-
const allLeftTypes = tsutils.unionConstituents(
|
|
62
|
-
const allRightTypes = tsutils.unionConstituents(
|
|
63
|
-
for (
|
|
64
|
-
|
|
65
|
-
|
|
105
|
+
function compareTypes(leftTypes, rightTypes, rightNode, context, services) {
|
|
106
|
+
const allLeftTypes = splitTypes(leftTypes.flatMap((t) => tsutils.unionConstituents(t)));
|
|
107
|
+
const allRightTypes = splitTypes(rightTypes.flatMap((t) => tsutils.unionConstituents(t)));
|
|
108
|
+
for (let i = 0; i < allLeftTypes.advancedTypes.length; i++) {
|
|
109
|
+
if (allLeftTypes.advancedTypes[i].length > 0 &&
|
|
110
|
+
allRightTypes.advancedTypes[i].length > 0) {
|
|
111
|
+
compareTypes(allLeftTypes.advancedTypes[i], allRightTypes.advancedTypes[i], rightNode, context, services);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const rightType of allRightTypes.basicTypes) {
|
|
115
|
+
if (!isObjectLiteral(rightType)) {
|
|
66
116
|
continue;
|
|
67
117
|
}
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
.getProperties()
|
|
76
|
-
.map((p) => p.name);
|
|
77
|
-
if (leftResolvedType.getStringIndexType() !== undefined ||
|
|
78
|
-
leftResolvedType.getNumberIndexType() !== undefined) {
|
|
79
|
-
bestMatchExcessPropertyNames = null;
|
|
118
|
+
const rightProperties = rightType.getProperties();
|
|
119
|
+
let bestMatchExcessProperties = null;
|
|
120
|
+
for (const leftType of allLeftTypes.basicTypes) {
|
|
121
|
+
const leftPropertyNames = leftType.getProperties().map((p) => p.name);
|
|
122
|
+
if (leftType.getStringIndexType() !== undefined ||
|
|
123
|
+
leftType.getNumberIndexType() !== undefined) {
|
|
124
|
+
bestMatchExcessProperties = null;
|
|
80
125
|
break;
|
|
81
126
|
}
|
|
82
|
-
const
|
|
127
|
+
const excessProperties = rightProperties.filter((p) => !leftPropertyNames.includes(p.name));
|
|
83
128
|
if (leftPropertyNames.length > 0 &&
|
|
84
|
-
(
|
|
85
|
-
|
|
86
|
-
|
|
129
|
+
(bestMatchExcessProperties === null ||
|
|
130
|
+
excessProperties.length < bestMatchExcessProperties.length)) {
|
|
131
|
+
bestMatchExcessProperties = excessProperties;
|
|
87
132
|
}
|
|
88
133
|
}
|
|
89
|
-
if (
|
|
90
|
-
|
|
91
|
-
context.report({
|
|
92
|
-
data: {
|
|
93
|
-
excessPropertyNames: bestMatchExcessPropertyNames.join(", "),
|
|
94
|
-
},
|
|
95
|
-
messageId: "noExcessProperties",
|
|
96
|
-
node: rightNode,
|
|
97
|
-
});
|
|
134
|
+
if (bestMatchExcessProperties && bestMatchExcessProperties.length > 0) {
|
|
135
|
+
report(bestMatchExcessProperties, rightNode, context, services);
|
|
98
136
|
}
|
|
99
137
|
}
|
|
100
138
|
}
|
|
@@ -106,7 +144,7 @@ const noExcessProperties = createRule({
|
|
|
106
144
|
AssignmentExpression(node) {
|
|
107
145
|
const leftType = services.getTypeAtLocation(node.left);
|
|
108
146
|
const rightType = services.getTypeAtLocation(node.right);
|
|
109
|
-
compareTypes(leftType, rightType, node.right, context);
|
|
147
|
+
compareTypes([leftType], [rightType], node.right, context, services);
|
|
110
148
|
},
|
|
111
149
|
CallExpression(node) {
|
|
112
150
|
if (node.arguments.length <= 0) {
|
|
@@ -130,7 +168,7 @@ const noExcessProperties = createRule({
|
|
|
130
168
|
paramType = arrayType;
|
|
131
169
|
}
|
|
132
170
|
}
|
|
133
|
-
compareTypes(paramType, argType, node.arguments[i], context);
|
|
171
|
+
compareTypes([paramType], [argType], node.arguments[i], context, services);
|
|
134
172
|
}
|
|
135
173
|
},
|
|
136
174
|
Property(node) {
|
|
@@ -143,7 +181,7 @@ const noExcessProperties = createRule({
|
|
|
143
181
|
if (!leftType) {
|
|
144
182
|
return;
|
|
145
183
|
}
|
|
146
|
-
compareTypes(leftType, rightType, node, context);
|
|
184
|
+
compareTypes([leftType], [rightType], node, context, services);
|
|
147
185
|
},
|
|
148
186
|
ReturnStatement(node) {
|
|
149
187
|
if (!node.argument) {
|
|
@@ -165,7 +203,7 @@ const noExcessProperties = createRule({
|
|
|
165
203
|
}
|
|
166
204
|
}
|
|
167
205
|
const argType = services.getTypeAtLocation(node.argument);
|
|
168
|
-
compareTypes(returnType, argType, node.argument, context);
|
|
206
|
+
compareTypes([returnType], [argType], node.argument, context, services);
|
|
169
207
|
},
|
|
170
208
|
VariableDeclarator(node) {
|
|
171
209
|
if (!node.id.typeAnnotation || !node.init) {
|
|
@@ -173,7 +211,7 @@ const noExcessProperties = createRule({
|
|
|
173
211
|
}
|
|
174
212
|
const leftType = services.getTypeAtLocation(node.id.typeAnnotation.typeAnnotation);
|
|
175
213
|
const rightType = services.getTypeAtLocation(node.init);
|
|
176
|
-
compareTypes(leftType, rightType, node.init, context);
|
|
214
|
+
compareTypes([leftType], [rightType], node.init, context, services);
|
|
177
215
|
},
|
|
178
216
|
};
|
|
179
217
|
},
|
|
@@ -185,6 +223,7 @@ const noExcessProperties = createRule({
|
|
|
185
223
|
requiresTypeChecking: true,
|
|
186
224
|
},
|
|
187
225
|
messages: {
|
|
226
|
+
noExcessProperty: "Excess property '{{ excessPropertyName }}' found",
|
|
188
227
|
noExcessProperties: "Excess properties '{{ excessPropertyNames }}' found",
|
|
189
228
|
},
|
|
190
229
|
schema: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-literal.js","sourceRoot":"","sources":["../src/object-literal.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"object-literal.js","sourceRoot":"","sources":["../src/object-literal.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "eslint-plugin-no-excess-properties",
|
|
3
3
|
"description": "Excess properties are not allowed on object literals",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.9",
|
|
6
6
|
"homepage": "https://bitbucket.org/unimorphic/eslint-plugin-no-excess-properties",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"eslint-plugin",
|
|
@@ -8,18 +8,19 @@ RuleTester.it = vitest.it;
|
|
|
8
8
|
RuleTester.itOnly = vitest.it.only;
|
|
9
9
|
RuleTester.describe = vitest.describe;
|
|
10
10
|
|
|
11
|
-
function createError(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
function createError(
|
|
12
|
+
props: Partial<TestCaseError<"noExcessProperties" | "noExcessProperty">> & {
|
|
13
|
+
line: number;
|
|
14
|
+
column: number;
|
|
15
|
+
endColumn: number;
|
|
16
|
+
isMulti?: boolean;
|
|
17
|
+
},
|
|
18
|
+
): TestCaseError<"noExcessProperties" | "noExcessProperty"> {
|
|
19
|
+
const { endLine, isMulti, ...otherProps } = props;
|
|
17
20
|
return {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
line: props.line,
|
|
22
|
-
messageId: "noExcessProperties",
|
|
21
|
+
...otherProps,
|
|
22
|
+
endLine: endLine ?? props.line,
|
|
23
|
+
messageId: isMulti ? "noExcessProperties" : "noExcessProperty",
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -87,7 +88,7 @@ ruleTester.run("object-literal", objectLiteral, {
|
|
|
87
88
|
code: `
|
|
88
89
|
const test: () => { prop1: number; } = () => ({ prop1: 1, prop2: 2 })
|
|
89
90
|
`,
|
|
90
|
-
errors: [createError({ column:
|
|
91
|
+
errors: [createError({ column: 67, endColumn: 75, line: 2 })],
|
|
91
92
|
},
|
|
92
93
|
{
|
|
93
94
|
code: `
|
|
@@ -127,21 +128,21 @@ ruleTester.run("object-literal", objectLiteral, {
|
|
|
127
128
|
function test(param1: { prop1: number }) {}
|
|
128
129
|
test({ prop1: 1, prop2: 2 });
|
|
129
130
|
`,
|
|
130
|
-
errors: [createError({ column:
|
|
131
|
+
errors: [createError({ column: 26, endColumn: 34, line: 3 })],
|
|
131
132
|
},
|
|
132
133
|
{
|
|
133
134
|
code: `
|
|
134
135
|
function test(param1: () => { prop1: number }) {}
|
|
135
136
|
test(() => ({ prop1: 1, prop2: 2 }));
|
|
136
137
|
`,
|
|
137
|
-
errors: [createError({ column:
|
|
138
|
+
errors: [createError({ column: 33, endColumn: 41, line: 3 })],
|
|
138
139
|
},
|
|
139
140
|
{
|
|
140
141
|
code: `
|
|
141
142
|
function test(param1: number, param2: { prop1: number } | null) {}
|
|
142
143
|
test(1, true ? { prop1: 1, prop2: 2 } : null);
|
|
143
144
|
`,
|
|
144
|
-
errors: [createError({ column:
|
|
145
|
+
errors: [createError({ column: 36, endColumn: 44, line: 3 })],
|
|
145
146
|
},
|
|
146
147
|
],
|
|
147
148
|
});
|
|
@@ -190,14 +191,14 @@ ruleTester.run("object-literal", objectLiteral, {
|
|
|
190
191
|
code: `
|
|
191
192
|
const test1: { prop1: 1 }[] = [{ prop1: 1 }].map(a => ({ ...a, prop2: 2 }))
|
|
192
193
|
`,
|
|
193
|
-
errors: [createError({ column:
|
|
194
|
+
errors: [createError({ column: 72, endColumn: 80, line: 2 })],
|
|
194
195
|
},
|
|
195
196
|
{
|
|
196
197
|
code: `
|
|
197
198
|
const test: { prop1: number; }[] = [];
|
|
198
199
|
test.push({ prop1: 1, prop: 2 })
|
|
199
200
|
`,
|
|
200
|
-
errors: [createError({ column:
|
|
201
|
+
errors: [createError({ column: 31, endColumn: 38, line: 3 })],
|
|
201
202
|
},
|
|
202
203
|
],
|
|
203
204
|
});
|
|
@@ -227,28 +228,28 @@ ruleTester.run("object-literal", objectLiteral, {
|
|
|
227
228
|
function test(param1: { prop1: number }[] | (() => void)) {}
|
|
228
229
|
test([{ prop1: 1, prop2: 2 }]);
|
|
229
230
|
`,
|
|
230
|
-
errors: [createError({ column:
|
|
231
|
+
errors: [createError({ column: 27, endColumn: 35, line: 3 })],
|
|
231
232
|
},
|
|
232
233
|
{
|
|
233
234
|
code: `
|
|
234
235
|
function test(param1: { prop1: number }[] | (() => { prop1: number })) {}
|
|
235
236
|
test(() => ({ prop1: 1, prop2: 2 }));
|
|
236
237
|
`,
|
|
237
|
-
errors: [createError({ column:
|
|
238
|
+
errors: [createError({ column: 33, endColumn: 41, line: 3 })],
|
|
238
239
|
},
|
|
239
240
|
{
|
|
240
241
|
code: `
|
|
241
242
|
function test(param1: { prop1: number } | { prop1: number, prop2: number }) {}
|
|
242
243
|
test({ prop1: 1, prop2: 2, prop3: 3 });
|
|
243
244
|
`,
|
|
244
|
-
errors: [createError({ column:
|
|
245
|
+
errors: [createError({ column: 36, endColumn: 44, line: 3 })],
|
|
245
246
|
},
|
|
246
247
|
{
|
|
247
248
|
code: `
|
|
248
249
|
function test(param1: { prop1: number } | { prop2: number }) {}
|
|
249
250
|
test({ prop1: 1, prop2: 2 });
|
|
250
251
|
`,
|
|
251
|
-
errors: [createError({ column:
|
|
252
|
+
errors: [createError({ column: 26, endColumn: 34, line: 3 })],
|
|
252
253
|
},
|
|
253
254
|
],
|
|
254
255
|
});
|
|
@@ -266,7 +267,78 @@ ruleTester.run("object-literal", objectLiteral, {
|
|
|
266
267
|
function test(param1: { prop1: number } & { prop2: number }) {}
|
|
267
268
|
test({ prop1: 1, prop2: 2, prop3: 3 });
|
|
268
269
|
`,
|
|
269
|
-
errors: [createError({ column:
|
|
270
|
+
errors: [createError({ column: 36, endColumn: 44, line: 3 })],
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
ruleTester.run("object-literal", objectLiteral, {
|
|
276
|
+
valid: [
|
|
277
|
+
`
|
|
278
|
+
function test(param1: ({ prop1: number } | { prop2: number })[]) {}
|
|
279
|
+
test([{ prop2: 2 }]);
|
|
280
|
+
`,
|
|
281
|
+
`
|
|
282
|
+
function test(param1: () => ({ prop1: number } | { prop2: number } | null)[]) {}
|
|
283
|
+
test(() => [true ? { prop2: 2 } : null]);
|
|
284
|
+
`,
|
|
285
|
+
],
|
|
286
|
+
invalid: [
|
|
287
|
+
{
|
|
288
|
+
code: `
|
|
289
|
+
function test(param1: ({ prop1: number } | { prop2: number })[]) {}
|
|
290
|
+
test([{ prop1: 1, prop2: 2 }]);
|
|
291
|
+
`,
|
|
292
|
+
errors: [createError({ column: 27, endColumn: 35, line: 3 })],
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
code: `
|
|
296
|
+
function test(param1: () => ({ prop1: number } | { prop2: number } | null)[]) {}
|
|
297
|
+
test(() => [true ? { prop1: 1, prop2: 2 } : null]);
|
|
298
|
+
`,
|
|
299
|
+
errors: [createError({ column: 40, endColumn: 48, line: 3 })],
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
ruleTester.run("object-literal", objectLiteral, {
|
|
305
|
+
valid: [],
|
|
306
|
+
invalid: [
|
|
307
|
+
{
|
|
308
|
+
code: `
|
|
309
|
+
function test(param1: { prop1: number }) {}
|
|
310
|
+
test({ prop1: 1, prop2: 2, prop3: 3 });
|
|
311
|
+
`,
|
|
312
|
+
errors: [
|
|
313
|
+
createError({
|
|
314
|
+
column: 26,
|
|
315
|
+
data: { excessPropertyName: "prop2" },
|
|
316
|
+
endColumn: 34,
|
|
317
|
+
line: 3,
|
|
318
|
+
}),
|
|
319
|
+
createError({
|
|
320
|
+
column: 36,
|
|
321
|
+
data: { excessPropertyName: "prop3" },
|
|
322
|
+
endColumn: 44,
|
|
323
|
+
line: 3,
|
|
324
|
+
}),
|
|
325
|
+
],
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
code: `
|
|
329
|
+
let test1: { prop1: number; } = { prop1: 1 };
|
|
330
|
+
const test2 = { prop1: 2, prop2: 3, prop3: 4 };
|
|
331
|
+
test1 = test2;
|
|
332
|
+
`,
|
|
333
|
+
errors: [
|
|
334
|
+
createError({
|
|
335
|
+
column: 17,
|
|
336
|
+
data: { excessPropertyNames: "prop2, prop3" },
|
|
337
|
+
endColumn: 22,
|
|
338
|
+
line: 4,
|
|
339
|
+
isMulti: true,
|
|
340
|
+
}),
|
|
341
|
+
],
|
|
270
342
|
},
|
|
271
343
|
],
|
|
272
344
|
});
|
package/src/object-literal.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ASTUtils,
|
|
3
|
+
ESLintUtils,
|
|
4
|
+
ParserServicesWithTypeInformation,
|
|
5
|
+
TSESTree,
|
|
6
|
+
} from "@typescript-eslint/utils";
|
|
2
7
|
import { RuleContext } from "@typescript-eslint/utils/ts-eslint";
|
|
3
8
|
import ts from "typescript";
|
|
4
9
|
import * as tsutils from "ts-api-utils";
|
|
@@ -24,84 +29,144 @@ function isObjectLiteral(type: ts.Type): boolean {
|
|
|
24
29
|
);
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
function
|
|
28
|
-
let
|
|
32
|
+
function isChildNode(node: TSESTree.Node, parentNode: TSESTree.Node) {
|
|
33
|
+
let parent: TSESTree.Node | undefined = node;
|
|
34
|
+
do {
|
|
35
|
+
parent = parent.parent;
|
|
36
|
+
if (parent === parentNode) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
} while (parent);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function splitTypes(types: ts.Type[]) {
|
|
44
|
+
const result = {
|
|
45
|
+
advancedTypes: [[], []] as ts.Type[][],
|
|
46
|
+
basicTypes: [] as ts.Type[],
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
for (const type of types) {
|
|
50
|
+
const callSignatures = type.getCallSignatures();
|
|
51
|
+
if (callSignatures.length === 1) {
|
|
52
|
+
result.advancedTypes[0].push(callSignatures[0].getReturnType());
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const arrayType = type.getNumberIndexType();
|
|
57
|
+
if (arrayType && (type as TypeOptionalSymbol).symbol?.name === "Array") {
|
|
58
|
+
result.advancedTypes[1].push(arrayType);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
result.basicTypes.push(type);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function report(
|
|
69
|
+
properties: ts.Symbol[],
|
|
70
|
+
parentNode: TSESTree.Node,
|
|
71
|
+
context: Readonly<RuleContext<"noExcessProperties" | "noExcessProperty", []>>,
|
|
72
|
+
services: ParserServicesWithTypeInformation,
|
|
73
|
+
) {
|
|
74
|
+
const propertyNodes = properties.map((p) =>
|
|
75
|
+
p.valueDeclaration
|
|
76
|
+
? services.tsNodeToESTreeNodeMap.get(p.valueDeclaration)
|
|
77
|
+
: null,
|
|
78
|
+
);
|
|
29
79
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
80
|
+
if (propertyNodes.every((p) => p && isChildNode(p, parentNode))) {
|
|
81
|
+
for (let i = 0; i < properties.length; i++) {
|
|
82
|
+
context.report({
|
|
83
|
+
data: { excessPropertyName: properties[i].name },
|
|
84
|
+
messageId: "noExcessProperty",
|
|
85
|
+
node: propertyNodes[i] ?? parentNode,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return;
|
|
33
89
|
}
|
|
34
90
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
91
|
+
if (properties.length > 1) {
|
|
92
|
+
context.report({
|
|
93
|
+
data: { excessPropertyNames: properties.map((p) => p.name).join(", ") },
|
|
94
|
+
messageId: "noExcessProperties",
|
|
95
|
+
node: parentNode,
|
|
96
|
+
});
|
|
97
|
+
return;
|
|
41
98
|
}
|
|
42
99
|
|
|
43
|
-
|
|
100
|
+
context.report({
|
|
101
|
+
data: { excessPropertyName: properties[0].name },
|
|
102
|
+
messageId: "noExcessProperty",
|
|
103
|
+
node: parentNode,
|
|
104
|
+
});
|
|
44
105
|
}
|
|
45
106
|
|
|
46
107
|
function compareTypes(
|
|
47
|
-
|
|
48
|
-
|
|
108
|
+
leftTypes: ts.Type[],
|
|
109
|
+
rightTypes: ts.Type[],
|
|
49
110
|
rightNode: TSESTree.Node,
|
|
50
|
-
context: Readonly<RuleContext<"noExcessProperties", []>>,
|
|
111
|
+
context: Readonly<RuleContext<"noExcessProperties" | "noExcessProperty", []>>,
|
|
112
|
+
services: ParserServicesWithTypeInformation,
|
|
51
113
|
): void {
|
|
52
|
-
const allLeftTypes =
|
|
53
|
-
|
|
114
|
+
const allLeftTypes = splitTypes(
|
|
115
|
+
leftTypes.flatMap((t) => tsutils.unionConstituents(t)),
|
|
116
|
+
);
|
|
117
|
+
const allRightTypes = splitTypes(
|
|
118
|
+
rightTypes.flatMap((t) => tsutils.unionConstituents(t)),
|
|
119
|
+
);
|
|
54
120
|
|
|
55
|
-
for (
|
|
56
|
-
|
|
121
|
+
for (let i = 0; i < allLeftTypes.advancedTypes.length; i++) {
|
|
122
|
+
if (
|
|
123
|
+
allLeftTypes.advancedTypes[i].length > 0 &&
|
|
124
|
+
allRightTypes.advancedTypes[i].length > 0
|
|
125
|
+
) {
|
|
126
|
+
compareTypes(
|
|
127
|
+
allLeftTypes.advancedTypes[i],
|
|
128
|
+
allRightTypes.advancedTypes[i],
|
|
129
|
+
rightNode,
|
|
130
|
+
context,
|
|
131
|
+
services,
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
57
135
|
|
|
58
|
-
|
|
136
|
+
for (const rightType of allRightTypes.basicTypes) {
|
|
137
|
+
if (!isObjectLiteral(rightType)) {
|
|
59
138
|
continue;
|
|
60
139
|
}
|
|
61
140
|
|
|
62
|
-
const
|
|
63
|
-
.getProperties()
|
|
64
|
-
.map((p) => p.name);
|
|
141
|
+
const rightProperties = rightType.getProperties();
|
|
65
142
|
|
|
66
|
-
let
|
|
67
|
-
for (const leftType of allLeftTypes) {
|
|
68
|
-
const
|
|
69
|
-
const leftPropertyNames = leftResolvedType
|
|
70
|
-
.getProperties()
|
|
71
|
-
.map((p) => p.name);
|
|
143
|
+
let bestMatchExcessProperties: ts.Symbol[] | null = null;
|
|
144
|
+
for (const leftType of allLeftTypes.basicTypes) {
|
|
145
|
+
const leftPropertyNames = leftType.getProperties().map((p) => p.name);
|
|
72
146
|
|
|
73
147
|
if (
|
|
74
|
-
|
|
75
|
-
|
|
148
|
+
leftType.getStringIndexType() !== undefined ||
|
|
149
|
+
leftType.getNumberIndexType() !== undefined
|
|
76
150
|
) {
|
|
77
|
-
|
|
151
|
+
bestMatchExcessProperties = null;
|
|
78
152
|
break;
|
|
79
153
|
}
|
|
80
154
|
|
|
81
|
-
const
|
|
82
|
-
(
|
|
155
|
+
const excessProperties = rightProperties.filter(
|
|
156
|
+
(p) => !leftPropertyNames.includes(p.name),
|
|
83
157
|
);
|
|
84
158
|
|
|
85
159
|
if (
|
|
86
160
|
leftPropertyNames.length > 0 &&
|
|
87
|
-
(
|
|
88
|
-
|
|
161
|
+
(bestMatchExcessProperties === null ||
|
|
162
|
+
excessProperties.length < bestMatchExcessProperties.length)
|
|
89
163
|
) {
|
|
90
|
-
|
|
164
|
+
bestMatchExcessProperties = excessProperties;
|
|
91
165
|
}
|
|
92
166
|
}
|
|
93
167
|
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
bestMatchExcessPropertyNames.length > 0
|
|
97
|
-
) {
|
|
98
|
-
context.report({
|
|
99
|
-
data: {
|
|
100
|
-
excessPropertyNames: bestMatchExcessPropertyNames.join(", "),
|
|
101
|
-
},
|
|
102
|
-
messageId: "noExcessProperties",
|
|
103
|
-
node: rightNode,
|
|
104
|
-
});
|
|
168
|
+
if (bestMatchExcessProperties && bestMatchExcessProperties.length > 0) {
|
|
169
|
+
report(bestMatchExcessProperties, rightNode, context, services);
|
|
105
170
|
}
|
|
106
171
|
}
|
|
107
172
|
}
|
|
@@ -116,7 +181,7 @@ const noExcessProperties = createRule({
|
|
|
116
181
|
const leftType = services.getTypeAtLocation(node.left);
|
|
117
182
|
const rightType = services.getTypeAtLocation(node.right);
|
|
118
183
|
|
|
119
|
-
compareTypes(leftType, rightType, node.right, context);
|
|
184
|
+
compareTypes([leftType], [rightType], node.right, context, services);
|
|
120
185
|
},
|
|
121
186
|
CallExpression(node) {
|
|
122
187
|
if (node.arguments.length <= 0) {
|
|
@@ -152,7 +217,13 @@ const noExcessProperties = createRule({
|
|
|
152
217
|
}
|
|
153
218
|
}
|
|
154
219
|
|
|
155
|
-
compareTypes(
|
|
220
|
+
compareTypes(
|
|
221
|
+
[paramType],
|
|
222
|
+
[argType],
|
|
223
|
+
node.arguments[i],
|
|
224
|
+
context,
|
|
225
|
+
services,
|
|
226
|
+
);
|
|
156
227
|
}
|
|
157
228
|
},
|
|
158
229
|
Property(node) {
|
|
@@ -169,7 +240,7 @@ const noExcessProperties = createRule({
|
|
|
169
240
|
return;
|
|
170
241
|
}
|
|
171
242
|
|
|
172
|
-
compareTypes(leftType, rightType, node, context);
|
|
243
|
+
compareTypes([leftType], [rightType], node, context, services);
|
|
173
244
|
},
|
|
174
245
|
ReturnStatement(node) {
|
|
175
246
|
if (!node.argument) {
|
|
@@ -200,7 +271,7 @@ const noExcessProperties = createRule({
|
|
|
200
271
|
|
|
201
272
|
const argType = services.getTypeAtLocation(node.argument);
|
|
202
273
|
|
|
203
|
-
compareTypes(returnType, argType, node.argument, context);
|
|
274
|
+
compareTypes([returnType], [argType], node.argument, context, services);
|
|
204
275
|
},
|
|
205
276
|
VariableDeclarator(node) {
|
|
206
277
|
if (!node.id.typeAnnotation || !node.init) {
|
|
@@ -212,7 +283,7 @@ const noExcessProperties = createRule({
|
|
|
212
283
|
);
|
|
213
284
|
const rightType = services.getTypeAtLocation(node.init);
|
|
214
285
|
|
|
215
|
-
compareTypes(leftType, rightType, node.init, context);
|
|
286
|
+
compareTypes([leftType], [rightType], node.init, context, services);
|
|
216
287
|
},
|
|
217
288
|
};
|
|
218
289
|
},
|
|
@@ -224,6 +295,7 @@ const noExcessProperties = createRule({
|
|
|
224
295
|
requiresTypeChecking: true,
|
|
225
296
|
},
|
|
226
297
|
messages: {
|
|
298
|
+
noExcessProperty: "Excess property '{{ excessPropertyName }}' found",
|
|
227
299
|
noExcessProperties: "Excess properties '{{ excessPropertyNames }}' found",
|
|
228
300
|
},
|
|
229
301
|
schema: [],
|