@alloy-js/core 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/src/binder.d.ts +18 -235
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +85 -386
- package/dist/src/components/Block.d.ts +1 -1
- package/dist/src/components/Block.d.ts.map +1 -1
- package/dist/src/components/Block.js +3 -1
- package/dist/src/components/Declaration.d.ts +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +5 -4
- package/dist/src/components/For.d.ts +1 -1
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +1 -1
- package/dist/src/components/Indent.d.ts +1 -1
- package/dist/src/components/Indent.d.ts.map +1 -1
- package/dist/src/components/List.d.ts +1 -1
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +2 -1
- package/dist/src/components/MemberDeclaration.d.ts +1 -1
- package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
- package/dist/src/components/MemberDeclaration.js +3 -4
- package/dist/src/components/MemberScope.d.ts +1 -1
- package/dist/src/components/MemberScope.d.ts.map +1 -1
- package/dist/src/components/MemberScope.js +0 -2
- package/dist/src/components/Prose.d.ts +1 -1
- package/dist/src/components/Prose.d.ts.map +1 -1
- package/dist/src/components/ReferenceOrContent.d.ts +1 -1
- package/dist/src/components/ReferenceOrContent.d.ts.map +1 -1
- package/dist/src/components/Scope.d.ts +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +3 -6
- package/dist/src/components/Show.d.ts +1 -1
- package/dist/src/components/Show.d.ts.map +1 -1
- package/dist/src/components/StatementList.d.ts +1 -1
- package/dist/src/components/StatementList.d.ts.map +1 -1
- package/dist/src/components/StatementList.js +1 -1
- package/dist/src/components/Switch.d.ts +1 -1
- package/dist/src/components/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch.js +1 -1
- package/dist/src/components/Wrap.d.ts +1 -1
- package/dist/src/components/Wrap.d.ts.map +1 -1
- package/dist/src/context/assignment.d.ts +1 -1
- package/dist/src/context/assignment.d.ts.map +1 -1
- package/dist/src/context/binder.d.ts +2 -2
- package/dist/src/context/binder.d.ts.map +1 -1
- package/dist/src/context/declaration.d.ts +1 -1
- package/dist/src/context/declaration.d.ts.map +1 -1
- package/dist/src/context/member-declaration.d.ts +1 -1
- package/dist/src/context/member-declaration.d.ts.map +1 -1
- package/dist/src/context/member-declaration.js +0 -1
- package/dist/src/context/member-scope.d.ts +1 -1
- package/dist/src/context/member-scope.d.ts.map +1 -1
- package/dist/src/context/name-policy.d.ts +1 -1
- package/dist/src/context/name-policy.d.ts.map +1 -1
- package/dist/src/context/scope.d.ts +1 -1
- package/dist/src/context/scope.d.ts.map +1 -1
- package/dist/src/context/source-directory.d.ts +1 -1
- package/dist/src/context/source-directory.d.ts.map +1 -1
- package/dist/src/context/source-file.d.ts +2 -2
- package/dist/src/context/source-file.d.ts.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -1
- package/dist/src/jsx-runtime.d.ts +12 -3
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +6 -2
- package/dist/src/reactive-union-set.d.ts +29 -0
- package/dist/src/reactive-union-set.d.ts.map +1 -0
- package/dist/src/reactive-union-set.js +183 -0
- package/dist/src/refkey.d.ts +36 -0
- package/dist/src/refkey.d.ts.map +1 -1
- package/dist/src/refkey.js +40 -0
- package/dist/src/scheduler.d.ts +2 -2
- package/dist/src/scheduler.d.ts.map +1 -1
- package/dist/src/scheduler.js +27 -6
- package/dist/src/slot.d.ts +1 -1
- package/dist/src/slot.d.ts.map +1 -1
- package/dist/src/stc.d.ts +1 -1
- package/dist/src/stc.d.ts.map +1 -1
- package/dist/src/sti.d.ts +1 -1
- package/dist/src/sti.d.ts.map +1 -1
- package/dist/src/sti.js +1 -1
- package/dist/src/symbols/index.d.ts +6 -0
- package/dist/src/symbols/index.d.ts.map +1 -0
- package/dist/src/symbols/index.js +5 -0
- package/dist/src/symbols/output-scope.d.ts +116 -0
- package/dist/src/symbols/output-scope.d.ts.map +1 -0
- package/dist/src/symbols/output-scope.js +246 -0
- package/dist/src/symbols/output-symbol.d.ts +134 -0
- package/dist/src/symbols/output-symbol.d.ts.map +1 -0
- package/dist/src/symbols/output-symbol.js +379 -0
- package/dist/src/symbols/symbol-flow.d.ts +13 -0
- package/dist/src/symbols/symbol-flow.d.ts.map +1 -0
- package/dist/src/symbols/symbol-flow.js +74 -0
- package/dist/src/symbols/symbol-slot.d.ts +12 -0
- package/dist/src/symbols/symbol-slot.d.ts.map +1 -0
- package/dist/src/symbols/symbol-slot.js +36 -0
- package/dist/src/symbols/symbol-table.d.ts +14 -0
- package/dist/src/symbols/symbol-table.d.ts.map +1 -0
- package/dist/src/symbols/symbol-table.js +42 -0
- package/dist/src/tap.d.ts +2 -1
- package/dist/src/tap.d.ts.map +1 -1
- package/dist/src/tracer.d.ts +181 -0
- package/dist/src/tracer.d.ts.map +1 -0
- package/dist/src/tracer.js +441 -0
- package/dist/src/tsdoc-metadata.json +1 -1
- package/dist/test/components/slot.test.js +5 -7
- package/dist/test/reactive-union-set.test.d.ts +2 -0
- package/dist/test/reactive-union-set.test.d.ts.map +1 -0
- package/dist/test/reactive-union-set.test.js +170 -0
- package/dist/test/symbols/output-scope.test.d.ts +2 -0
- package/dist/test/symbols/output-scope.test.d.ts.map +1 -0
- package/dist/test/symbols/output-scope.test.js +342 -0
- package/dist/test/symbols/output-symbol.test.d.ts +2 -0
- package/dist/test/symbols/output-symbol.test.d.ts.map +1 -0
- package/dist/test/symbols/output-symbol.test.js +446 -0
- package/dist/test/symbols/resolution.test.d.ts +2 -0
- package/dist/test/symbols/resolution.test.d.ts.map +1 -0
- package/dist/test/symbols/resolution.test.js +140 -0
- package/dist/test/symbols/utils.d.ts +24 -0
- package/dist/test/symbols/utils.d.ts.map +1 -0
- package/dist/test/symbols/utils.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/binder.ts +148 -672
- package/src/components/Block.tsx +4 -1
- package/src/components/Declaration.tsx +6 -6
- package/src/components/For.tsx +1 -1
- package/src/components/Indent.tsx +1 -1
- package/src/components/List.tsx +1 -1
- package/src/components/MemberDeclaration.tsx +4 -4
- package/src/components/MemberScope.tsx +2 -5
- package/src/components/Prose.tsx +1 -1
- package/src/components/ReferenceOrContent.tsx +1 -1
- package/src/components/Scope.tsx +2 -6
- package/src/components/Show.tsx +1 -1
- package/src/components/StatementList.tsx +2 -1
- package/src/components/Switch.tsx +1 -1
- package/src/components/Wrap.tsx +1 -1
- package/src/context/assignment.ts +1 -1
- package/src/context/binder.ts +2 -2
- package/src/context/declaration.ts +1 -1
- package/src/context/member-declaration.ts +1 -1
- package/src/context/member-scope.ts +1 -1
- package/src/context/name-policy.ts +1 -1
- package/src/context/scope.ts +1 -1
- package/src/context/source-directory.ts +1 -1
- package/src/context/source-file.ts +2 -2
- package/src/index.ts +11 -0
- package/src/jsx-runtime.ts +18 -2
- package/src/reactive-union-set.ts +238 -0
- package/src/refkey.ts +40 -0
- package/src/scheduler.ts +31 -6
- package/src/slot.ts +1 -1
- package/src/stc.ts +3 -3
- package/src/sti.ts +5 -5
- package/src/symbols/index.ts +5 -0
- package/src/symbols/output-scope.ts +323 -0
- package/src/symbols/output-symbol.ts +512 -0
- package/src/symbols/symbol-flow.ts +104 -0
- package/src/symbols/symbol-slot.tsx +47 -0
- package/src/symbols/symbol-table.ts +72 -0
- package/src/tap.ts +2 -1
- package/src/tracer.ts +440 -0
- package/temp/api.json +4172 -1582
- package/test/components/slot.test.tsx +8 -11
- package/test/reactive-union-set.test.tsx +191 -0
- package/test/symbols/output-scope.test.ts +302 -0
- package/test/symbols/output-symbol.test.ts +459 -0
- package/test/symbols/resolution.test.ts +172 -0
- package/test/symbols/utils.ts +95 -0
- package/dist/test/symbols.test.d.ts +0 -2
- package/dist/test/symbols.test.d.ts.map +0 -1
- package/dist/test/symbols.test.js +0 -884
- package/test/symbols.test.ts +0 -1006
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { NameConflictResolver } from "../binder.js";
|
|
2
|
+
import { ReactiveUnionSet } from "../reactive-union-set.js";
|
|
3
|
+
import { queueJob } from "../scheduler.js";
|
|
4
|
+
import {
|
|
5
|
+
formatScopeName,
|
|
6
|
+
formatSymbolName,
|
|
7
|
+
trace,
|
|
8
|
+
TracePhase,
|
|
9
|
+
} from "../tracer.js";
|
|
10
|
+
import { OutputScope } from "./output-scope.js";
|
|
11
|
+
import { OutputSymbol } from "./output-symbol.js";
|
|
12
|
+
|
|
13
|
+
export class SymbolTable extends ReactiveUnionSet<OutputSymbol> {
|
|
14
|
+
private _namesToDeconflict: Set<string> = new Set();
|
|
15
|
+
private _nameConflictResolver?: NameConflictResolver;
|
|
16
|
+
private _deconflictNames = () => {
|
|
17
|
+
for (const name of this._namesToDeconflict) {
|
|
18
|
+
const conflictedSymbols = [...this].filter(
|
|
19
|
+
(sym) => sym.originalName === name,
|
|
20
|
+
);
|
|
21
|
+
if (this._nameConflictResolver) {
|
|
22
|
+
this._nameConflictResolver(name, conflictedSymbols);
|
|
23
|
+
} else {
|
|
24
|
+
defaultConflictHandler(name, conflictedSymbols);
|
|
25
|
+
}
|
|
26
|
+
this._namesToDeconflict.delete(name);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
public scope;
|
|
30
|
+
constructor(
|
|
31
|
+
scope: OutputScope,
|
|
32
|
+
options: {
|
|
33
|
+
nameConflictResolver?: NameConflictResolver;
|
|
34
|
+
} = {},
|
|
35
|
+
) {
|
|
36
|
+
super({
|
|
37
|
+
onAdd: (symbol) => {
|
|
38
|
+
trace(
|
|
39
|
+
TracePhase.symbol.addToScope,
|
|
40
|
+
() => `${formatSymbolName(symbol)} -> ${formatScopeName(scope)}`,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
this._namesToDeconflict.add(symbol.name);
|
|
44
|
+
|
|
45
|
+
queueJob(this._deconflictNames);
|
|
46
|
+
|
|
47
|
+
return symbol;
|
|
48
|
+
},
|
|
49
|
+
onDelete(symbol) {
|
|
50
|
+
trace(
|
|
51
|
+
TracePhase.symbol.removeFromScope,
|
|
52
|
+
() => `${formatSymbolName(symbol)} -> ${formatScopeName(scope)}`,
|
|
53
|
+
);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
this.scope = scope;
|
|
58
|
+
|
|
59
|
+
this._nameConflictResolver = options.nameConflictResolver;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Default conflict handler. This will rename all but the first symbol
|
|
65
|
+
* to have a suffix of _2, _3, etc.
|
|
66
|
+
*/
|
|
67
|
+
function defaultConflictHandler(_: string, conflictedSymbols: OutputSymbol[]) {
|
|
68
|
+
for (let i = 1; i < conflictedSymbols.length; i++) {
|
|
69
|
+
conflictedSymbols[i].name =
|
|
70
|
+
conflictedSymbols[i].originalName + "_" + (i + 1);
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/tap.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ShallowRef, shallowRef } from "@vue/reactivity";
|
|
2
|
-
import { OutputScope, OutputSymbol } from "./binder.js";
|
|
3
2
|
import { useContext } from "./context.js";
|
|
4
3
|
import { DeclarationContext } from "./context/declaration.js";
|
|
5
4
|
import { MemberDeclarationContext } from "./context/member-declaration.js";
|
|
6
5
|
import { useScope } from "./context/scope.js";
|
|
7
6
|
import { SourceFileContext } from "./context/source-file.js";
|
|
8
7
|
import { ComponentDefinition } from "./jsx-runtime.js";
|
|
8
|
+
import { OutputScope } from "./symbols/output-scope.js";
|
|
9
|
+
import { OutputSymbol } from "./symbols/output-symbol.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The return value of {@link createTap}, this holds a reference to the tapped
|
package/src/tracer.ts
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { untrack } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { effect, ReactiveEffectRunner } from "@vue/reactivity";
|
|
3
|
+
import type { Refkey } from "./refkey.js";
|
|
4
|
+
import { scheduler } from "./scheduler.js";
|
|
5
|
+
import { OutputScope, OutputScopeFlags } from "./symbols/output-scope.js";
|
|
6
|
+
import { OutputSymbol, OutputSymbolFlags } from "./symbols/output-symbol.js";
|
|
7
|
+
|
|
8
|
+
// enable tracing for specific phases using a comma separated list of
|
|
9
|
+
// dotted identifiers, e.g. `scope.update,symbol.create`.
|
|
10
|
+
const traceEnv = process.env.ALLOY_TRACE ?? "";
|
|
11
|
+
const tracePhases = new Set<string>(
|
|
12
|
+
traceEnv === "" ? [] : traceEnv.split(",").map((t) => t.trim()),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
if (tracePhases.size > 0) {
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
console.log(
|
|
18
|
+
"Tracing enabled for phases:",
|
|
19
|
+
Array.from(tracePhases).join(", "),
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const debuggerIdsEnv = process.env.ALLOY_BREAK_ON_DID ?? "";
|
|
24
|
+
const dids = new Set<number>();
|
|
25
|
+
|
|
26
|
+
debuggerIdsEnv.split(",").forEach((id) => {
|
|
27
|
+
const num = parseInt(id, 10);
|
|
28
|
+
if (!isNaN(num)) {
|
|
29
|
+
dids.add(num);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
export const TracePhase = {
|
|
33
|
+
render: {},
|
|
34
|
+
scope: {
|
|
35
|
+
update: {
|
|
36
|
+
area: "scope",
|
|
37
|
+
subarea: "update",
|
|
38
|
+
bg: { r: 0, g: 255, b: 100 },
|
|
39
|
+
},
|
|
40
|
+
create: {
|
|
41
|
+
area: "scope",
|
|
42
|
+
subarea: "create",
|
|
43
|
+
bg: { r: 0, g: 150, b: 100 },
|
|
44
|
+
},
|
|
45
|
+
copySymbols: {
|
|
46
|
+
area: "scope",
|
|
47
|
+
subarea: "copySymbols",
|
|
48
|
+
bg: { r: 0, g: 100, b: 100 },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
symbol: {
|
|
52
|
+
update: {
|
|
53
|
+
area: "symbol",
|
|
54
|
+
subarea: "update",
|
|
55
|
+
bg: { r: 0, g: 0, b: 255 },
|
|
56
|
+
},
|
|
57
|
+
resolve: {
|
|
58
|
+
area: "symbol",
|
|
59
|
+
subarea: "resolve",
|
|
60
|
+
bg: { r: 0, g: 0, b: 200 },
|
|
61
|
+
},
|
|
62
|
+
create: {
|
|
63
|
+
area: "symbol",
|
|
64
|
+
subarea: "create",
|
|
65
|
+
bg: { r: 0, g: 0, b: 150 },
|
|
66
|
+
},
|
|
67
|
+
flow: {
|
|
68
|
+
area: "symbol",
|
|
69
|
+
subarea: "flow",
|
|
70
|
+
bg: { r: 0, g: 0, b: 100 },
|
|
71
|
+
},
|
|
72
|
+
addToScope: {
|
|
73
|
+
area: "symbol",
|
|
74
|
+
subarea: "addToScope",
|
|
75
|
+
bg: { r: 0, g: 0, b: 50 },
|
|
76
|
+
},
|
|
77
|
+
instantiate: {
|
|
78
|
+
area: "symbol",
|
|
79
|
+
subarea: "instantiate",
|
|
80
|
+
bg: { r: 0, g: 0, b: 25 },
|
|
81
|
+
},
|
|
82
|
+
clone: {
|
|
83
|
+
area: "symbol",
|
|
84
|
+
subarea: "clone",
|
|
85
|
+
bg: { r: 0, g: 0, b: 25 },
|
|
86
|
+
},
|
|
87
|
+
delete: {
|
|
88
|
+
area: "symbol",
|
|
89
|
+
subarea: "delete",
|
|
90
|
+
bg: { r: 100, g: 0, b: 100 },
|
|
91
|
+
},
|
|
92
|
+
removeFromScope: {
|
|
93
|
+
area: "symbol",
|
|
94
|
+
subarea: "removeFromScope",
|
|
95
|
+
bg: { r: 50, g: 0, b: 50 },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
resolve: {
|
|
99
|
+
success: {
|
|
100
|
+
area: "resolve",
|
|
101
|
+
subarea: "success",
|
|
102
|
+
bg: { r: 0, g: 255, b: 0 },
|
|
103
|
+
},
|
|
104
|
+
pending: {
|
|
105
|
+
area: "resolve",
|
|
106
|
+
subarea: "pending",
|
|
107
|
+
bg: { r: 255, g: 255, b: 0 },
|
|
108
|
+
},
|
|
109
|
+
failure: {
|
|
110
|
+
area: "resolve",
|
|
111
|
+
subarea: "failure",
|
|
112
|
+
bg: { r: 100, g: 50, b: 50 },
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
} as const;
|
|
116
|
+
|
|
117
|
+
interface TracePhase extends TextFormat {
|
|
118
|
+
area: string;
|
|
119
|
+
subarea: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let triggerCount = 0;
|
|
123
|
+
|
|
124
|
+
function shouldTrace(phase: TracePhase) {
|
|
125
|
+
return (
|
|
126
|
+
tracePhases.has(phase.area) ||
|
|
127
|
+
tracePhases.has(phase.area + "." + phase.subarea)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
export function trace(
|
|
131
|
+
phase: TracePhase,
|
|
132
|
+
cb: () => string,
|
|
133
|
+
triggerIds: Set<number> = new Set(),
|
|
134
|
+
) {
|
|
135
|
+
if (!shouldTrace(phase)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (triggerIds.size === 0) {
|
|
139
|
+
// not an effect trace.
|
|
140
|
+
const id = triggerCount++;
|
|
141
|
+
triggerIds.add(id);
|
|
142
|
+
|
|
143
|
+
if (dids.has(id)) {
|
|
144
|
+
// eslint-disable-next-line no-debugger
|
|
145
|
+
debugger;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const areaTag = ` ${phase.area + ":" + phase.subarea} `;
|
|
150
|
+
// eslint-disable-next-line no-console
|
|
151
|
+
console.log(
|
|
152
|
+
colorText(areaTag, { ...phase, bold: true }) +
|
|
153
|
+
" " +
|
|
154
|
+
colorText("[" + [...triggerIds].join(",") + "]", {
|
|
155
|
+
fg: { r: 50, g: 50, b: 50 },
|
|
156
|
+
}) +
|
|
157
|
+
" " +
|
|
158
|
+
cb() +
|
|
159
|
+
"\n",
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function traceEffect(phase: TracePhase, cb: () => string) {
|
|
164
|
+
if (!shouldTrace(phase)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
let first = true;
|
|
168
|
+
const triggerIds = new Set<number>();
|
|
169
|
+
|
|
170
|
+
const runner: ReactiveEffectRunner<void> = effect(
|
|
171
|
+
() => {
|
|
172
|
+
if (first) {
|
|
173
|
+
// just track what we need, don't log.
|
|
174
|
+
cb();
|
|
175
|
+
first = false;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
trace(phase, cb, triggerIds);
|
|
179
|
+
triggerIds.clear();
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
scheduler: scheduler(() => runner, true),
|
|
183
|
+
onTrigger(event) {
|
|
184
|
+
const id = triggerCount++;
|
|
185
|
+
if (dids.has(id)) {
|
|
186
|
+
// eslint-disable-next-line no-debugger
|
|
187
|
+
debugger;
|
|
188
|
+
}
|
|
189
|
+
triggerIds.add(id);
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
interface Color {
|
|
196
|
+
r: number;
|
|
197
|
+
g: number;
|
|
198
|
+
b: number;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Descriptor for how to format the text */
|
|
202
|
+
interface TextFormat {
|
|
203
|
+
fg?: Color; // optional foreground color
|
|
204
|
+
bg?: Color; // optional background color
|
|
205
|
+
bold?: boolean; // optional bold flag
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Wraps `text` in ANSI escape codes according to the given format.
|
|
210
|
+
*
|
|
211
|
+
* @param text The string to format.
|
|
212
|
+
* @param fmt Optional formatting descriptor.
|
|
213
|
+
* @returns The text wrapped in ANSI codes (or unmodified if no styles given).
|
|
214
|
+
*/
|
|
215
|
+
function colorText(text: string, fmt?: TextFormat): string {
|
|
216
|
+
if (!fmt) return text;
|
|
217
|
+
|
|
218
|
+
const codes: string[] = [];
|
|
219
|
+
|
|
220
|
+
if (fmt.bold) {
|
|
221
|
+
codes.push("1"); // ANSI code for bold
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (fmt.fg) {
|
|
225
|
+
const { r, g, b } = fmt.fg;
|
|
226
|
+
codes.push(`38;2;${r};${g};${b}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (fmt.bg) {
|
|
230
|
+
const { r, g, b } = fmt.bg;
|
|
231
|
+
codes.push(`48;2;${r};${g};${b}`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (codes.length === 0) {
|
|
235
|
+
return text;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const prefix = `\x1b[${codes.join(";")}m`;
|
|
239
|
+
const reset = `\x1b[0m`;
|
|
240
|
+
return `${prefix}${text}${reset}`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Format flag values in a concise way, showing only the flags that are set
|
|
245
|
+
* @param flags The numeric flags value to format
|
|
246
|
+
* @param flagEnum The enum containing flag definitions
|
|
247
|
+
* @returns An array of flag names that are set
|
|
248
|
+
*/
|
|
249
|
+
function formatFlags<T extends Record<string, string | number>>(
|
|
250
|
+
flags: number,
|
|
251
|
+
flagEnum: T,
|
|
252
|
+
): string[] {
|
|
253
|
+
return Object.entries(flagEnum)
|
|
254
|
+
.filter(
|
|
255
|
+
([name, value]) =>
|
|
256
|
+
typeof value === "number" && value !== 0 && (flags & value) === value,
|
|
257
|
+
)
|
|
258
|
+
.map(([name]) => name);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Format a symbol name with its ID in a blue-green color
|
|
263
|
+
* @param symbol The symbol to format
|
|
264
|
+
* @returns A formatted string representation of the symbol name with ID
|
|
265
|
+
*/
|
|
266
|
+
export function formatSymbolName(symbol: OutputSymbol): string {
|
|
267
|
+
return colorText(`Symbol ${symbol.name}[${symbol.id}]`, {
|
|
268
|
+
fg: {
|
|
269
|
+
r: 0,
|
|
270
|
+
b: 150,
|
|
271
|
+
g: 100,
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Format the symbols in a member scope, showing their names and IDs
|
|
278
|
+
* @param scope The member scope containing the symbols to format
|
|
279
|
+
* @returns A formatted string representation of the member scope symbols
|
|
280
|
+
*/
|
|
281
|
+
function formatMemberScopeSymbols(scope: OutputScope): string {
|
|
282
|
+
if (!scope || scope.symbols.size === 0) {
|
|
283
|
+
return "none";
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return Array.from(scope.symbols)
|
|
287
|
+
.map((symbol) => formatSymbolName(symbol))
|
|
288
|
+
.join(", ");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function formatSymbol(symbol: OutputSymbol): string {
|
|
292
|
+
// Base display with name and ID
|
|
293
|
+
let result = formatSymbolName(symbol);
|
|
294
|
+
|
|
295
|
+
// Add details on subsequent lines
|
|
296
|
+
const details: string[] = [];
|
|
297
|
+
|
|
298
|
+
if (!symbol.binder) {
|
|
299
|
+
details.push(colorText(" !UNBOUND", { fg: { r: 255, g: 0, b: 0 } }));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Show only enabled flags
|
|
303
|
+
const flagsInfo = formatFlags(symbol.flags, OutputSymbolFlags);
|
|
304
|
+
|
|
305
|
+
if (flagsInfo.length > 0) {
|
|
306
|
+
details.push(` flags: ${flagsInfo.join(", ")}`);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Show scope info with formatted name
|
|
310
|
+
if (symbol.scope) {
|
|
311
|
+
details.push(untrack(() => ` scope: ${formatScopeName(symbol.scope)}`));
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Show member scopes if present
|
|
315
|
+
if (symbol.instanceMemberScope) {
|
|
316
|
+
untrack(() => {
|
|
317
|
+
const memberCount = symbol.instanceMemberScope!.symbols.size;
|
|
318
|
+
details.push(
|
|
319
|
+
` instance members: ${memberCount} - ${formatMemberScopeSymbols(symbol.instanceMemberScope!)}`,
|
|
320
|
+
);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (symbol.staticMemberScope) {
|
|
325
|
+
untrack(() => {
|
|
326
|
+
const memberCount = symbol.staticMemberScope!.symbols.size;
|
|
327
|
+
details.push(
|
|
328
|
+
` static members: ${memberCount} - ${formatMemberScopeSymbols(symbol.staticMemberScope!)}`,
|
|
329
|
+
);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Show all refkeys with proper formatting
|
|
334
|
+
if (symbol.refkeys && symbol.refkeys.length > 0) {
|
|
335
|
+
details.push(` refkeys: ${formatRefkeys(symbol.refkeys)}`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (details.length > 0) {
|
|
339
|
+
result += "\n" + details.join("\n");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return result;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export function formatScopeName(scope: OutputScope): string {
|
|
346
|
+
let text = colorText(`${scope.name}[${scope.id}]`, {
|
|
347
|
+
fg: {
|
|
348
|
+
r: 0,
|
|
349
|
+
g: 150,
|
|
350
|
+
b: 50,
|
|
351
|
+
},
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
if (scope.owner) {
|
|
355
|
+
text += untrack(() => ` of ${formatSymbolName(scope.owner!)}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return text;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Format an OutputScope for display, showing information in a concise format
|
|
363
|
+
* @param scope The scope to format
|
|
364
|
+
* @returns A formatted string representation of the scope
|
|
365
|
+
*/
|
|
366
|
+
export function formatScope(scope: OutputSymbol["scope"]): string {
|
|
367
|
+
if (!scope) {
|
|
368
|
+
return "!Undefined scope!";
|
|
369
|
+
}
|
|
370
|
+
// Base display with name
|
|
371
|
+
let result = colorText(`Scope ${formatScopeName(scope)}`, {
|
|
372
|
+
fg: {
|
|
373
|
+
r: 0,
|
|
374
|
+
b: 200,
|
|
375
|
+
g: 100,
|
|
376
|
+
},
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Add details on subsequent lines
|
|
380
|
+
const details: string[] = [];
|
|
381
|
+
|
|
382
|
+
if (!scope.binder) {
|
|
383
|
+
details.push(colorText(" !UNBOUND", { fg: { r: 255, g: 0, b: 0 } }));
|
|
384
|
+
}
|
|
385
|
+
// Show only enabled flags
|
|
386
|
+
const flagsInfo = formatFlags(scope.flags, OutputScopeFlags);
|
|
387
|
+
|
|
388
|
+
if (flagsInfo.length > 0) {
|
|
389
|
+
details.push(` flags: ${flagsInfo.join(", ")}`);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Show symbol count
|
|
393
|
+
const symbolCount = scope.symbols.size;
|
|
394
|
+
if (symbolCount > 0) {
|
|
395
|
+
details.push(` symbols: ${symbolCount}`);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Show parent scope if present
|
|
399
|
+
if (scope.parent) {
|
|
400
|
+
details.push(` parent: ${formatScopeName(scope.parent)}`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Show owner if present (for member scopes)
|
|
404
|
+
if (scope.owner) {
|
|
405
|
+
details.push(` owner: ${formatSymbolName(scope.owner)}`);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Show child scopes if present
|
|
409
|
+
if (scope.children && scope.children.size > 0) {
|
|
410
|
+
details.push(` children: ${scope.children.size}`);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (details.length > 0) {
|
|
414
|
+
result += "\n" + details.join("\n");
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return result;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function formatRefkeys(refkeys: Refkey[] | Refkey | undefined) {
|
|
421
|
+
if (!refkeys) {
|
|
422
|
+
return "";
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (Array.isArray(refkeys)) {
|
|
426
|
+
return refkeys.map(formatRefkey).join(", ");
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return formatRefkey(refkeys);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
function formatRefkey(refkey: Refkey): string {
|
|
433
|
+
return colorText(`refkey[${refkey.key}]`, {
|
|
434
|
+
fg: {
|
|
435
|
+
r: 150,
|
|
436
|
+
g: 0,
|
|
437
|
+
b: 0,
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
}
|