@cplieger/deadset-ts 3.3.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/src/analysis.js +8 -1
- package/dist/src/calls.js +154 -0
- package/dist/src/class-members.js +92 -0
- package/dist/src/components.js +61 -106
- package/dist/src/config.js +9 -0
- package/dist/src/configured-declarations.js +232 -0
- package/dist/src/decorator.js +3 -10
- package/dist/src/framework-lifecycle.js +192 -0
- package/dist/src/injection-container.js +101 -0
- package/dist/src/kinds.js +40 -0
- package/dist/src/print.js +28 -1
- package/dist/src/resolve.js +188 -9
- package/dist/src/run.js +9 -3
- package/dist/src/schema.js +55 -2
- package/dist/src/scope.js +55 -21
- package/dist/src/serialization-contract.js +405 -0
- package/dist/src/value-reach.js +120 -0
- package/dist/src/version.js +1 -1
- package/jsr.json +1 -1
- package/package.json +2 -2
- package/src/analysis.ts +8 -1
- package/src/calls.ts +224 -0
- package/src/class-members.ts +136 -0
- package/src/components.ts +67 -130
- package/src/config.ts +68 -2
- package/src/configured-declarations.ts +308 -0
- package/src/decorator.ts +4 -16
- package/src/exempt.ts +5 -1
- package/src/framework-lifecycle.ts +280 -0
- package/src/injection-container.ts +141 -0
- package/src/kinds.ts +41 -0
- package/src/print.ts +36 -1
- package/src/resolve.ts +278 -9
- package/src/run.ts +10 -3
- package/src/schema.ts +66 -3
- package/src/scope.ts +63 -22
- package/src/serialization-contract.ts +610 -0
- package/src/value-reach.ts +152 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The classes of the target a value of one type carries, as a serializer walking the
|
|
3
|
+
* value reaches them: through union and intersection constituents, array and tuple
|
|
4
|
+
* elements, and the data members of the target's classes and of object types the
|
|
5
|
+
* target writes. The walk stops at `any`, `unknown`, a type parameter, a function and
|
|
6
|
+
* an interface or class of another program, so an instance held only there is missed.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
ObjectFlags,
|
|
11
|
+
SymbolFlags,
|
|
12
|
+
type ObjectType,
|
|
13
|
+
type Symbol as TSSymbol,
|
|
14
|
+
type Type,
|
|
15
|
+
} from "@typescript/native/unstable/sync";
|
|
16
|
+
import { classNames, typesAt } from "./class-members.ts";
|
|
17
|
+
import type { Inventory } from "./inventory.ts";
|
|
18
|
+
import type { ProjectView } from "./session.ts";
|
|
19
|
+
|
|
20
|
+
/** The object types whose members the walk reads whatever declares them. */
|
|
21
|
+
const WRITTEN = ObjectFlags.ObjectLiteral | ObjectFlags.Mapped;
|
|
22
|
+
|
|
23
|
+
/** The symbols of an anonymous object type the target writes as a type. */
|
|
24
|
+
const LITERAL_SYMBOLS = SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral;
|
|
25
|
+
|
|
26
|
+
/** The classes a type's values carry, each asked of the checker once. */
|
|
27
|
+
export interface ValueReach {
|
|
28
|
+
/** The identifiers of the target's classes a value of `type` carries. */
|
|
29
|
+
classesOf(type: Type): ReadonlySet<string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The global array types, whose element type is what an array value carries. */
|
|
33
|
+
function arrayTargets<Brand>(project: ProjectView<Brand>): ReadonlySet<number> {
|
|
34
|
+
const checker = project.checker;
|
|
35
|
+
return new Set(
|
|
36
|
+
["Array", "ReadonlyArray"].flatMap((name) => {
|
|
37
|
+
const symbol = checker.resolveName(name, SymbolFlags.Type, undefined, false);
|
|
38
|
+
return symbol === undefined ? [] : [checker.getDeclaredTypeOfSymbol(symbol).id];
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The walk over one project's types, against the classes of `held`, the same
|
|
45
|
+
* project's inventory.
|
|
46
|
+
*/
|
|
47
|
+
export function valueReach<Brand>(project: ProjectView<Brand>, held: Inventory): ValueReach {
|
|
48
|
+
const checker = project.checker;
|
|
49
|
+
const names = [...classNames(project, held)];
|
|
50
|
+
const declared = typesAt(
|
|
51
|
+
project,
|
|
52
|
+
names.map(([, node]) => node),
|
|
53
|
+
);
|
|
54
|
+
const classOfTarget = new Map<number, string>();
|
|
55
|
+
names.forEach(([id], index) => {
|
|
56
|
+
const type = declared[index];
|
|
57
|
+
if (type !== undefined) {
|
|
58
|
+
classOfTarget.set(type.id, id);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const arrays = arrayTargets(project);
|
|
62
|
+
const own = new Set(project.ownSourceFiles().map((file) => file.fileName));
|
|
63
|
+
const children = new Map<number, readonly Type[]>();
|
|
64
|
+
|
|
65
|
+
/** The generic target of a type reference, and the type itself otherwise. */
|
|
66
|
+
const targetOf = (type: ObjectType): Type =>
|
|
67
|
+
(type.objectFlags & ObjectFlags.Reference) !== 0 && type.isTypeReference()
|
|
68
|
+
? type.getTarget()
|
|
69
|
+
: type;
|
|
70
|
+
|
|
71
|
+
const classOf = (type: Type): string | undefined => {
|
|
72
|
+
if (!type.isObjectType()) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return classOfTarget.get(type.id) ?? classOfTarget.get(targetOf(type).id);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/** Whether the target writes the object type, so its members are what the value holds. */
|
|
79
|
+
const isWritten = (type: ObjectType): boolean => {
|
|
80
|
+
if ((type.objectFlags & WRITTEN) !== 0) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
const symbol: TSSymbol | undefined = type.getSymbol();
|
|
84
|
+
if (symbol === undefined) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if ((type.objectFlags & ObjectFlags.Anonymous) !== 0) {
|
|
88
|
+
return (symbol.flags & LITERAL_SYMBOLS) !== 0;
|
|
89
|
+
}
|
|
90
|
+
return (
|
|
91
|
+
(symbol.flags & SymbolFlags.Interface) !== 0 &&
|
|
92
|
+
symbol.declarations.every((handle) => own.has(handle.path))
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** The types a value of one object type holds in its data members. */
|
|
97
|
+
const memberTypes = (type: Type): readonly Type[] => {
|
|
98
|
+
const properties = checker
|
|
99
|
+
.getPropertiesOfType(type)
|
|
100
|
+
.filter((property) => (property.flags & SymbolFlags.Property) !== 0);
|
|
101
|
+
const types = properties.length === 0 ? [] : checker.getTypeOfSymbol(properties);
|
|
102
|
+
return [
|
|
103
|
+
...types.filter((held): held is Type => held !== undefined),
|
|
104
|
+
...checker.getIndexInfosOfType(type).map((info) => info.valueType),
|
|
105
|
+
];
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/** The types a value of one type holds, read once per type. */
|
|
109
|
+
const childrenOf = (type: Type): readonly Type[] => {
|
|
110
|
+
const known = children.get(type.id);
|
|
111
|
+
if (known !== undefined) {
|
|
112
|
+
return known;
|
|
113
|
+
}
|
|
114
|
+
let found: readonly Type[] = [];
|
|
115
|
+
if (type.isUnionType() || type.isIntersectionType()) {
|
|
116
|
+
found = type.getTypes();
|
|
117
|
+
} else if (type.isObjectType()) {
|
|
118
|
+
const target = targetOf(type);
|
|
119
|
+
const isList =
|
|
120
|
+
type.isTypeReference() &&
|
|
121
|
+
(arrays.has(target.id) ||
|
|
122
|
+
(target.isObjectType() && (target.objectFlags & ObjectFlags.Tuple) !== 0));
|
|
123
|
+
if (classOf(type) !== undefined || (!isList && isWritten(type))) {
|
|
124
|
+
found = memberTypes(type);
|
|
125
|
+
} else if (isList && type.isTypeReference()) {
|
|
126
|
+
found = checker.getTypeArguments(type);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
children.set(type.id, found);
|
|
130
|
+
return found;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
classesOf: (type) => {
|
|
135
|
+
const found = new Set<string>();
|
|
136
|
+
const seen = new Set<number>();
|
|
137
|
+
const pending: Type[] = [type];
|
|
138
|
+
for (let next = pending.pop(); next !== undefined; next = pending.pop()) {
|
|
139
|
+
if (seen.has(next.id)) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
seen.add(next.id);
|
|
143
|
+
const owner = classOf(next);
|
|
144
|
+
if (owner !== undefined) {
|
|
145
|
+
found.add(owner);
|
|
146
|
+
}
|
|
147
|
+
pending.push(...childrenOf(next));
|
|
148
|
+
}
|
|
149
|
+
return found;
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
package/src/version.ts
CHANGED