Skip to content

Commit b31bb92

Browse files
committed
✨ print extra properties on arrays as well
1 parent 6bbcc0d commit b31bb92

File tree

1 file changed

+110
-38
lines changed

1 file changed

+110
-38
lines changed

src/inspect/inspectors/inspectIterable.ts

Lines changed: 110 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { consoleText } from "../../core/consoleText";
1+
import { type ConsoleText, consoleText } from "../../core/consoleText";
22
import inspectAny from "./inspectAny";
33
import consoleStyles from "../utils/consoleStyles";
44
import {
55
ConsoleInspectContext,
66
ConsoleInspectOptions,
77
} from "../consoleInspect";
8-
import { consoleObject } from "../../core/consoleObject";
8+
import { type ConsoleObject, consoleObject } from "../../core/consoleObject";
99
import spansLength from "../../utils/spansLength";
1010
import indent from "../../utils/indent";
1111
import isPrimitive from "../../utils/isPrimitive";
@@ -35,9 +35,13 @@ export function inspectIterable(
3535

3636
// wrap is "auto", try to fit on one line
3737
const inspection = inspectIterableSingleLine(iterable, options, context);
38+
const array = iterableArray(iterable);
3839
if (
39-
iterableArray(iterable).every(isPrimitive) &&
40-
spansLength(inspection.spans) <= context.wrap
40+
spansLength(inspection.spans) <= context.wrap &&
41+
array.every(isPrimitive) &&
42+
iterableExtraKeys(iterable).every((key) =>
43+
isPrimitive(array[key as keyof typeof array]),
44+
)
4145
) {
4246
return inspection;
4347
}
@@ -52,6 +56,7 @@ export function inspectIterableSingleLine(
5256
): ConsoleInspection {
5357
const type = iterableType(iterable);
5458
const array = iterableArray(iterable);
59+
const extraKeys = iterableExtraKeys(iterable);
5560
return {
5661
type: "inline",
5762
spans: [
@@ -68,6 +73,20 @@ export function inspectIterableSingleLine(
6873
? inspection.spans
6974
: [consoleText(", "), ...inspection.spans];
7075
}),
76+
...extraKeys.flatMap((key, i) => {
77+
const value = array[key as keyof typeof array];
78+
const spans = [
79+
consoleText(key, consoleStyles[options.theme].dimmed),
80+
consoleText(": "),
81+
...inspectAny(value, options, {
82+
...context,
83+
depth: context.depth + 1,
84+
}).spans,
85+
];
86+
return i === 0 && array.length === 0
87+
? spans
88+
: [consoleText(", "), ...spans];
89+
}),
7190
consoleText(type === undefined ? "]" : "}"),
7291
consoleText(
7392
` ${type ?? ""}(${array.length})`,
@@ -85,33 +104,67 @@ export function inspectIterableMultiLine(
85104
const array = iterableArray(iterable);
86105
return {
87106
type: "block",
88-
spans: array.flatMap((value, i) => {
89-
const indexText = `[${i}]: `;
90-
const inspection =
91-
iterableType(iterable) === "Map"
92-
? inspectEntry(value, options, context)
93-
: inspectAny(value, options, {
94-
keys: context.keys,
95-
depth: context.depth + 1,
96-
wrap: Math.max(
97-
context.wrap -
98-
Math.max(indexText.length, options.indent),
99-
0,
100-
),
101-
});
102-
const valueSpans =
103-
inspection.type === "block"
104-
? [
105-
consoleText("\n"),
106-
...indent(inspection.spans, options.indent),
107-
]
108-
: inspection.spans;
109-
return [
110-
...(i === 0 ? [] : [consoleText("\n")]),
111-
consoleText(indexText, consoleStyles[options.theme].highlight),
112-
...valueSpans,
113-
];
114-
}),
107+
spans: [
108+
...array.flatMap((value, i) => {
109+
const indexText = `[${i}]: `;
110+
const inspection =
111+
iterableType(iterable) === "Map"
112+
? inspectEntry(value, options, context)
113+
: inspectAny(value, options, {
114+
keys: context.keys,
115+
depth: context.depth + 1,
116+
wrap: Math.max(
117+
context.wrap -
118+
Math.max(
119+
indexText.length,
120+
options.indent,
121+
),
122+
0,
123+
),
124+
});
125+
const valueSpans =
126+
inspection.type === "block"
127+
? [
128+
consoleText("\n"),
129+
...indent(inspection.spans, options.indent),
130+
]
131+
: inspection.spans;
132+
return [
133+
...(i === 0 ? [] : [consoleText("\n")]),
134+
consoleText(
135+
indexText,
136+
consoleStyles[options.theme].highlight,
137+
),
138+
...valueSpans,
139+
];
140+
}),
141+
...iterableExtraKeys(iterable).flatMap((key, i) => {
142+
const spans: (ConsoleText | ConsoleObject)[] = [];
143+
if (i !== 0 || array.length !== 0) {
144+
spans.push(consoleText("\n"));
145+
}
146+
147+
spans.push(consoleText(key, consoleStyles[options.theme].highlight));
148+
spans.push(consoleText(": "));
149+
150+
const value = array[key as keyof typeof array];
151+
const inspection = inspectAny(value, options, {
152+
keys: context.keys,
153+
depth: context.depth + 1,
154+
wrap: Math.max(
155+
context.wrap - Math.max(key.length + 2, options.indent),
156+
0,
157+
),
158+
});
159+
if (inspection.type === "block") {
160+
spans.push(consoleText("\n"));
161+
spans.push(...indent(inspection.spans, options.indent));
162+
} else {
163+
spans.push(...inspection.spans);
164+
}
165+
return spans
166+
})
167+
],
115168
};
116169
}
117170

@@ -145,20 +198,20 @@ function inspectEntry(
145198
};
146199
}
147200

148-
const weakMap = new WeakMap<Iterable<unknown>, unknown[]>();
201+
const iterableArrayCache = new WeakMap<Iterable<unknown>, unknown[]>();
149202
function iterableArray(iterable: Iterable<unknown>): unknown[] {
150203
if (Array.isArray(iterable)) {
151204
return iterable;
152205
}
153206

154-
const cached = weakMap.get(iterable);
155-
if (cached === undefined) {
156-
const array = [...iterable];
157-
weakMap.set(iterable, array);
158-
return array;
159-
} else {
207+
const cached = iterableArrayCache.get(iterable);
208+
if (cached !== undefined) {
160209
return cached;
161210
}
211+
212+
const array = [...iterable];
213+
iterableArrayCache.set(iterable, array);
214+
return array;
162215
}
163216

164217
function iterableType(iterable: Iterable<unknown>): "Set" | "Map" | undefined {
@@ -168,3 +221,22 @@ function iterableType(iterable: Iterable<unknown>): "Set" | "Map" | undefined {
168221
? "Map"
169222
: undefined;
170223
}
224+
225+
const iterableExtraKeysCache = new WeakMap<Iterable<unknown>, string[]>();
226+
function iterableExtraKeys(iterable: Iterable<unknown>): string[] {
227+
const cached = iterableExtraKeysCache.get(iterable);
228+
229+
if (cached !== undefined) {
230+
return cached;
231+
}
232+
233+
const keys: string[] = [];
234+
const array = iterableArray(iterable);
235+
for (const key of Object.keys(array)) {
236+
const index = Number.parseInt(key, 10);
237+
if (Number.isNaN(index) || index < 0 || index >= array.length) {
238+
keys.push(key);
239+
}
240+
}
241+
return keys;
242+
}

0 commit comments

Comments
 (0)