@prisma/orm-framework 8.0.0-rc.14-dev.16 → 8.0.0-rc.14-dev.17
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/{authoring-Bn_5zI9q.mjs → authoring-C8hxYYQI.mjs} +3 -21
- package/dist/authoring-C8hxYYQI.mjs.map +1 -0
- package/dist/{authoring-DTZsvKV7.d.mts → authoring-CQOFIHhF.d.mts} +4 -20
- package/dist/{authoring-DTZsvKV7.d.mts.map → authoring-CQOFIHhF.d.mts.map} +1 -1
- package/dist/binder-CQGFQCuK-DrdVszQh.d.mts +452 -0
- package/dist/binder-CQGFQCuK-DrdVszQh.d.mts.map +1 -0
- package/dist/{components-DgQX4ccF.d.mts → components-DFA65tWf.d.mts} +2 -2
- package/dist/{components-DgQX4ccF.d.mts.map → components-DFA65tWf.d.mts.map} +1 -1
- package/dist/components.d.mts +11 -11
- package/dist/components.mjs +4 -4
- package/dist/components__authoring.d.mts +4 -4
- package/dist/components__authoring.mjs +3 -3
- package/dist/components__components.d.mts +2 -2
- package/dist/components__control.d.mts +3 -3
- package/dist/components__control.mjs +2 -2
- package/dist/components__execution.d.mts +1 -1
- package/dist/components__psl-ast.d.mts +3 -3
- package/dist/{config-types-CcK2xcMX.d.mts → config-types-DDNiQ3jk.d.mts} +8 -4
- package/dist/config-types-DDNiQ3jk.d.mts.map +1 -0
- package/dist/config.d.mts +1 -1
- package/dist/config__config-types.d.mts +1 -1
- package/dist/contract-authoring.d.mts +2 -2
- package/dist/contract-authoring.mjs +1 -1
- package/dist/{control-qWBPmuvX.d.mts → control-B059zyD4.d.mts} +10 -6
- package/dist/{control-qWBPmuvX.d.mts.map → control-B059zyD4.d.mts.map} +1 -1
- package/dist/{control-uVHmDgha.mjs → control-DEcjDcjA.mjs} +2 -2
- package/dist/{control-uVHmDgha.mjs.map → control-DEcjDcjA.mjs.map} +1 -1
- package/dist/{declarations-C0VwsVFX-24_6w6Lb.mjs → declarations-C0VwsVFX-BcP1Nyv4.mjs} +2 -2
- package/dist/{declarations-C0VwsVFX-24_6w6Lb.mjs.map → declarations-C0VwsVFX-BcP1Nyv4.mjs.map} +1 -1
- package/dist/errors.d.mts +1 -1
- package/dist/errors__execution.d.mts +1 -1
- package/dist/{execution-DHFIqFJC.d.mts → execution-D5L9gHoo.d.mts} +2 -2
- package/dist/{execution-DHFIqFJC.d.mts.map → execution-D5L9gHoo.d.mts.map} +1 -1
- package/dist/{execution-BW3cjWqQ.d.mts → execution-NKU9_mZ4.d.mts} +2 -2
- package/dist/{execution-BW3cjWqQ.d.mts.map → execution-NKU9_mZ4.d.mts.map} +1 -1
- package/dist/{framework-authoring-CsVwBOxP-saf7NH7p.d.mts → framework-authoring-BLXTNi9g-CcRc8u9I.d.mts} +3 -12
- package/dist/{framework-authoring-CsVwBOxP-saf7NH7p.d.mts.map → framework-authoring-BLXTNi9g-CcRc8u9I.d.mts.map} +1 -1
- package/dist/{framework-components-DNtoaHTX-DWt4JeHF.d.mts → framework-components-CwclBqDh-CBGrY3Ry.d.mts} +4 -4
- package/dist/{framework-components-DNtoaHTX-DWt4JeHF.d.mts.map → framework-components-CwclBqDh-CBGrY3Ry.d.mts.map} +1 -1
- package/dist/{mutation-default-types--XIOgxCm-B6NmSBxF.d.mts → mutation-default-types-ZfKqVdmf-DATmLFpQ.d.mts} +3 -3
- package/dist/{mutation-default-types--XIOgxCm-B6NmSBxF.d.mts.map → mutation-default-types-ZfKqVdmf-DATmLFpQ.d.mts.map} +1 -1
- package/dist/{parse-DqMTVHCw-Cw1RjDIQ.d.mts → parse-DqMTVHCw-DqqgVEUq.d.mts} +6 -6
- package/dist/{parse-DqMTVHCw-Cw1RjDIQ.d.mts.map → parse-DqMTVHCw-DqqgVEUq.d.mts.map} +1 -1
- package/dist/{parse-EvT3Ac9q-j7zYLB_6.mjs → parse-EvT3Ac9q-B0Nxq52v.mjs} +2 -2
- package/dist/{parse-EvT3Ac9q-j7zYLB_6.mjs.map → parse-EvT3Ac9q-B0Nxq52v.mjs.map} +1 -1
- package/dist/{psl-ast-CAA6nJRp-DIk-wyX1.d.mts → psl-ast-CPxYIxM1-XHoHPgRO.d.mts} +3 -3
- package/dist/{psl-ast-CAA6nJRp-DIk-wyX1.d.mts.map → psl-ast-CPxYIxM1-XHoHPgRO.d.mts.map} +1 -1
- package/dist/psl-ast-DA_tKWiL.d.mts +2 -0
- package/dist/psl-parser.d.mts +10 -320
- package/dist/psl-parser.d.mts.map +1 -1
- package/dist/psl-parser.mjs +1388 -1328
- package/dist/psl-parser.mjs.map +1 -1
- package/dist/psl-parser__format.d.mts +1 -1
- package/dist/psl-parser__format.mjs +2 -2
- package/dist/psl-parser__interpret.d.mts +21 -32
- package/dist/psl-parser__interpret.d.mts.map +1 -1
- package/dist/psl-parser__interpret.mjs +28 -40
- package/dist/psl-parser__interpret.mjs.map +1 -1
- package/dist/psl-parser__syntax.d.mts +1 -1
- package/dist/psl-parser__syntax.mjs +2 -2
- package/dist/psl-printer.d.mts +4 -4
- package/dist/psl-printer.mjs +1 -1
- package/dist/{temporal-presets-UGhnJIuo-DCoJ3HJj.d.mts → temporal-presets-DKHiZVPP-DLAr--Pb.d.mts} +4 -4
- package/dist/{temporal-presets-UGhnJIuo-DCoJ3HJj.d.mts.map → temporal-presets-DKHiZVPP-DLAr--Pb.d.mts.map} +1 -1
- package/dist/{temporal-presets-DsGuaFyT-DWzKyja_.mjs → temporal-presets-DzBBD4St-BaL1QaZ7.mjs} +3 -16
- package/dist/temporal-presets-DzBBD4St-BaL1QaZ7.mjs.map +1 -0
- package/package.json +15 -15
- package/dist/authoring-Bn_5zI9q.mjs.map +0 -1
- package/dist/config-types-CcK2xcMX.d.mts.map +0 -1
- package/dist/psl-ast-irbNZ93U.d.mts +0 -2
- package/dist/symbol-table-DZDTpkQ7-BrBUqb4g.d.mts +0 -126
- package/dist/symbol-table-DZDTpkQ7-BrBUqb4g.d.mts.map +0 -1
- package/dist/temporal-presets-DsGuaFyT-DWzKyja_.mjs.map +0 -1
package/dist/psl-parser.mjs
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import { t as blindCast } from "./casts-DpaahrlC-Bd5n2coI.mjs";
|
|
2
2
|
import { t as InternalError } from "./internal-error-ChGYPVpq-DhUD05u0.mjs";
|
|
3
3
|
import { a as or, i as okVoid, n as notOk, r as ok, t as and } from "./result-8OXF26MN.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { b as isAuthoringModelAttributeDescriptor, x as isAuthoringPslBlockDescriptor } from "./temporal-presets-DzBBD4St-BaL1QaZ7.mjs";
|
|
5
5
|
import { a as flatPslModels, c as namespacePslExtensionBlocks } from "./psl-ast-CyvE6CR-.mjs";
|
|
6
6
|
import { n as isPslIdentifier } from "./tokenizer-BMz7z2KR-J0yZ4im3.mjs";
|
|
7
|
-
import { C as TaggedLiteralExprAst, S as StringLiteralExprAst, T as TypesBlockAst, _ as NumberLiteralExprAst, a as CompositeTypeDeclarationAst, d as IdentifierAst, g as NamespaceDeclarationAst, i as BooleanLiteralExprAst, l as FunctionCallAst, m as ModelDeclarationAst, t as ArrayLiteralAst, u as GenericBlockDeclarationAst, y as ObjectLiteralExprAst } from "./declarations-C0VwsVFX-
|
|
7
|
+
import { C as TaggedLiteralExprAst, S as StringLiteralExprAst, T as TypesBlockAst, _ as NumberLiteralExprAst, a as CompositeTypeDeclarationAst, d as IdentifierAst, g as NamespaceDeclarationAst, i as BooleanLiteralExprAst, l as FunctionCallAst, m as ModelDeclarationAst, t as ArrayLiteralAst, u as GenericBlockDeclarationAst, y as ObjectLiteralExprAst } from "./declarations-C0VwsVFX-BcP1Nyv4.mjs";
|
|
8
8
|
import { a as mapPslDiagnostics, c as readResolvedAttributes, i as keywordPslSpan, l as readResolvedConstructorCall, n as diagnosticFromSpan, o as nodePslSpan, r as diagnosticSource, s as readResolvedAttribute, t as createPslDiagnosticCollector } from "./resolve-GE34dgM6-D33m6YEw.mjs";
|
|
9
|
-
//#region ../../../1-framework/2-authoring/psl-parser/dist/
|
|
10
|
-
function getPositionalArgument(attribute, index = 0) {
|
|
11
|
-
return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
|
|
12
|
-
}
|
|
13
|
-
function parseQuotedStringLiteral(value) {
|
|
14
|
-
const match = value.trim().match(/^(['"])(.*)\1$/);
|
|
15
|
-
if (!match) return void 0;
|
|
16
|
-
return match[2] ?? "";
|
|
17
|
-
}
|
|
9
|
+
//#region ../../../1-framework/2-authoring/psl-parser/dist/symbol-table-0DYRY2eQ.mjs
|
|
18
10
|
function* modelAttributeDescriptors(namespace) {
|
|
19
11
|
for (const value of Object.values(namespace)) {
|
|
20
12
|
if (isAuthoringModelAttributeDescriptor(value)) {
|
|
@@ -37,1216 +29,1514 @@ function assembleAttributeSpecs(contributions) {
|
|
|
37
29
|
field: Object.freeze({ ...contributions.attributeSpecs.field })
|
|
38
30
|
}));
|
|
39
31
|
}
|
|
40
|
-
function
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
name,
|
|
44
|
-
documentation: config.documentation,
|
|
45
|
-
positional: config.positional ?? [],
|
|
46
|
-
named: config.named ?? {},
|
|
47
|
-
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
48
|
-
};
|
|
32
|
+
function resolveDescribeUnsupportedAttribute(pslDiagnostics) {
|
|
33
|
+
if (pslDiagnostics?.describeUnsupportedAttribute === void 0) return;
|
|
34
|
+
return blindCast(pslDiagnostics.describeUnsupportedAttribute);
|
|
49
35
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
53
|
-
code,
|
|
54
|
-
message,
|
|
55
|
-
...diagnosticSource(ctx.sources, node.syntax).at(nodePslSpan(node.syntax, ctx.sources))
|
|
56
|
-
};
|
|
36
|
+
function resolveDescribeUnresolvedType(pslDiagnostics) {
|
|
37
|
+
if (pslDiagnostics?.describeUnresolvedType === void 0) return;
|
|
38
|
+
return blindCast(pslDiagnostics.describeUnresolvedType);
|
|
57
39
|
}
|
|
58
|
-
function
|
|
40
|
+
function blockSpecFactoryOf(descriptor) {
|
|
41
|
+
return blindCast(descriptor.spec);
|
|
42
|
+
}
|
|
43
|
+
function isContributedTypeDescriptor(value) {
|
|
44
|
+
return "kind" in value && (value.kind === "typeConstructor" || value.kind === "fieldPreset");
|
|
45
|
+
}
|
|
46
|
+
function mergeContributedTypes(...namespaces) {
|
|
47
|
+
const merged = {};
|
|
48
|
+
for (const namespace of namespaces) for (const [name, value] of Object.entries(namespace)) {
|
|
49
|
+
const existing = Object.hasOwn(merged, name) ? merged[name] : void 0;
|
|
50
|
+
merged[name] = existing !== void 0 && !isContributedTypeDescriptor(existing) && !isContributedTypeDescriptor(value) ? mergeContributedTypes(existing, value) : value;
|
|
51
|
+
}
|
|
52
|
+
return merged;
|
|
53
|
+
}
|
|
54
|
+
function contributedTypeScope(contributedTypes) {
|
|
55
|
+
const members = collect(contributedTypes, []);
|
|
59
56
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const value = literal.value();
|
|
66
|
-
if (value !== void 0) return ok(value);
|
|
67
|
-
}
|
|
68
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected a boolean literal")]);
|
|
57
|
+
lookup(name) {
|
|
58
|
+
return members.get(name);
|
|
59
|
+
},
|
|
60
|
+
entries() {
|
|
61
|
+
return members.entries();
|
|
69
62
|
}
|
|
70
63
|
};
|
|
71
64
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
65
|
+
function collect(namespace, prefix) {
|
|
66
|
+
const members = /* @__PURE__ */ new Map();
|
|
67
|
+
for (const [name, value] of Object.entries(namespace)) {
|
|
68
|
+
const path = [...prefix, name];
|
|
69
|
+
members.set(name, isContributedTypeDescriptor(value) ? {
|
|
70
|
+
kind: "contributedType",
|
|
71
|
+
name,
|
|
72
|
+
path,
|
|
73
|
+
descriptor: value
|
|
74
|
+
} : {
|
|
75
|
+
kind: "contributedNamespace",
|
|
76
|
+
name,
|
|
77
|
+
path,
|
|
78
|
+
members: collect(value, path)
|
|
79
|
+
});
|
|
80
80
|
}
|
|
81
|
+
return members;
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
function findBlockDescriptor(descriptors, keyword) {
|
|
84
|
+
if (descriptors === void 0) return void 0;
|
|
85
|
+
for (const value of Object.values(descriptors)) {
|
|
86
|
+
if (value === void 0) continue;
|
|
87
|
+
if (isAuthoringPslBlockDescriptor(value)) {
|
|
88
|
+
if (value.keyword === keyword) return value;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const nested = findBlockDescriptor(value, keyword);
|
|
92
|
+
if (nested !== void 0) return nested;
|
|
93
|
+
}
|
|
91
94
|
}
|
|
92
|
-
function
|
|
93
|
-
const
|
|
94
|
-
if (declaration.kind !== expected.kind) return false;
|
|
95
|
-
return expected.kind !== "block" || declaration.kind === "block" && declaration.keyword === expected.keyword;
|
|
95
|
+
function* recordNames(...records) {
|
|
96
|
+
for (const record of records) yield* Object.keys(record);
|
|
96
97
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
case "crossSpace": return "cross-space reference";
|
|
102
|
-
case "unresolved": return "unresolved name";
|
|
103
|
-
default: return resolution.kind;
|
|
98
|
+
var Scope = class {
|
|
99
|
+
parent;
|
|
100
|
+
constructor(parent) {
|
|
101
|
+
this.parent = parent;
|
|
104
102
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
parse: (arg, ctx) => {
|
|
113
|
-
const name = IdentifierAst.cast(arg.syntax)?.name();
|
|
114
|
-
if (name === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
|
|
115
|
-
const resolution = ctx.binder.symbolForNode(arg.syntax);
|
|
116
|
-
if (resolution === void 0 || resolution.kind === "unresolved") return notOk([]);
|
|
117
|
-
const reference = entityReference(resolution);
|
|
118
|
-
if (reference === void 0 || !matchesSelector(reference, expected)) return notOk([leafDiagnostic(ctx, arg, `Expected ${label} "${name}", found ${describeResolution(resolution)}`)]);
|
|
119
|
-
return ok(reference);
|
|
103
|
+
*entries() {
|
|
104
|
+
const seen = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const name of this.ownNames()) {
|
|
106
|
+
if (seen.has(name)) continue;
|
|
107
|
+
seen.add(name);
|
|
108
|
+
const resolution = this.lookup(name);
|
|
109
|
+
if (resolution !== void 0) yield [name, resolution];
|
|
120
110
|
}
|
|
111
|
+
for (const entry of this.parent?.entries() ?? []) if (!seen.has(entry[0])) yield entry;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
function contributedResolution(member) {
|
|
115
|
+
return member.kind === "contributedType" ? {
|
|
116
|
+
kind: "contributedType",
|
|
117
|
+
symbol: member
|
|
118
|
+
} : {
|
|
119
|
+
kind: "contributedNamespace",
|
|
120
|
+
symbol: member
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
function
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (resolution === void 0) return notOk([]);
|
|
130
|
-
if (resolution.kind === "field") return ok(resolution.symbol.name);
|
|
131
|
-
if (resolution.kind === "crossSpace") return ok(name);
|
|
132
|
-
return notOk([]);
|
|
133
|
-
}
|
|
134
|
-
function fieldRef() {
|
|
135
|
-
return {
|
|
136
|
-
kind: "fieldRef",
|
|
137
|
-
label: "field name",
|
|
138
|
-
parse: parseFieldName
|
|
123
|
+
function namespaceMember(namespace, name) {
|
|
124
|
+
const model = namespace.models[name];
|
|
125
|
+
if (model !== void 0) return {
|
|
126
|
+
kind: "model",
|
|
127
|
+
symbol: model,
|
|
128
|
+
namespace
|
|
139
129
|
};
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
130
|
+
const compositeType = namespace.compositeTypes[name];
|
|
131
|
+
if (compositeType !== void 0) return {
|
|
132
|
+
kind: "compositeType",
|
|
133
|
+
symbol: compositeType,
|
|
134
|
+
namespace
|
|
135
|
+
};
|
|
136
|
+
const block = namespace.blocks[name];
|
|
137
|
+
if (block !== void 0) return {
|
|
138
|
+
kind: "block",
|
|
139
|
+
symbol: block,
|
|
140
|
+
namespace
|
|
146
141
|
};
|
|
147
142
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
let reportedExcess = false;
|
|
154
|
-
for (const arg of args) {
|
|
155
|
-
const name = arg.name()?.name();
|
|
156
|
-
let key;
|
|
157
|
-
let param;
|
|
158
|
-
if (name === void 0) {
|
|
159
|
-
const posParam = spec.positional[positionalSlot];
|
|
160
|
-
if (posParam === void 0) {
|
|
161
|
-
if (!reportedExcess) {
|
|
162
|
-
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received too many positional arguments`, ctx, span, sourceNode)]));
|
|
163
|
-
reportedExcess = true;
|
|
164
|
-
}
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
positionalSlot += 1;
|
|
168
|
-
key = posParam.key;
|
|
169
|
-
param = posParam.type;
|
|
170
|
-
} else {
|
|
171
|
-
const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : void 0;
|
|
172
|
-
if (namedParam === void 0) {
|
|
173
|
-
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received unknown argument "${name}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
key = name;
|
|
177
|
-
param = namedParam.type;
|
|
178
|
-
}
|
|
179
|
-
if (seen.has(key)) {
|
|
180
|
-
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received duplicate argument "${key}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
seen.add(key);
|
|
184
|
-
const result = parseArgValue(arg, param, ctx);
|
|
185
|
-
if (result.ok) output[key] = result.value;
|
|
186
|
-
outcome = and(outcome, result);
|
|
143
|
+
var ContributedScope = class extends Scope {
|
|
144
|
+
#registry;
|
|
145
|
+
constructor(registry) {
|
|
146
|
+
super(void 0);
|
|
147
|
+
this.#registry = registry;
|
|
187
148
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
finalized.add(key);
|
|
192
|
-
const effective = namedParam ?? positionalParam;
|
|
193
|
-
if (effective === void 0) return;
|
|
194
|
-
if (isOptionalArgType(effective)) {
|
|
195
|
-
if (effective.hasDefault) output[key] = effective.defaultValue;
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" is missing required argument "${key}"`, ctx, span, sourceNode)]));
|
|
199
|
-
};
|
|
200
|
-
for (const param of spec.positional) {
|
|
201
|
-
const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : void 0;
|
|
202
|
-
finalizeAbsentKey(param.key, param.type, namedParam?.type);
|
|
149
|
+
lookup(name) {
|
|
150
|
+
const member = this.#registry.lookup(name);
|
|
151
|
+
return member === void 0 ? void 0 : contributedResolution(member);
|
|
203
152
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
153
|
+
*ownNames() {
|
|
154
|
+
for (const [name] of this.#registry.entries()) yield name;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
var DocumentScope = class extends Scope {
|
|
158
|
+
#records;
|
|
159
|
+
constructor(records, parent) {
|
|
160
|
+
super(parent);
|
|
161
|
+
this.#records = records;
|
|
162
|
+
}
|
|
163
|
+
lookup(name) {
|
|
164
|
+
const records = this.#records;
|
|
165
|
+
const model = records.models[name];
|
|
166
|
+
if (model !== void 0) return {
|
|
167
|
+
kind: "model",
|
|
168
|
+
symbol: model
|
|
169
|
+
};
|
|
170
|
+
const compositeType = records.compositeTypes[name];
|
|
171
|
+
if (compositeType !== void 0) return {
|
|
172
|
+
kind: "compositeType",
|
|
173
|
+
symbol: compositeType
|
|
174
|
+
};
|
|
175
|
+
const namedType = records.namedTypes[name];
|
|
176
|
+
if (namedType !== void 0) return {
|
|
177
|
+
kind: "namedType",
|
|
178
|
+
symbol: namedType
|
|
179
|
+
};
|
|
180
|
+
const block = records.blocks[name];
|
|
181
|
+
if (block !== void 0) return {
|
|
182
|
+
kind: "block",
|
|
183
|
+
symbol: block
|
|
184
|
+
};
|
|
185
|
+
const namespace = records.namespaces[name];
|
|
186
|
+
if (namespace !== void 0) return {
|
|
187
|
+
kind: "namespace",
|
|
188
|
+
symbol: namespace
|
|
189
|
+
};
|
|
190
|
+
return this.parent?.lookup(name);
|
|
191
|
+
}
|
|
192
|
+
ownNames() {
|
|
193
|
+
const records = this.#records;
|
|
194
|
+
return recordNames(records.models, records.compositeTypes, records.namedTypes, records.blocks, records.namespaces);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
var NamespaceScope = class extends Scope {
|
|
198
|
+
#namespace;
|
|
199
|
+
constructor(namespace, parent) {
|
|
200
|
+
super(parent);
|
|
201
|
+
this.#namespace = namespace;
|
|
202
|
+
}
|
|
203
|
+
lookup(name) {
|
|
204
|
+
return namespaceMember(this.#namespace, name) ?? this.parent?.lookup(name);
|
|
205
|
+
}
|
|
206
|
+
ownNames() {
|
|
207
|
+
const namespace = this.#namespace;
|
|
208
|
+
return recordNames(namespace.models, namespace.compositeTypes, namespace.blocks);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
function contributedScope(registry) {
|
|
212
|
+
return new ContributedScope(registry);
|
|
213
|
+
}
|
|
214
|
+
function documentScope(records, parent) {
|
|
215
|
+
return new DocumentScope(records, parent);
|
|
216
|
+
}
|
|
217
|
+
function namedTypeBaseScope(records, parent) {
|
|
218
|
+
return new DocumentScope({
|
|
219
|
+
...records,
|
|
220
|
+
namedTypes: {}
|
|
221
|
+
}, parent);
|
|
222
|
+
}
|
|
223
|
+
function namespaceScope(namespace, parent) {
|
|
224
|
+
return new NamespaceScope(namespace, parent);
|
|
225
|
+
}
|
|
226
|
+
function isNamespaceLike(resolution) {
|
|
227
|
+
return resolution.kind === "namespace" || resolution.kind === "contributedNamespace";
|
|
228
|
+
}
|
|
229
|
+
function* memberEntries(qualifier) {
|
|
230
|
+
if (qualifier.kind === "contributedNamespace") {
|
|
231
|
+
for (const [name, member] of qualifier.symbol.members) yield [name, contributedResolution(member)];
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
yield* new NamespaceScope(qualifier.symbol, void 0).entries();
|
|
235
|
+
}
|
|
236
|
+
function lookupMember(qualifier, name) {
|
|
237
|
+
if (qualifier.kind === "contributedNamespace") {
|
|
238
|
+
const member = qualifier.symbol.members.get(name);
|
|
239
|
+
return member === void 0 ? void 0 : contributedResolution(member);
|
|
240
|
+
}
|
|
241
|
+
return namespaceMember(qualifier.symbol, name);
|
|
242
|
+
}
|
|
243
|
+
const PSL_UNRESOLVED_REFERENCE = "PSL_UNRESOLVED_REFERENCE";
|
|
244
|
+
function typeReferenceNode(symbol) {
|
|
245
|
+
return symbol.node.typeAnnotation()?.name()?.syntax;
|
|
246
|
+
}
|
|
247
|
+
function contributedTypeOf(resolution, binder) {
|
|
248
|
+
const base = resolution?.kind === "namedType" ? typeReferenceNode(resolution.symbol) : void 0;
|
|
249
|
+
const target = base === void 0 ? resolution : binder.symbolForNode(base);
|
|
250
|
+
return target?.kind === "contributedType" ? target.symbol : void 0;
|
|
251
|
+
}
|
|
252
|
+
var PslBinder = class {
|
|
253
|
+
#declarations;
|
|
254
|
+
#references;
|
|
255
|
+
#documentScope;
|
|
256
|
+
#scopes;
|
|
257
|
+
constructor(declarations, references, documentScope, scopes) {
|
|
258
|
+
this.#declarations = declarations;
|
|
259
|
+
this.#references = references;
|
|
260
|
+
this.#documentScope = documentScope;
|
|
261
|
+
this.#scopes = scopes;
|
|
262
|
+
}
|
|
263
|
+
declaredSymbol(node) {
|
|
264
|
+
return this.#declarations.get(node);
|
|
265
|
+
}
|
|
266
|
+
symbolForNode(node) {
|
|
267
|
+
return this.#references.get(node);
|
|
268
|
+
}
|
|
269
|
+
scopeAt(node) {
|
|
270
|
+
return node.findAncestor((ancestor) => this.#scopes.get(ancestor)) ?? this.#documentScope;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
var ScopeStack = class {
|
|
274
|
+
#base;
|
|
275
|
+
#scopes;
|
|
276
|
+
constructor(base) {
|
|
277
|
+
this.#base = base;
|
|
278
|
+
this.#scopes = [base];
|
|
279
|
+
}
|
|
280
|
+
current() {
|
|
281
|
+
return this.#scopes[this.#scopes.length - 1] ?? this.#base;
|
|
282
|
+
}
|
|
283
|
+
push(scope) {
|
|
284
|
+
this.#scopes.push(scope);
|
|
285
|
+
}
|
|
286
|
+
pop() {
|
|
287
|
+
this.#scopes.pop();
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
function walkEntities(symbolTable, stack, binder, visit) {
|
|
291
|
+
const { topLevel } = symbolTable;
|
|
292
|
+
for (const entity of Object.values(topLevel.models)) visit(entity);
|
|
293
|
+
for (const entity of Object.values(topLevel.compositeTypes)) visit(entity);
|
|
294
|
+
for (const namespace of Object.values(topLevel.namespaces)) {
|
|
295
|
+
stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
|
|
296
|
+
for (const entity of Object.values(namespace.models)) visit(entity);
|
|
297
|
+
for (const entity of Object.values(namespace.compositeTypes)) visit(entity);
|
|
298
|
+
stack.pop();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function createBinder(input) {
|
|
302
|
+
const { symbolTable, sources, context } = input;
|
|
303
|
+
const contributions = context.authoringContributions;
|
|
304
|
+
const describeUnsupportedAttributeFactory = resolveDescribeUnsupportedAttribute(context.pslDiagnostics);
|
|
305
|
+
const describeUnresolvedTypeFactory = resolveDescribeUnresolvedType(context.pslDiagnostics);
|
|
306
|
+
return bind({
|
|
307
|
+
sources,
|
|
308
|
+
symbolTable,
|
|
309
|
+
contributedTypes: mergeContributedTypes(contributions.field, contributions.type),
|
|
310
|
+
attributeSpecs: assembleAttributeSpecs(contributions),
|
|
311
|
+
pslBlockDescriptors: contributions.pslBlockDescriptors,
|
|
312
|
+
controlMutationDefaults: {
|
|
313
|
+
defaultFunctionRegistry: context.controlMutationDefaults.defaultFunctionRegistry,
|
|
314
|
+
dataTypeEntries: contributions.dataTypes
|
|
315
|
+
},
|
|
316
|
+
...describeUnsupportedAttributeFactory !== void 0 ? { describeUnsupportedAttribute: describeUnsupportedAttributeFactory(sources) } : {},
|
|
317
|
+
...describeUnresolvedTypeFactory !== void 0 ? { describeUnresolvedType: describeUnresolvedTypeFactory(contributions) } : {}
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function bind(options) {
|
|
321
|
+
const { sources, symbolTable, contributedTypes, attributeSpecs, controlMutationDefaults, describeUnsupportedAttribute, describeUnresolvedType } = options;
|
|
322
|
+
const pslBlockDescriptors = options.pslBlockDescriptors ?? {};
|
|
323
|
+
const contributed = contributedScope(contributedTypeScope(contributedTypes));
|
|
324
|
+
const document = documentScope(symbolTable.topLevel, contributed);
|
|
325
|
+
const stack = new ScopeStack(document);
|
|
326
|
+
const scopes = /* @__PURE__ */ new WeakMap();
|
|
327
|
+
const declarations = /* @__PURE__ */ new WeakMap();
|
|
328
|
+
const references = /* @__PURE__ */ new WeakMap();
|
|
329
|
+
const diagnostics = [];
|
|
330
|
+
const binder = new PslBinder(declarations, references, document, scopes);
|
|
331
|
+
const baseScope = namedTypeBaseScope(symbolTable.topLevel, contributed);
|
|
332
|
+
for (const symbol of Object.values(symbolTable.topLevel.namedTypes)) {
|
|
333
|
+
declarations.set(symbol.node.syntax, symbol);
|
|
334
|
+
const name = symbol.node.typeAnnotation()?.name();
|
|
335
|
+
const outcome = resolveTypeReference(name, baseScope);
|
|
336
|
+
if (name === void 0 || outcome === void 0) continue;
|
|
337
|
+
references.set(name.syntax, outcome.resolution);
|
|
338
|
+
}
|
|
339
|
+
for (const symbol of Object.values(symbolTable.topLevel.blocks)) declarations.set(symbol.node.syntax, symbol);
|
|
340
|
+
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
|
|
341
|
+
const scope = namespaceScope(namespace, document);
|
|
342
|
+
for (const declaration of namespace.declarations) {
|
|
343
|
+
declarations.set(declaration.node.syntax, namespace);
|
|
344
|
+
scopes.set(declaration.node.syntax, scope);
|
|
345
|
+
}
|
|
346
|
+
for (const symbol of Object.values(namespace.blocks)) declarations.set(symbol.node.syntax, symbol);
|
|
347
|
+
}
|
|
348
|
+
walkEntities(symbolTable, stack, binder, (entity) => {
|
|
349
|
+
declarations.set(entity.node.syntax, entity);
|
|
350
|
+
for (const field of Object.values(entity.fields)) {
|
|
351
|
+
declarations.set(field.node.syntax, field);
|
|
352
|
+
const node = typeReferenceNode(field);
|
|
353
|
+
if (node === void 0) continue;
|
|
354
|
+
const outcome = resolveTypeReference(field.node.typeAnnotation()?.name(), stack.current(), (written) => describeUnresolvedType?.({
|
|
355
|
+
field,
|
|
356
|
+
owner: entity,
|
|
357
|
+
written
|
|
358
|
+
}));
|
|
359
|
+
if (outcome === void 0) continue;
|
|
360
|
+
references.set(node, outcome.resolution);
|
|
361
|
+
if (outcome.message !== void 0) diagnostics.push({
|
|
362
|
+
code: PSL_UNRESOLVED_REFERENCE,
|
|
363
|
+
message: outcome.message,
|
|
364
|
+
data: {
|
|
365
|
+
reference: "type",
|
|
366
|
+
name: outcome.name,
|
|
367
|
+
constructorCall: field.typeConstructor !== void 0
|
|
368
|
+
},
|
|
369
|
+
...diagnosticSource(sources, node).at()
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
walkEntities(symbolTable, stack, binder, (entity) => {
|
|
374
|
+
const context = {
|
|
375
|
+
owner: entity,
|
|
376
|
+
scope: stack.current(),
|
|
377
|
+
references,
|
|
378
|
+
diagnostics,
|
|
379
|
+
symbolTable,
|
|
380
|
+
sources,
|
|
381
|
+
describeUnsupportedAttribute
|
|
382
|
+
};
|
|
383
|
+
const specContext = entity.kind === "model" ? {
|
|
384
|
+
symbols: symbolTable,
|
|
385
|
+
model: entity,
|
|
386
|
+
controlMutationDefaults
|
|
387
|
+
} : void 0;
|
|
388
|
+
bindAttributes(entity, entity.attributes, attributeSpecs.model, (factory) => specContext === void 0 ? void 0 : factory(specContext), {
|
|
389
|
+
...context,
|
|
390
|
+
field: void 0
|
|
391
|
+
});
|
|
392
|
+
for (const field of Object.values(entity.fields)) bindAttributes(field, field.attributes, attributeSpecs.field, (factory) => {
|
|
393
|
+
if (specContext === void 0) return void 0;
|
|
394
|
+
const node = typeReferenceNode(field);
|
|
395
|
+
const typeResolution = node === void 0 ? void 0 : references.get(node);
|
|
396
|
+
return factory({
|
|
397
|
+
...specContext,
|
|
398
|
+
field,
|
|
399
|
+
typeResolution
|
|
400
|
+
});
|
|
401
|
+
}, {
|
|
402
|
+
...context,
|
|
403
|
+
field
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
const blockContext = {
|
|
407
|
+
pslBlockDescriptors,
|
|
408
|
+
symbolTable,
|
|
409
|
+
sources,
|
|
410
|
+
references,
|
|
411
|
+
diagnostics
|
|
412
|
+
};
|
|
413
|
+
const bindBlocks = (blocks) => {
|
|
414
|
+
const context = {
|
|
415
|
+
...blockContext,
|
|
416
|
+
scope: stack.current()
|
|
417
|
+
};
|
|
418
|
+
for (const block of Object.values(blocks)) bindBlock(block, context);
|
|
419
|
+
};
|
|
420
|
+
bindBlocks(symbolTable.topLevel.blocks);
|
|
421
|
+
for (const namespace of Object.values(symbolTable.topLevel.namespaces)) {
|
|
422
|
+
stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
|
|
423
|
+
bindBlocks(namespace.blocks);
|
|
424
|
+
stack.pop();
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
binder,
|
|
428
|
+
diagnostics
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function bindBlock(block, ctx) {
|
|
432
|
+
const descriptor = findBlockDescriptor(ctx.pslBlockDescriptors, block.keyword);
|
|
433
|
+
if (descriptor === void 0) return;
|
|
434
|
+
const spec = blockSpecFactoryOf(descriptor)({
|
|
435
|
+
symbols: ctx.symbolTable,
|
|
436
|
+
block
|
|
437
|
+
});
|
|
438
|
+
for (const entry of block.node.entries()) {
|
|
439
|
+
const key = entry.key()?.name();
|
|
440
|
+
if (key === void 0) continue;
|
|
441
|
+
const rule = spec.mode === "struct" ? Object.hasOwn(spec.parameters, key) ? spec.parameters[key]?.type : void 0 : spec.value.type;
|
|
442
|
+
const value = entry.value();
|
|
443
|
+
if (rule === void 0 || value === void 0) continue;
|
|
444
|
+
bindExpression(rule, value, ctx);
|
|
445
|
+
}
|
|
446
|
+
const attributeSpecs = descriptor.attributes ?? {};
|
|
447
|
+
if (Object.keys(attributeSpecs).length === 0) return;
|
|
448
|
+
for (const attribute of readResolvedAttributes(block.node.attributes(), ctx.sources)) {
|
|
449
|
+
const factory = attributeSpecs[attribute.name];
|
|
450
|
+
if (factory === void 0) continue;
|
|
451
|
+
bindArguments(attribute, blindCast(factory)({
|
|
452
|
+
symbols: ctx.symbolTable,
|
|
453
|
+
block
|
|
454
|
+
}), ctx);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
function bindExpression(rule, expression, ctx, modelContext) {
|
|
458
|
+
const trial = tryBindExpression(rule, expression, ctx, modelContext);
|
|
459
|
+
for (const [node, resolution] of trial.references) ctx.references.set(node, resolution);
|
|
460
|
+
ctx.diagnostics.push(...trial.diagnostics.values());
|
|
461
|
+
}
|
|
462
|
+
function tryBindExpression(rule, expression, ctx, modelContext) {
|
|
463
|
+
const references = /* @__PURE__ */ new Map();
|
|
464
|
+
const diagnostics = /* @__PURE__ */ new Map();
|
|
465
|
+
switch (rule.kind) {
|
|
466
|
+
case "oneOf":
|
|
467
|
+
for (const alternative of rule.alternatives) {
|
|
468
|
+
const trial = tryBindExpression(alternative, expression, ctx, modelContext);
|
|
469
|
+
if (trial.matched) return trial;
|
|
470
|
+
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
471
|
+
for (const [node, resolution] of trial.references) if (resolution.kind === "unresolved") references.set(node, resolution);
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
matched: false,
|
|
475
|
+
references,
|
|
476
|
+
diagnostics
|
|
477
|
+
};
|
|
478
|
+
case "list":
|
|
479
|
+
case "record": {
|
|
480
|
+
const children = rule.kind === "list" ? ArrayLiteralAst.cast(expression.syntax)?.elements() : recordValues(expression);
|
|
481
|
+
if (children === void 0) return {
|
|
482
|
+
matched: false,
|
|
483
|
+
references,
|
|
484
|
+
diagnostics
|
|
485
|
+
};
|
|
486
|
+
let matched = true;
|
|
487
|
+
for (const child of children) {
|
|
488
|
+
const trial = tryBindExpression(rule.of, child, ctx, modelContext);
|
|
489
|
+
matched = trial.matched && matched;
|
|
490
|
+
for (const [node, resolution] of trial.references) references.set(node, resolution);
|
|
491
|
+
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
492
|
+
}
|
|
493
|
+
return {
|
|
494
|
+
matched,
|
|
495
|
+
references,
|
|
496
|
+
diagnostics
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
case "funcCall": {
|
|
500
|
+
const call = FunctionCallAst.cast(expression.syntax);
|
|
501
|
+
const name = call?.name();
|
|
502
|
+
if (call === void 0 || name === void 0 || name.dot() !== void 0 || name.colon() !== void 0 || name.identifier()?.name() !== rule.name) return {
|
|
503
|
+
matched: false,
|
|
504
|
+
references,
|
|
505
|
+
diagnostics
|
|
506
|
+
};
|
|
507
|
+
let matched = true;
|
|
508
|
+
let positional = 0;
|
|
509
|
+
for (const arg of call.args()) {
|
|
510
|
+
const key = arg.name()?.name();
|
|
511
|
+
const parameter = argumentParameter(rule.signature, key, key === void 0 ? positional++ : positional);
|
|
512
|
+
const value = arg.value();
|
|
513
|
+
if (parameter === void 0 || value === void 0) {
|
|
514
|
+
matched = false;
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
const trial = tryBindExpression(parameter.type, value, ctx, modelContext);
|
|
518
|
+
matched = trial.matched && matched;
|
|
519
|
+
for (const [node, resolution] of trial.references) references.set(node, resolution);
|
|
520
|
+
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
521
|
+
}
|
|
522
|
+
return {
|
|
523
|
+
matched,
|
|
524
|
+
references,
|
|
525
|
+
diagnostics
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
case "entityRef": {
|
|
529
|
+
const node = expression.syntax;
|
|
530
|
+
const name = IdentifierAst.cast(node)?.name();
|
|
531
|
+
if (name === void 0) return {
|
|
532
|
+
matched: false,
|
|
533
|
+
references,
|
|
534
|
+
diagnostics
|
|
535
|
+
};
|
|
536
|
+
const failures = [];
|
|
537
|
+
const resolution = resolveEntity(name, node, {
|
|
538
|
+
...ctx,
|
|
539
|
+
diagnostics: failures
|
|
540
|
+
});
|
|
541
|
+
references.set(node, resolution);
|
|
542
|
+
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
543
|
+
return {
|
|
544
|
+
matched: resolution.kind !== "unresolved",
|
|
545
|
+
references,
|
|
546
|
+
diagnostics
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
case "fieldRef": {
|
|
550
|
+
const node = expression.syntax;
|
|
551
|
+
const name = IdentifierAst.cast(node)?.name();
|
|
552
|
+
if (name === void 0 || modelContext === void 0) return {
|
|
553
|
+
matched: false,
|
|
554
|
+
references,
|
|
555
|
+
diagnostics
|
|
556
|
+
};
|
|
557
|
+
const failures = [];
|
|
558
|
+
const resolution = resolveOwnerField(name, node, {
|
|
559
|
+
...modelContext,
|
|
560
|
+
diagnostics: failures
|
|
561
|
+
});
|
|
562
|
+
references.set(node, resolution);
|
|
563
|
+
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
564
|
+
return {
|
|
565
|
+
matched: resolution.kind !== "unresolved",
|
|
566
|
+
references,
|
|
567
|
+
diagnostics
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
case "referencedFieldRef": {
|
|
571
|
+
const node = expression.syntax;
|
|
572
|
+
const name = IdentifierAst.cast(node)?.name();
|
|
573
|
+
if (name === void 0 || modelContext === void 0) return {
|
|
574
|
+
matched: false,
|
|
575
|
+
references,
|
|
576
|
+
diagnostics
|
|
577
|
+
};
|
|
578
|
+
const failures = [];
|
|
579
|
+
const resolution = resolveReferencedField(name, node, {
|
|
580
|
+
...modelContext,
|
|
581
|
+
diagnostics: failures
|
|
582
|
+
});
|
|
583
|
+
references.set(node, resolution);
|
|
584
|
+
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
585
|
+
return {
|
|
586
|
+
matched: resolution.kind !== "unresolved",
|
|
587
|
+
references,
|
|
588
|
+
diagnostics
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
default: return {
|
|
592
|
+
matched: true,
|
|
593
|
+
references,
|
|
594
|
+
diagnostics
|
|
595
|
+
};
|
|
216
596
|
}
|
|
217
|
-
return ok(value);
|
|
218
|
-
}
|
|
219
|
-
function parseArgValue(arg, argType, ctx) {
|
|
220
|
-
const value = arg.value();
|
|
221
|
-
if (value === void 0) return notOk([diagnostic("Attribute argument is missing a value", ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]);
|
|
222
|
-
return argType.parse(value, ctx);
|
|
223
597
|
}
|
|
224
|
-
function
|
|
225
|
-
|
|
598
|
+
function recordValues(expression) {
|
|
599
|
+
const record = ObjectLiteralExprAst.cast(expression.syntax);
|
|
600
|
+
if (record === void 0) return void 0;
|
|
601
|
+
return (function* () {
|
|
602
|
+
for (const field of record.fields()) {
|
|
603
|
+
const value = field.value();
|
|
604
|
+
if (value !== void 0) yield value;
|
|
605
|
+
}
|
|
606
|
+
})();
|
|
226
607
|
}
|
|
227
|
-
function
|
|
608
|
+
function bindAttributes(holder, attributes, specs, instantiate, ctx) {
|
|
609
|
+
const declared = holder.node.attributes();
|
|
610
|
+
const nodes = Array.from(declared);
|
|
611
|
+
const level = holder.kind === "field" ? "field" : "model";
|
|
612
|
+
attributes.forEach((attribute, index) => {
|
|
613
|
+
const factory = own(specs, attribute.name);
|
|
614
|
+
if (factory === void 0) {
|
|
615
|
+
const diagnostic = ctx.describeUnsupportedAttribute?.({
|
|
616
|
+
attribute,
|
|
617
|
+
level,
|
|
618
|
+
owner: ctx.owner,
|
|
619
|
+
field: level === "field" ? ctx.field : void 0
|
|
620
|
+
});
|
|
621
|
+
if (diagnostic !== void 0) ctx.diagnostics.push(diagnostic);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
const spec = instantiate(factory);
|
|
625
|
+
if (spec === void 0) return;
|
|
626
|
+
const nameNode = nodes[index]?.name()?.syntax;
|
|
627
|
+
if (nameNode !== void 0) ctx.references.set(nameNode, {
|
|
628
|
+
kind: "attribute",
|
|
629
|
+
symbol: {
|
|
630
|
+
kind: "attribute",
|
|
631
|
+
name: attribute.name,
|
|
632
|
+
level,
|
|
633
|
+
spec
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
bindArguments(attribute, spec, ctx, ctx);
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
function bindArguments(attribute, spec, ctx, modelContext) {
|
|
640
|
+
let positional = 0;
|
|
641
|
+
for (const arg of attribute.args) {
|
|
642
|
+
const parameter = argumentParameter(spec, arg.name, arg.name === void 0 ? positional++ : positional);
|
|
643
|
+
if (parameter === void 0 || arg.expression === void 0) continue;
|
|
644
|
+
bindExpression(parameter.type, arg.expression, ctx, modelContext);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
function argumentParameter(spec, name, position) {
|
|
648
|
+
if (name === void 0) return spec.positional?.[position];
|
|
649
|
+
return spec.named === void 0 ? void 0 : own(spec.named, name);
|
|
650
|
+
}
|
|
651
|
+
function resolveOwnerField(name, node, ctx) {
|
|
652
|
+
const field = ctx.owner.fields[name];
|
|
653
|
+
if (field !== void 0) return {
|
|
654
|
+
kind: "field",
|
|
655
|
+
symbol: field
|
|
656
|
+
};
|
|
657
|
+
report(`Cannot find field "${name}" on "${ctx.owner.name}"`, node, ctx, "field");
|
|
658
|
+
return {
|
|
659
|
+
kind: "unresolved",
|
|
660
|
+
name
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function resolveReferencedField(name, node, ctx) {
|
|
664
|
+
const declaring = ctx.field;
|
|
665
|
+
if (declaring === void 0) return {
|
|
666
|
+
kind: "unresolved",
|
|
667
|
+
name
|
|
668
|
+
};
|
|
669
|
+
if (declaring.typeContractSpaceId !== void 0) return { kind: "crossSpace" };
|
|
670
|
+
const typeNode = typeReferenceNode(declaring);
|
|
671
|
+
const field = targetFields(typeNode === void 0 ? void 0 : ctx.references.get(typeNode))?.[name];
|
|
672
|
+
if (field !== void 0) return {
|
|
673
|
+
kind: "field",
|
|
674
|
+
symbol: field
|
|
675
|
+
};
|
|
676
|
+
report(`Cannot find field "${name}" on the type of "${ctx.owner.name}.${declaring.name}"`, node, ctx, "field");
|
|
677
|
+
return {
|
|
678
|
+
kind: "unresolved",
|
|
679
|
+
name
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function targetFields(target) {
|
|
683
|
+
if (target === void 0) return void 0;
|
|
684
|
+
if (target.kind === "model" || target.kind === "compositeType") return target.symbol.fields;
|
|
685
|
+
}
|
|
686
|
+
function resolveEntity(name, node, ctx) {
|
|
687
|
+
const found = ctx.scope.lookup(name);
|
|
688
|
+
if (found === void 0) {
|
|
689
|
+
report(`Cannot find entity "${name}"`, node, ctx, "entity");
|
|
690
|
+
return {
|
|
691
|
+
kind: "unresolved",
|
|
692
|
+
name
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
return found;
|
|
696
|
+
}
|
|
697
|
+
function report(message, node, ctx, reference) {
|
|
698
|
+
ctx.diagnostics.push({
|
|
699
|
+
code: PSL_UNRESOLVED_REFERENCE,
|
|
700
|
+
message,
|
|
701
|
+
data: { reference },
|
|
702
|
+
...diagnosticSource(ctx.sources, node).at()
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
function resolveTypeReference(reference, scope, describeUnresolved) {
|
|
706
|
+
if (reference === void 0 || reference.isOverQualified()) return void 0;
|
|
707
|
+
if (reference.space() !== void 0) return { resolution: { kind: "crossSpace" } };
|
|
708
|
+
const name = reference.identifier()?.name();
|
|
709
|
+
if (name === void 0 || name === "") return void 0;
|
|
710
|
+
const namespaceId = reference.namespace()?.name();
|
|
711
|
+
const found = namespaceId === void 0 ? scope.lookup(name) : qualifiedMember(namespaceId, name, scope);
|
|
712
|
+
if (found === void 0) {
|
|
713
|
+
const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
|
|
714
|
+
const message = describeUnresolved?.(written) ?? `Cannot find type "${written}"`;
|
|
715
|
+
return {
|
|
716
|
+
resolution: {
|
|
717
|
+
kind: "unresolved",
|
|
718
|
+
name: written
|
|
719
|
+
},
|
|
720
|
+
message,
|
|
721
|
+
name: written
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
if ("badQualifier" in found) return {
|
|
725
|
+
resolution: {
|
|
726
|
+
kind: "unresolved",
|
|
727
|
+
name: found.qualifier
|
|
728
|
+
},
|
|
729
|
+
message: found.badQualifier,
|
|
730
|
+
name: found.qualifier
|
|
731
|
+
};
|
|
732
|
+
if (found.kind === "namespace" || found.kind === "contributedNamespace") {
|
|
733
|
+
const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
|
|
734
|
+
return {
|
|
735
|
+
resolution: found,
|
|
736
|
+
message: `"${written}" is a namespace; a type reference must name a model, composite type, enum, or named type`,
|
|
737
|
+
name: written
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
return { resolution: found };
|
|
741
|
+
}
|
|
742
|
+
function qualifiedMember(namespaceId, name, scope) {
|
|
743
|
+
const qualifier = scope.lookup(namespaceId);
|
|
744
|
+
if (qualifier === void 0) return void 0;
|
|
745
|
+
if (!isNamespaceLike(qualifier)) return {
|
|
746
|
+
badQualifier: `"${namespaceId}" is ${describeQualifier(qualifier)}, not a namespace`,
|
|
747
|
+
qualifier: namespaceId
|
|
748
|
+
};
|
|
749
|
+
return lookupMember(qualifier, name);
|
|
750
|
+
}
|
|
751
|
+
function describeQualifier(resolution) {
|
|
752
|
+
switch (resolution.kind) {
|
|
753
|
+
case "model": return "a model";
|
|
754
|
+
case "compositeType": return "a composite type";
|
|
755
|
+
case "namedType": return "a named type";
|
|
756
|
+
case "block": return `${resolution.symbol.keyword === "enum" ? "an" : "a"} ${resolution.symbol.keyword}`;
|
|
757
|
+
default: return "a scalar type";
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
function own(record, name) {
|
|
761
|
+
return Object.hasOwn(record, name) ? record[name] : void 0;
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Owns duplicate-declaration detection for all PSL scopes; downstream consumers
|
|
765
|
+
* should consume first-wins symbols rather than re-emitting duplicate diagnostics.
|
|
766
|
+
*/
|
|
767
|
+
function buildSymbolTable(options) {
|
|
768
|
+
const { documents, sources } = options;
|
|
769
|
+
const diagnostics = [];
|
|
770
|
+
const namespaces = Object.create(null);
|
|
771
|
+
const namedTypes = Object.create(null);
|
|
772
|
+
const blocks = Object.create(null);
|
|
773
|
+
const models = Object.create(null);
|
|
774
|
+
const compositeTypes = Object.create(null);
|
|
775
|
+
const topLevelNames = /* @__PURE__ */ new Set();
|
|
776
|
+
for (const document of documents) {
|
|
777
|
+
const sourceFile = sources.sourceFileFor(document.syntax);
|
|
778
|
+
const claim = (taken, name) => {
|
|
779
|
+
const text = name?.name();
|
|
780
|
+
if (text === void 0) return void 0;
|
|
781
|
+
if (taken.has(text)) {
|
|
782
|
+
const range = nameRange(name, sources);
|
|
783
|
+
if (range) diagnostics.push({
|
|
784
|
+
code: "PSL_DUPLICATE_DECLARATION",
|
|
785
|
+
message: `Duplicate declaration of "${text}"`,
|
|
786
|
+
filename: sourceFile.filename,
|
|
787
|
+
range
|
|
788
|
+
});
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
taken.add(text);
|
|
792
|
+
return text;
|
|
793
|
+
};
|
|
794
|
+
for (const declaration of document.declarations()) if (declaration instanceof ModelDeclarationAst) {
|
|
795
|
+
const name = claim(topLevelNames, declaration.name());
|
|
796
|
+
if (name !== void 0) models[name] = buildModel(name, declaration, sources, diagnostics);
|
|
797
|
+
} else if (declaration instanceof CompositeTypeDeclarationAst) {
|
|
798
|
+
const name = claim(topLevelNames, declaration.name());
|
|
799
|
+
if (name !== void 0) compositeTypes[name] = buildCompositeType(name, declaration, sources, diagnostics);
|
|
800
|
+
} else if (declaration instanceof GenericBlockDeclarationAst) {
|
|
801
|
+
const name = claim(topLevelNames, declaration.name());
|
|
802
|
+
if (name !== void 0) blocks[name] = buildBlock(name, declaration, sources);
|
|
803
|
+
} else if (declaration instanceof NamespaceDeclarationAst) {
|
|
804
|
+
const declaredName = declaration.name()?.name();
|
|
805
|
+
if (declaredName === void 0) continue;
|
|
806
|
+
let namespace = namespaces[declaredName];
|
|
807
|
+
if (namespace === void 0) {
|
|
808
|
+
const name = claim(topLevelNames, declaration.name());
|
|
809
|
+
if (name === void 0) continue;
|
|
810
|
+
namespace = {
|
|
811
|
+
kind: "namespace",
|
|
812
|
+
name,
|
|
813
|
+
declarations: [{
|
|
814
|
+
node: declaration,
|
|
815
|
+
span: nodePslSpan(declaration.syntax, sources)
|
|
816
|
+
}],
|
|
817
|
+
models: Object.create(null),
|
|
818
|
+
compositeTypes: Object.create(null),
|
|
819
|
+
blocks: Object.create(null)
|
|
820
|
+
};
|
|
821
|
+
namespaces[name] = namespace;
|
|
822
|
+
} else namespace.declarations.push({
|
|
823
|
+
node: declaration,
|
|
824
|
+
span: nodePslSpan(declaration.syntax, sources)
|
|
825
|
+
});
|
|
826
|
+
extendNamespace(namespace, declaration, diagnostics, sources);
|
|
827
|
+
} else if (declaration instanceof TypesBlockAst) for (const binding of declaration.declarations()) {
|
|
828
|
+
const name = claim(topLevelNames, binding.name());
|
|
829
|
+
if (name === void 0) continue;
|
|
830
|
+
const resolved = resolveNamedTypeBinding(binding, sources);
|
|
831
|
+
namedTypes[name] = {
|
|
832
|
+
kind: "namedType",
|
|
833
|
+
name,
|
|
834
|
+
node: binding,
|
|
835
|
+
span: nodePslSpan(binding.syntax, sources),
|
|
836
|
+
...resolved
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
}
|
|
228
840
|
return {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
841
|
+
symbolTable: { topLevel: {
|
|
842
|
+
namespaces,
|
|
843
|
+
namedTypes,
|
|
844
|
+
blocks,
|
|
845
|
+
models,
|
|
846
|
+
compositeTypes
|
|
847
|
+
} },
|
|
848
|
+
diagnostics
|
|
232
849
|
};
|
|
233
850
|
}
|
|
234
|
-
function
|
|
851
|
+
function buildModel(name, node, sources, diagnostics) {
|
|
235
852
|
return {
|
|
236
|
-
kind: "
|
|
237
|
-
label: `${name}()`,
|
|
853
|
+
kind: "model",
|
|
238
854
|
name,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const span = nodePslSpan(guard.value.syntax, ctx.sources);
|
|
244
|
-
const bound = interpretArgs(guard.value.args(), {
|
|
245
|
-
name,
|
|
246
|
-
positional: sig.positional ?? [],
|
|
247
|
-
named: sig.named ?? {}
|
|
248
|
-
}, ctx, span, guard.value.syntax);
|
|
249
|
-
if (!bound.ok) return notOk(bound.failure);
|
|
250
|
-
return ok({
|
|
251
|
-
fn: name,
|
|
252
|
-
span,
|
|
253
|
-
args: bound.value
|
|
254
|
-
});
|
|
255
|
-
}
|
|
855
|
+
node,
|
|
856
|
+
span: nodePslSpan(node.syntax, sources),
|
|
857
|
+
fields: buildFields(name, node.fields(), sources, diagnostics),
|
|
858
|
+
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
256
859
|
};
|
|
257
860
|
}
|
|
258
|
-
function
|
|
259
|
-
const call = FunctionCallAst.cast(arg.syntax);
|
|
260
|
-
if (call === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
261
|
-
const qname = call.name();
|
|
262
|
-
if (qname === void 0 || qname.dot() !== void 0 || qname.colon() !== void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
263
|
-
const calleeName = qname.identifier()?.token()?.text;
|
|
264
|
-
if (calleeName === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
265
|
-
if (calleeName !== name) return notOk([leafDiagnostic(ctx, arg, `Expected ${name}()`)]);
|
|
266
|
-
return ok(call);
|
|
267
|
-
}
|
|
268
|
-
function identifier(name, options) {
|
|
269
|
-
const label = name ?? "identifier";
|
|
861
|
+
function buildCompositeType(name, node, sources, diagnostics) {
|
|
270
862
|
return {
|
|
271
|
-
kind: "
|
|
272
|
-
label,
|
|
863
|
+
kind: "compositeType",
|
|
273
864
|
name,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
|
|
279
|
-
}
|
|
865
|
+
node,
|
|
866
|
+
span: nodePslSpan(node.syntax, sources),
|
|
867
|
+
fields: buildFields(name, node.fields(), sources, diagnostics),
|
|
868
|
+
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
280
869
|
};
|
|
281
870
|
}
|
|
282
|
-
function
|
|
283
|
-
const min = opts?.min;
|
|
284
|
-
const max = opts?.max;
|
|
871
|
+
function buildBlock(name, node, sources) {
|
|
285
872
|
return {
|
|
286
|
-
kind: "
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const literal = NumberLiteralExprAst.cast(arg.syntax);
|
|
292
|
-
if (literal !== void 0) {
|
|
293
|
-
const value = literal.value();
|
|
294
|
-
if (value !== void 0 && Number.isInteger(value)) {
|
|
295
|
-
if ((min === void 0 || value >= min) && (max === void 0 || value <= max)) return ok(value);
|
|
296
|
-
return notOk([leafDiagnostic(ctx, arg, rangeMessage(min, max))]);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected an integer literal")]);
|
|
300
|
-
}
|
|
873
|
+
kind: "block",
|
|
874
|
+
name,
|
|
875
|
+
keyword: node.keyword()?.text ?? "",
|
|
876
|
+
node,
|
|
877
|
+
span: nodePslSpan(node.syntax, sources)
|
|
301
878
|
};
|
|
302
879
|
}
|
|
303
|
-
function
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
parse: (arg, ctx) => {
|
|
318
|
-
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
319
|
-
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a JSON object string")]);
|
|
320
|
-
const raw = literal.value();
|
|
321
|
-
if (raw !== void 0) try {
|
|
322
|
-
const parsed = JSON.parse(raw);
|
|
323
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return ok(blindCast(parsed));
|
|
324
|
-
} catch {}
|
|
325
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected a valid JSON object")]);
|
|
880
|
+
function extendNamespace(namespace, node, diagnostics, sources) {
|
|
881
|
+
const { models, compositeTypes, blocks } = namespace;
|
|
882
|
+
for (const member of node.declarations()) {
|
|
883
|
+
const memberName = member.name()?.name();
|
|
884
|
+
if (memberName === void 0) continue;
|
|
885
|
+
if (Object.hasOwn(models, memberName) || Object.hasOwn(compositeTypes, memberName) || Object.hasOwn(blocks, memberName)) {
|
|
886
|
+
const range = nameRange(member.name(), sources);
|
|
887
|
+
if (range) diagnostics.push({
|
|
888
|
+
code: "PSL_DUPLICATE_DECLARATION",
|
|
889
|
+
message: `Duplicate declaration of "${memberName}"`,
|
|
890
|
+
filename: sources.sourceFileFor(member.syntax).filename,
|
|
891
|
+
range
|
|
892
|
+
});
|
|
893
|
+
continue;
|
|
326
894
|
}
|
|
327
|
-
|
|
895
|
+
if (member instanceof ModelDeclarationAst) models[memberName] = buildModel(memberName, member, sources, diagnostics);
|
|
896
|
+
else if (member instanceof CompositeTypeDeclarationAst) compositeTypes[memberName] = buildCompositeType(memberName, member, sources, diagnostics);
|
|
897
|
+
else if (member instanceof GenericBlockDeclarationAst) blocks[memberName] = buildBlock(memberName, member, sources);
|
|
898
|
+
}
|
|
328
899
|
}
|
|
329
|
-
function
|
|
330
|
-
const
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
for (const element of literal.elements()) {
|
|
345
|
-
count += 1;
|
|
346
|
-
const result = of.parse(element, ctx);
|
|
347
|
-
if (result.ok) parsed.push({
|
|
348
|
-
node: element,
|
|
349
|
-
value: result.value
|
|
350
|
-
});
|
|
351
|
-
outcome = and(outcome, result);
|
|
352
|
-
}
|
|
353
|
-
if (!allowEmpty && count === 0) outcome = and(outcome, notOk([leafDiagnostic(ctx, arg, "Expected a non-empty list")]));
|
|
354
|
-
if (unique) {
|
|
355
|
-
const seen = /* @__PURE__ */ new Set();
|
|
356
|
-
for (const { node, value } of parsed) if (seen.has(value)) outcome = and(outcome, notOk([leafDiagnostic(ctx, node, "Duplicate list entry")]));
|
|
357
|
-
else seen.add(value);
|
|
358
|
-
}
|
|
359
|
-
if (!outcome.ok) return notOk(outcome.failure);
|
|
360
|
-
return ok(parsed.map((entry) => entry.value));
|
|
900
|
+
function buildFields(ownerName, fields, sources, diagnostics) {
|
|
901
|
+
const result = Object.create(null);
|
|
902
|
+
for (const field of fields) {
|
|
903
|
+
const nameNode = field.name();
|
|
904
|
+
const name = nameNode?.name();
|
|
905
|
+
if (name === void 0) continue;
|
|
906
|
+
if (Object.hasOwn(result, name)) {
|
|
907
|
+
const range = nameRange(nameNode, sources);
|
|
908
|
+
if (range) diagnostics.push({
|
|
909
|
+
code: "PSL_DUPLICATE_DECLARATION",
|
|
910
|
+
message: `Duplicate declaration of "${name}"`,
|
|
911
|
+
filename: sources.sourceFileFor(field.syntax).filename,
|
|
912
|
+
range
|
|
913
|
+
});
|
|
914
|
+
continue;
|
|
361
915
|
}
|
|
362
|
-
|
|
916
|
+
result[name] = buildField(ownerName, name, field, sources, diagnostics);
|
|
917
|
+
}
|
|
918
|
+
return result;
|
|
363
919
|
}
|
|
364
|
-
function
|
|
365
|
-
const
|
|
920
|
+
function buildField(ownerName, name, node, sources, diagnostics) {
|
|
921
|
+
const attributes = readResolvedAttributes(node.attributes(), sources);
|
|
922
|
+
const span = nodePslSpan(node.syntax, sources);
|
|
923
|
+
const annotation = node.typeAnnotation();
|
|
924
|
+
const typeName = annotation?.name();
|
|
925
|
+
if (typeName?.isOverQualified()) {
|
|
926
|
+
const path = typeName.path();
|
|
927
|
+
diagnostics.push({
|
|
928
|
+
code: "PSL_INVALID_QUALIFIED_TYPE",
|
|
929
|
+
message: `Field "${ownerName}.${name}" has an invalid qualified type "${path.join(".")}"; use at most one namespace qualifier (e.g. "ns.TypeName")`,
|
|
930
|
+
filename: sources.sourceFileFor(typeName.syntax).filename,
|
|
931
|
+
range: nodeRange(typeName.syntax, sources)
|
|
932
|
+
});
|
|
933
|
+
return {
|
|
934
|
+
kind: "field",
|
|
935
|
+
name,
|
|
936
|
+
node,
|
|
937
|
+
span,
|
|
938
|
+
typeName: path[path.length - 1] ?? "",
|
|
939
|
+
optional: false,
|
|
940
|
+
list: false,
|
|
941
|
+
elementOptional: false,
|
|
942
|
+
malformedType: true,
|
|
943
|
+
attributes
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
const typeConstructor = annotation?.isConstructor() ? readResolvedConstructorCall(annotation, sources) : void 0;
|
|
947
|
+
const typeNamespaceId = typeName?.namespace()?.name();
|
|
948
|
+
const typeContractSpaceId = typeName?.space()?.name();
|
|
366
949
|
return {
|
|
367
|
-
kind: "
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
if (!rejection.ok && rejection.failure.length === 0) return notOk([]);
|
|
380
|
-
return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
|
|
381
|
-
}
|
|
950
|
+
kind: "field",
|
|
951
|
+
name,
|
|
952
|
+
node,
|
|
953
|
+
span,
|
|
954
|
+
typeName: typeName?.identifier()?.name() ?? "",
|
|
955
|
+
...typeNamespaceId !== void 0 ? { typeNamespaceId } : {},
|
|
956
|
+
...typeContractSpaceId !== void 0 ? { typeContractSpaceId } : {},
|
|
957
|
+
optional: annotation?.isOptional() ?? false,
|
|
958
|
+
list: annotation?.isList() ?? false,
|
|
959
|
+
elementOptional: annotation?.isElementOptional() ?? false,
|
|
960
|
+
...typeConstructor !== void 0 ? { typeConstructor } : {},
|
|
961
|
+
attributes
|
|
382
962
|
};
|
|
383
963
|
}
|
|
384
|
-
function
|
|
964
|
+
function resolveNamedTypeBinding(node, sources) {
|
|
965
|
+
const annotation = node.typeAnnotation();
|
|
966
|
+
const isConstructor = annotation?.isConstructor() ?? false;
|
|
967
|
+
const baseType = annotation?.name()?.identifier()?.name();
|
|
968
|
+
const typeConstructor = readResolvedConstructorCall(annotation, sources);
|
|
385
969
|
return {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const literal = ObjectLiteralExprAst.cast(arg.syntax);
|
|
391
|
-
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected an object literal")]);
|
|
392
|
-
const entries = [];
|
|
393
|
-
const keys = /* @__PURE__ */ new Set();
|
|
394
|
-
let outcome = okVoid();
|
|
395
|
-
for (const field of Array.from(literal.fields())) {
|
|
396
|
-
const key = field.keyName();
|
|
397
|
-
if (key === void 0) {
|
|
398
|
-
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, "Expected a key")]));
|
|
399
|
-
continue;
|
|
400
|
-
}
|
|
401
|
-
const value = field.value();
|
|
402
|
-
if (value === void 0) {
|
|
403
|
-
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Expected a value for key "${key}"`)]));
|
|
404
|
-
continue;
|
|
405
|
-
}
|
|
406
|
-
const parsed = of.parse(value, ctx);
|
|
407
|
-
if (!parsed.ok) {
|
|
408
|
-
outcome = and(outcome, parsed);
|
|
409
|
-
continue;
|
|
410
|
-
}
|
|
411
|
-
if (keys.has(key)) {
|
|
412
|
-
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Duplicate key "${key}"`)]));
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
keys.add(key);
|
|
416
|
-
entries.push([key, parsed.value]);
|
|
417
|
-
}
|
|
418
|
-
if (!outcome.ok) return notOk(outcome.failure);
|
|
419
|
-
return ok(Object.fromEntries(entries));
|
|
420
|
-
}
|
|
970
|
+
isConstructor,
|
|
971
|
+
...!isConstructor && baseType !== void 0 ? { baseType } : {},
|
|
972
|
+
...typeConstructor !== void 0 ? { typeConstructor } : {},
|
|
973
|
+
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
421
974
|
};
|
|
422
975
|
}
|
|
423
|
-
function
|
|
424
|
-
if (
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
430
|
-
if (literal !== void 0) {
|
|
431
|
-
const parsed = literal.value();
|
|
432
|
-
if (parsed !== void 0) return ok(parsed);
|
|
433
|
-
}
|
|
434
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected a string literal")]);
|
|
435
|
-
}
|
|
976
|
+
function nameRange(name, sources) {
|
|
977
|
+
if (name === void 0) return void 0;
|
|
978
|
+
const sourceFile = sources.sourceFileFor(name.syntax);
|
|
979
|
+
for (const token of name.syntax.tokens()) if (token.kind === "Ident") return {
|
|
980
|
+
start: sourceFile.positionAt(token.offset),
|
|
981
|
+
end: sourceFile.positionAt(token.offset + token.text.length)
|
|
436
982
|
};
|
|
983
|
+
}
|
|
984
|
+
function nodeRange(node, sources) {
|
|
985
|
+
const sourceFile = sources.sourceFileFor(node);
|
|
986
|
+
const start = node.offset;
|
|
987
|
+
const end = start + node.green.textLength;
|
|
437
988
|
return {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
value,
|
|
441
|
-
parse: (arg, ctx) => {
|
|
442
|
-
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
443
|
-
if (literal !== void 0) {
|
|
444
|
-
if (literal.value() === value) return ok(value);
|
|
445
|
-
}
|
|
446
|
-
return notOk([leafDiagnostic(ctx, arg, `Expected ${JSON.stringify(value)}`)]);
|
|
447
|
-
}
|
|
989
|
+
start: sourceFile.positionAt(start),
|
|
990
|
+
end: sourceFile.positionAt(end)
|
|
448
991
|
};
|
|
449
992
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
get alternatives() {
|
|
455
|
-
return composed.alternatives;
|
|
456
|
-
},
|
|
457
|
-
parse: (arg, ctx) => composed.parse(arg, ctx)
|
|
458
|
-
};
|
|
459
|
-
const composed = oneOf(str(), finiteNumber(), bool(), jsonNull(), list(self), record(self));
|
|
460
|
-
return self;
|
|
993
|
+
//#endregion
|
|
994
|
+
//#region ../../../1-framework/2-authoring/psl-parser/dist/index.mjs
|
|
995
|
+
function getPositionalArgument(attribute, index = 0) {
|
|
996
|
+
return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
|
|
461
997
|
}
|
|
462
|
-
function
|
|
998
|
+
function parseQuotedStringLiteral(value) {
|
|
999
|
+
const match = value.trim().match(/^(['"])(.*)\1$/);
|
|
1000
|
+
if (!match) return void 0;
|
|
1001
|
+
return match[2] ?? "";
|
|
1002
|
+
}
|
|
1003
|
+
function blockAttribute(name, config) {
|
|
463
1004
|
return {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
return ok(value);
|
|
471
|
-
}
|
|
1005
|
+
level: "block",
|
|
1006
|
+
name,
|
|
1007
|
+
documentation: config.documentation,
|
|
1008
|
+
positional: config.positional ?? [],
|
|
1009
|
+
named: config.named ?? {},
|
|
1010
|
+
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
472
1011
|
};
|
|
473
1012
|
}
|
|
474
|
-
|
|
1013
|
+
const ATTRIBUTE_DIAGNOSTIC_CODE = "PSL_INVALID_ATTRIBUTE_SYNTAX";
|
|
1014
|
+
function leafDiagnostic(ctx, node, message, code = ATTRIBUTE_DIAGNOSTIC_CODE) {
|
|
475
1015
|
return {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if (IdentifierAst.cast(arg.syntax)?.name() === "null") return ok(null);
|
|
480
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected null")]);
|
|
481
|
-
}
|
|
1016
|
+
code,
|
|
1017
|
+
message,
|
|
1018
|
+
...diagnosticSource(ctx.sources, node.syntax).at(nodePslSpan(node.syntax, ctx.sources))
|
|
482
1019
|
};
|
|
483
1020
|
}
|
|
484
|
-
function
|
|
485
|
-
if (value === void 0) return {
|
|
486
|
-
kind: "num",
|
|
487
|
-
label: "number",
|
|
488
|
-
value: void 0,
|
|
489
|
-
parse: (arg, ctx) => {
|
|
490
|
-
const literal = NumberLiteralExprAst.cast(arg.syntax);
|
|
491
|
-
if (literal !== void 0) {
|
|
492
|
-
const parsed = literal.value();
|
|
493
|
-
if (parsed !== void 0) return ok(parsed);
|
|
494
|
-
}
|
|
495
|
-
return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
|
|
496
|
-
}
|
|
497
|
-
};
|
|
1021
|
+
function bool() {
|
|
498
1022
|
return {
|
|
499
|
-
kind: "
|
|
500
|
-
label:
|
|
501
|
-
value,
|
|
1023
|
+
kind: "bool",
|
|
1024
|
+
label: "boolean",
|
|
502
1025
|
parse: (arg, ctx) => {
|
|
503
|
-
const literal =
|
|
1026
|
+
const literal = BooleanLiteralExprAst.cast(arg.syntax);
|
|
504
1027
|
if (literal !== void 0) {
|
|
505
|
-
|
|
1028
|
+
const value = literal.value();
|
|
1029
|
+
if (value !== void 0) return ok(value);
|
|
506
1030
|
}
|
|
507
|
-
return notOk([leafDiagnostic(ctx, arg,
|
|
1031
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a boolean literal")]);
|
|
508
1032
|
}
|
|
509
1033
|
};
|
|
510
1034
|
}
|
|
511
|
-
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
1035
|
+
const references = /* @__PURE__ */ new WeakMap();
|
|
1036
|
+
function entityReference(resolution) {
|
|
1037
|
+
switch (resolution.kind) {
|
|
1038
|
+
case "model":
|
|
1039
|
+
case "compositeType":
|
|
1040
|
+
case "namedType":
|
|
1041
|
+
case "block": return interned(resolution.symbol, resolution.namespace);
|
|
1042
|
+
default: return;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
function interned(declaration, namespace) {
|
|
1046
|
+
const existing = references.get(declaration);
|
|
1047
|
+
if (existing !== void 0) return existing;
|
|
1048
|
+
const reference = {
|
|
1049
|
+
declaration,
|
|
1050
|
+
namespace
|
|
522
1051
|
};
|
|
1052
|
+
references.set(declaration, reference);
|
|
1053
|
+
return reference;
|
|
523
1054
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
1055
|
+
function matchesSelector(reference, expected) {
|
|
1056
|
+
const declaration = reference.declaration;
|
|
1057
|
+
if (declaration.kind !== expected.kind) return false;
|
|
1058
|
+
return expected.kind !== "block" || declaration.kind === "block" && declaration.keyword === expected.keyword;
|
|
1059
|
+
}
|
|
1060
|
+
function describeResolution(resolution) {
|
|
1061
|
+
switch (resolution.kind) {
|
|
1062
|
+
case "block": return resolution.symbol.keyword;
|
|
1063
|
+
case "contributedType": return "scalar type";
|
|
1064
|
+
case "crossSpace": return "cross-space reference";
|
|
1065
|
+
case "unresolved": return "unresolved name";
|
|
1066
|
+
default: return resolution.kind;
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
function entityRef(expected) {
|
|
1070
|
+
const label = `${expected.kind === "block" ? expected.keyword : expected.kind} reference`;
|
|
529
1071
|
return {
|
|
530
|
-
kind: "
|
|
531
|
-
label
|
|
532
|
-
|
|
533
|
-
documentation: options.documentation,
|
|
1072
|
+
kind: "entityRef",
|
|
1073
|
+
label,
|
|
1074
|
+
expected,
|
|
534
1075
|
parse: (arg, ctx) => {
|
|
535
|
-
const
|
|
536
|
-
if (
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
1076
|
+
const name = IdentifierAst.cast(arg.syntax)?.name();
|
|
1077
|
+
if (name === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
|
|
1078
|
+
const resolution = ctx.binder.symbolForNode(arg.syntax);
|
|
1079
|
+
if (resolution === void 0 || resolution.kind === "unresolved") return notOk([]);
|
|
1080
|
+
const reference = entityReference(resolution);
|
|
1081
|
+
if (reference === void 0 || !matchesSelector(reference, expected)) return notOk([leafDiagnostic(ctx, arg, `Expected ${label} "${name}", found ${describeResolution(resolution)}`)]);
|
|
1082
|
+
return ok(reference);
|
|
542
1083
|
}
|
|
543
1084
|
};
|
|
544
1085
|
}
|
|
545
|
-
function
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
1086
|
+
function parseFieldName(arg, ctx) {
|
|
1087
|
+
const identifier = IdentifierAst.cast(arg.syntax);
|
|
1088
|
+
if (identifier === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
|
|
1089
|
+
const name = identifier.name();
|
|
1090
|
+
if (name === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a field name")]);
|
|
1091
|
+
const resolution = ctx.binder.symbolForNode(arg.syntax);
|
|
1092
|
+
if (resolution === void 0) return notOk([]);
|
|
1093
|
+
if (resolution.kind === "field") return ok(resolution.symbol.name);
|
|
1094
|
+
if (resolution.kind === "crossSpace") return ok(name);
|
|
1095
|
+
return notOk([]);
|
|
554
1096
|
}
|
|
555
|
-
function
|
|
1097
|
+
function fieldRef() {
|
|
556
1098
|
return {
|
|
557
|
-
|
|
558
|
-
name,
|
|
559
|
-
|
|
560
|
-
positional: config.positional ?? [],
|
|
561
|
-
named: Object.assign(Object.create(null), config.named),
|
|
562
|
-
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
1099
|
+
kind: "fieldRef",
|
|
1100
|
+
label: "field name",
|
|
1101
|
+
parse: parseFieldName
|
|
563
1102
|
};
|
|
564
1103
|
}
|
|
565
|
-
function
|
|
566
|
-
if (rest.length === 0) return {
|
|
567
|
-
...type,
|
|
568
|
-
optional: true,
|
|
569
|
-
hasDefault: false
|
|
570
|
-
};
|
|
1104
|
+
function referencedFieldRef() {
|
|
571
1105
|
return {
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
defaultValue: rest[0]
|
|
1106
|
+
kind: "referencedFieldRef",
|
|
1107
|
+
label: "field name",
|
|
1108
|
+
parse: parseFieldName
|
|
576
1109
|
};
|
|
577
1110
|
}
|
|
578
|
-
function
|
|
579
|
-
|
|
580
|
-
}
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
1111
|
+
function interpretArgs(args, spec, ctx, span, sourceNode) {
|
|
1112
|
+
let outcome = okVoid();
|
|
1113
|
+
const output = {};
|
|
1114
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1115
|
+
let positionalSlot = 0;
|
|
1116
|
+
let reportedExcess = false;
|
|
1117
|
+
for (const arg of args) {
|
|
1118
|
+
const name = arg.name()?.name();
|
|
1119
|
+
let key;
|
|
1120
|
+
let param;
|
|
1121
|
+
if (name === void 0) {
|
|
1122
|
+
const posParam = spec.positional[positionalSlot];
|
|
1123
|
+
if (posParam === void 0) {
|
|
1124
|
+
if (!reportedExcess) {
|
|
1125
|
+
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received too many positional arguments`, ctx, span, sourceNode)]));
|
|
1126
|
+
reportedExcess = true;
|
|
1127
|
+
}
|
|
1128
|
+
continue;
|
|
1129
|
+
}
|
|
1130
|
+
positionalSlot += 1;
|
|
1131
|
+
key = posParam.key;
|
|
1132
|
+
param = posParam.type;
|
|
1133
|
+
} else {
|
|
1134
|
+
const namedParam = Object.hasOwn(spec.named, name) ? spec.named[name] : void 0;
|
|
1135
|
+
if (namedParam === void 0) {
|
|
1136
|
+
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received unknown argument "${name}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
key = name;
|
|
1140
|
+
param = namedParam.type;
|
|
592
1141
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
return created;
|
|
596
|
-
}
|
|
597
|
-
function collect(namespace, prefix) {
|
|
598
|
-
const members = /* @__PURE__ */ new Map();
|
|
599
|
-
for (const [name, value] of Object.entries(namespace)) {
|
|
600
|
-
const path = [...prefix, name];
|
|
601
|
-
members.set(name, isAuthoringTypeConstructorDescriptor(value) ? {
|
|
602
|
-
kind: "contributedType",
|
|
603
|
-
name,
|
|
604
|
-
path,
|
|
605
|
-
descriptor: value
|
|
606
|
-
} : {
|
|
607
|
-
kind: "contributedNamespace",
|
|
608
|
-
name,
|
|
609
|
-
path,
|
|
610
|
-
members: collect(value, path)
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
return members;
|
|
614
|
-
}
|
|
615
|
-
function findBlockDescriptor(descriptors, keyword) {
|
|
616
|
-
if (descriptors === void 0) return void 0;
|
|
617
|
-
for (const value of Object.values(descriptors)) {
|
|
618
|
-
if (value === void 0) continue;
|
|
619
|
-
if (isAuthoringPslBlockDescriptor(value)) {
|
|
620
|
-
if (value.keyword === keyword) return value;
|
|
1142
|
+
if (seen.has(key)) {
|
|
1143
|
+
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" received duplicate argument "${key}"`, ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]));
|
|
621
1144
|
continue;
|
|
622
1145
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
function* recordNames(...records) {
|
|
628
|
-
for (const record of records) yield* Object.keys(record);
|
|
629
|
-
}
|
|
630
|
-
var Scope = class {
|
|
631
|
-
parent;
|
|
632
|
-
constructor(parent) {
|
|
633
|
-
this.parent = parent;
|
|
1146
|
+
seen.add(key);
|
|
1147
|
+
const result = parseArgValue(arg, param, ctx);
|
|
1148
|
+
if (result.ok) output[key] = result.value;
|
|
1149
|
+
outcome = and(outcome, result);
|
|
634
1150
|
}
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
1151
|
+
const finalized = /* @__PURE__ */ new Set();
|
|
1152
|
+
const finalizeAbsentKey = (key, positionalParam, namedParam) => {
|
|
1153
|
+
if (finalized.has(key) || seen.has(key)) return;
|
|
1154
|
+
finalized.add(key);
|
|
1155
|
+
const effective = namedParam ?? positionalParam;
|
|
1156
|
+
if (effective === void 0) return;
|
|
1157
|
+
if (isOptionalArgType(effective)) {
|
|
1158
|
+
if (effective.hasDefault) output[key] = effective.defaultValue;
|
|
1159
|
+
return;
|
|
642
1160
|
}
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
};
|
|
646
|
-
function contributedResolution(member) {
|
|
647
|
-
return member.kind === "contributedType" ? {
|
|
648
|
-
kind: "contributedType",
|
|
649
|
-
symbol: member
|
|
650
|
-
} : {
|
|
651
|
-
kind: "contributedNamespace",
|
|
652
|
-
symbol: member
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
function namespaceMember(namespace, name) {
|
|
656
|
-
const model = namespace.models[name];
|
|
657
|
-
if (model !== void 0) return {
|
|
658
|
-
kind: "model",
|
|
659
|
-
symbol: model,
|
|
660
|
-
namespace
|
|
661
|
-
};
|
|
662
|
-
const compositeType = namespace.compositeTypes[name];
|
|
663
|
-
if (compositeType !== void 0) return {
|
|
664
|
-
kind: "compositeType",
|
|
665
|
-
symbol: compositeType,
|
|
666
|
-
namespace
|
|
667
|
-
};
|
|
668
|
-
const block = namespace.blocks[name];
|
|
669
|
-
if (block !== void 0) return {
|
|
670
|
-
kind: "block",
|
|
671
|
-
symbol: block,
|
|
672
|
-
namespace
|
|
1161
|
+
outcome = and(outcome, notOk([diagnostic(`Attribute "${spec.name}" is missing required argument "${key}"`, ctx, span, sourceNode)]));
|
|
673
1162
|
};
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
constructor(registry) {
|
|
678
|
-
super(void 0);
|
|
679
|
-
this.#registry = registry;
|
|
680
|
-
}
|
|
681
|
-
lookup(name) {
|
|
682
|
-
const member = this.#registry.lookup(name);
|
|
683
|
-
return member === void 0 ? void 0 : contributedResolution(member);
|
|
684
|
-
}
|
|
685
|
-
*ownNames() {
|
|
686
|
-
for (const [name] of this.#registry.entries()) yield name;
|
|
687
|
-
}
|
|
688
|
-
};
|
|
689
|
-
var DocumentScope = class extends Scope {
|
|
690
|
-
#records;
|
|
691
|
-
constructor(records, parent) {
|
|
692
|
-
super(parent);
|
|
693
|
-
this.#records = records;
|
|
694
|
-
}
|
|
695
|
-
lookup(name) {
|
|
696
|
-
const records = this.#records;
|
|
697
|
-
const model = records.models[name];
|
|
698
|
-
if (model !== void 0) return {
|
|
699
|
-
kind: "model",
|
|
700
|
-
symbol: model
|
|
701
|
-
};
|
|
702
|
-
const compositeType = records.compositeTypes[name];
|
|
703
|
-
if (compositeType !== void 0) return {
|
|
704
|
-
kind: "compositeType",
|
|
705
|
-
symbol: compositeType
|
|
706
|
-
};
|
|
707
|
-
const namedType = records.namedTypes[name];
|
|
708
|
-
if (namedType !== void 0) return {
|
|
709
|
-
kind: "namedType",
|
|
710
|
-
symbol: namedType
|
|
711
|
-
};
|
|
712
|
-
const block = records.blocks[name];
|
|
713
|
-
if (block !== void 0) return {
|
|
714
|
-
kind: "block",
|
|
715
|
-
symbol: block
|
|
716
|
-
};
|
|
717
|
-
const namespace = records.namespaces[name];
|
|
718
|
-
if (namespace !== void 0) return {
|
|
719
|
-
kind: "namespace",
|
|
720
|
-
symbol: namespace
|
|
721
|
-
};
|
|
722
|
-
return this.parent?.lookup(name);
|
|
723
|
-
}
|
|
724
|
-
ownNames() {
|
|
725
|
-
const records = this.#records;
|
|
726
|
-
return recordNames(records.models, records.compositeTypes, records.namedTypes, records.blocks, records.namespaces);
|
|
727
|
-
}
|
|
728
|
-
};
|
|
729
|
-
var NamespaceScope = class extends Scope {
|
|
730
|
-
#namespace;
|
|
731
|
-
constructor(namespace, parent) {
|
|
732
|
-
super(parent);
|
|
733
|
-
this.#namespace = namespace;
|
|
734
|
-
}
|
|
735
|
-
lookup(name) {
|
|
736
|
-
return namespaceMember(this.#namespace, name) ?? this.parent?.lookup(name);
|
|
737
|
-
}
|
|
738
|
-
ownNames() {
|
|
739
|
-
const namespace = this.#namespace;
|
|
740
|
-
return recordNames(namespace.models, namespace.compositeTypes, namespace.blocks);
|
|
1163
|
+
for (const param of spec.positional) {
|
|
1164
|
+
const namedParam = Object.hasOwn(spec.named, param.key) ? spec.named[param.key] : void 0;
|
|
1165
|
+
finalizeAbsentKey(param.key, param.type, namedParam?.type);
|
|
741
1166
|
}
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
return
|
|
745
|
-
}
|
|
746
|
-
function documentScope(records, parent) {
|
|
747
|
-
return new DocumentScope(records, parent);
|
|
748
|
-
}
|
|
749
|
-
function namespaceScope(namespace, parent) {
|
|
750
|
-
return new NamespaceScope(namespace, parent);
|
|
751
|
-
}
|
|
752
|
-
function isNamespaceLike(resolution) {
|
|
753
|
-
return resolution.kind === "namespace" || resolution.kind === "contributedNamespace";
|
|
1167
|
+
for (const key of Object.keys(spec.named)) finalizeAbsentKey(key, void 0, spec.named[key]?.type);
|
|
1168
|
+
if (!outcome.ok) return notOk(outcome.failure);
|
|
1169
|
+
return ok(output);
|
|
754
1170
|
}
|
|
755
|
-
function
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1171
|
+
function interpretAttribute(attrNode, spec, ctx) {
|
|
1172
|
+
const attributeSpan = nodePslSpan(attrNode.syntax, ctx.sources);
|
|
1173
|
+
const bound = interpretArgs(attrNode.argList()?.args() ?? [], spec, ctx, attributeSpan, attrNode.syntax);
|
|
1174
|
+
if (!bound.ok) return notOk(bound.failure);
|
|
1175
|
+
const value = blindCast(bound.value);
|
|
1176
|
+
if (spec.refine !== void 0) {
|
|
1177
|
+
const refineDiagnostics = spec.refine(value, ctx, attrNode);
|
|
1178
|
+
if (refineDiagnostics.length > 0) return notOk(refineDiagnostics);
|
|
759
1179
|
}
|
|
760
|
-
|
|
1180
|
+
return ok(value);
|
|
761
1181
|
}
|
|
762
|
-
function
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
}
|
|
767
|
-
return namespaceMember(qualifier.symbol, name);
|
|
1182
|
+
function parseArgValue(arg, argType, ctx) {
|
|
1183
|
+
const value = arg.value();
|
|
1184
|
+
if (value === void 0) return notOk([diagnostic("Attribute argument is missing a value", ctx, nodePslSpan(arg.syntax, ctx.sources), arg.syntax)]);
|
|
1185
|
+
return argType.parse(value, ctx);
|
|
768
1186
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
return symbol.node.typeAnnotation()?.name()?.syntax;
|
|
1187
|
+
function isOptionalArgType(param) {
|
|
1188
|
+
return "optional" in param && param.optional === true;
|
|
772
1189
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
this.#declarations = declarations;
|
|
780
|
-
this.#references = references;
|
|
781
|
-
this.#documentScope = documentScope;
|
|
782
|
-
this.#scopes = scopes;
|
|
783
|
-
}
|
|
784
|
-
declaredSymbol(node) {
|
|
785
|
-
return this.#declarations.get(node);
|
|
786
|
-
}
|
|
787
|
-
symbolForNode(node) {
|
|
788
|
-
return this.#references.get(node);
|
|
789
|
-
}
|
|
790
|
-
scopeAt(node) {
|
|
791
|
-
return node.findAncestor((ancestor) => this.#scopes.get(ancestor)) ?? this.#documentScope;
|
|
792
|
-
}
|
|
793
|
-
};
|
|
794
|
-
var ScopeStack = class {
|
|
795
|
-
#base;
|
|
796
|
-
#scopes;
|
|
797
|
-
constructor(base) {
|
|
798
|
-
this.#base = base;
|
|
799
|
-
this.#scopes = [base];
|
|
800
|
-
}
|
|
801
|
-
current() {
|
|
802
|
-
return this.#scopes[this.#scopes.length - 1] ?? this.#base;
|
|
803
|
-
}
|
|
804
|
-
push(scope) {
|
|
805
|
-
this.#scopes.push(scope);
|
|
806
|
-
}
|
|
807
|
-
pop() {
|
|
808
|
-
this.#scopes.pop();
|
|
809
|
-
}
|
|
810
|
-
};
|
|
811
|
-
function walkEntities(symbolTable, stack, binder, visit) {
|
|
812
|
-
const { topLevel } = symbolTable;
|
|
813
|
-
for (const entity of Object.values(topLevel.models)) visit(entity);
|
|
814
|
-
for (const entity of Object.values(topLevel.compositeTypes)) visit(entity);
|
|
815
|
-
for (const namespace of Object.values(topLevel.namespaces)) {
|
|
816
|
-
stack.push(binder.scopeAt(namespace.declarations[0].node.syntax));
|
|
817
|
-
for (const entity of Object.values(namespace.models)) visit(entity);
|
|
818
|
-
for (const entity of Object.values(namespace.compositeTypes)) visit(entity);
|
|
819
|
-
stack.pop();
|
|
820
|
-
}
|
|
1190
|
+
function diagnostic(message, ctx, span, sourceNode) {
|
|
1191
|
+
return {
|
|
1192
|
+
code: ATTRIBUTE_DIAGNOSTIC_CODE,
|
|
1193
|
+
message,
|
|
1194
|
+
...diagnosticSource(ctx.sources, sourceNode).at(span)
|
|
1195
|
+
};
|
|
821
1196
|
}
|
|
822
|
-
function
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
declarations.set(declaration.node.syntax, namespace);
|
|
843
|
-
scopes.set(declaration.node.syntax, scope);
|
|
844
|
-
}
|
|
845
|
-
for (const symbol of Object.values(namespace.blocks)) declarations.set(symbol.node.syntax, symbol);
|
|
846
|
-
}
|
|
847
|
-
walkEntities(symbolTable, stack, binder, (entity) => {
|
|
848
|
-
declarations.set(entity.node.syntax, entity);
|
|
849
|
-
for (const field of Object.values(entity.fields)) {
|
|
850
|
-
declarations.set(field.node.syntax, field);
|
|
851
|
-
const node = typeReferenceNode(field);
|
|
852
|
-
if (node === void 0) continue;
|
|
853
|
-
const outcome = resolveTypeReference(field.node.typeAnnotation()?.name(), stack.current());
|
|
854
|
-
if (outcome === void 0) continue;
|
|
855
|
-
references.set(node, outcome.resolution);
|
|
856
|
-
if (outcome.message !== void 0) diagnostics.push({
|
|
857
|
-
code: PSL_UNRESOLVED_REFERENCE,
|
|
858
|
-
message: outcome.message,
|
|
859
|
-
data: {
|
|
860
|
-
reference: "type",
|
|
861
|
-
name: outcome.name,
|
|
862
|
-
constructorCall: field.typeConstructor !== void 0
|
|
863
|
-
},
|
|
864
|
-
...diagnosticSource(sources, node).at()
|
|
1197
|
+
function funcCall(name, sig) {
|
|
1198
|
+
return {
|
|
1199
|
+
kind: "funcCall",
|
|
1200
|
+
label: `${name}()`,
|
|
1201
|
+
name,
|
|
1202
|
+
signature: sig,
|
|
1203
|
+
parse: (arg, ctx) => {
|
|
1204
|
+
const guard = matchCallee(arg, name, ctx);
|
|
1205
|
+
if (!guard.ok) return guard;
|
|
1206
|
+
const span = nodePslSpan(guard.value.syntax, ctx.sources);
|
|
1207
|
+
const bound = interpretArgs(guard.value.args(), {
|
|
1208
|
+
name,
|
|
1209
|
+
positional: sig.positional ?? [],
|
|
1210
|
+
named: sig.named ?? {}
|
|
1211
|
+
}, ctx, span, guard.value.syntax);
|
|
1212
|
+
if (!bound.ok) return notOk(bound.failure);
|
|
1213
|
+
return ok({
|
|
1214
|
+
fn: name,
|
|
1215
|
+
span,
|
|
1216
|
+
args: bound.value
|
|
865
1217
|
});
|
|
866
1218
|
}
|
|
867
|
-
});
|
|
868
|
-
walkEntities(symbolTable, stack, binder, (entity) => {
|
|
869
|
-
const context = {
|
|
870
|
-
owner: entity,
|
|
871
|
-
scope: stack.current(),
|
|
872
|
-
references,
|
|
873
|
-
diagnostics,
|
|
874
|
-
symbolTable,
|
|
875
|
-
sources,
|
|
876
|
-
describeUnsupportedAttribute
|
|
877
|
-
};
|
|
878
|
-
const specContext = entity.kind === "model" ? {
|
|
879
|
-
symbols: symbolTable,
|
|
880
|
-
model: entity,
|
|
881
|
-
controlMutationDefaults
|
|
882
|
-
} : void 0;
|
|
883
|
-
bindAttributes(entity, entity.attributes, attributeSpecs.model, (factory) => specContext === void 0 ? void 0 : factory(specContext), {
|
|
884
|
-
...context,
|
|
885
|
-
field: void 0
|
|
886
|
-
});
|
|
887
|
-
for (const field of Object.values(entity.fields)) bindAttributes(field, field.attributes, attributeSpecs.field, (factory) => specContext === void 0 ? void 0 : factory({
|
|
888
|
-
...specContext,
|
|
889
|
-
field
|
|
890
|
-
}), {
|
|
891
|
-
...context,
|
|
892
|
-
field
|
|
893
|
-
});
|
|
894
|
-
});
|
|
895
|
-
const blockContext = {
|
|
896
|
-
pslBlockDescriptors,
|
|
897
|
-
symbolTable,
|
|
898
|
-
sources,
|
|
899
|
-
references,
|
|
900
|
-
diagnostics
|
|
901
1219
|
};
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1220
|
+
}
|
|
1221
|
+
function matchCallee(arg, name, ctx) {
|
|
1222
|
+
const call = FunctionCallAst.cast(arg.syntax);
|
|
1223
|
+
if (call === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
1224
|
+
const qname = call.name();
|
|
1225
|
+
if (qname === void 0 || qname.dot() !== void 0 || qname.colon() !== void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
1226
|
+
const calleeName = qname.identifier()?.token()?.text;
|
|
1227
|
+
if (calleeName === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a function call")]);
|
|
1228
|
+
if (calleeName !== name) return notOk([leafDiagnostic(ctx, arg, `Expected ${name}()`)]);
|
|
1229
|
+
return ok(call);
|
|
1230
|
+
}
|
|
1231
|
+
function identifier(name, options) {
|
|
1232
|
+
const label = name ?? "identifier";
|
|
1233
|
+
return {
|
|
1234
|
+
kind: "identifier",
|
|
1235
|
+
label,
|
|
1236
|
+
name,
|
|
1237
|
+
documentation: options?.documentation ?? "",
|
|
1238
|
+
parse: (arg, ctx) => {
|
|
1239
|
+
const value = IdentifierAst.cast(arg.syntax)?.name();
|
|
1240
|
+
if (value !== void 0 && (name === void 0 || value === name)) return ok(value);
|
|
1241
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${label}`)]);
|
|
1242
|
+
}
|
|
908
1243
|
};
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1244
|
+
}
|
|
1245
|
+
function int(opts) {
|
|
1246
|
+
const min = opts?.min;
|
|
1247
|
+
const max = opts?.max;
|
|
1248
|
+
return {
|
|
1249
|
+
kind: "int",
|
|
1250
|
+
label: "integer",
|
|
1251
|
+
...min === void 0 ? {} : { min },
|
|
1252
|
+
...max === void 0 ? {} : { max },
|
|
1253
|
+
parse: (arg, ctx) => {
|
|
1254
|
+
const literal = NumberLiteralExprAst.cast(arg.syntax);
|
|
1255
|
+
if (literal !== void 0) {
|
|
1256
|
+
const value = literal.value();
|
|
1257
|
+
if (value !== void 0 && Number.isInteger(value)) {
|
|
1258
|
+
if ((min === void 0 || value >= min) && (max === void 0 || value <= max)) return ok(value);
|
|
1259
|
+
return notOk([leafDiagnostic(ctx, arg, rangeMessage(min, max))]);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected an integer literal")]);
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
function rangeMessage(min, max) {
|
|
1267
|
+
if (min !== void 0 && max !== void 0) return `Expected an integer between ${min} and ${max}`;
|
|
1268
|
+
if (min !== void 0) return `Expected an integer greater than or equal to ${min}`;
|
|
1269
|
+
return `Expected an integer less than or equal to ${max}`;
|
|
1270
|
+
}
|
|
1271
|
+
/**
|
|
1272
|
+
* Reads an opaque JSON object from a quoted JSON string — the ADR's one text-encoded surface
|
|
1273
|
+
* exception (e.g. an index `filter` / `weights` argument). The string is decoded by the parser,
|
|
1274
|
+
* then JSON-parsed; a non-object (array/scalar) or invalid JSON is a diagnostic.
|
|
1275
|
+
*/
|
|
1276
|
+
function json() {
|
|
915
1277
|
return {
|
|
916
|
-
|
|
917
|
-
|
|
1278
|
+
kind: "json",
|
|
1279
|
+
label: "JSON object",
|
|
1280
|
+
parse: (arg, ctx) => {
|
|
1281
|
+
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
1282
|
+
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a JSON object string")]);
|
|
1283
|
+
const raw = literal.value();
|
|
1284
|
+
if (raw !== void 0) try {
|
|
1285
|
+
const parsed = JSON.parse(raw);
|
|
1286
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return ok(blindCast(parsed));
|
|
1287
|
+
} catch {}
|
|
1288
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a valid JSON object")]);
|
|
1289
|
+
}
|
|
918
1290
|
};
|
|
919
1291
|
}
|
|
920
|
-
function
|
|
921
|
-
const
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}), ctx);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
function bindExpression(rule, expression, ctx, modelContext) {
|
|
947
|
-
const trial = tryBindExpression(rule, expression, ctx, modelContext);
|
|
948
|
-
for (const [node, resolution] of trial.references) ctx.references.set(node, resolution);
|
|
949
|
-
ctx.diagnostics.push(...trial.diagnostics.values());
|
|
950
|
-
}
|
|
951
|
-
function tryBindExpression(rule, expression, ctx, modelContext) {
|
|
952
|
-
const references = /* @__PURE__ */ new Map();
|
|
953
|
-
const diagnostics = /* @__PURE__ */ new Map();
|
|
954
|
-
switch (rule.kind) {
|
|
955
|
-
case "oneOf":
|
|
956
|
-
for (const alternative of rule.alternatives) {
|
|
957
|
-
const trial = tryBindExpression(alternative, expression, ctx, modelContext);
|
|
958
|
-
if (trial.matched) return trial;
|
|
959
|
-
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
960
|
-
for (const [node, resolution] of trial.references) if (resolution.kind === "unresolved") references.set(node, resolution);
|
|
1292
|
+
function list(of, opts) {
|
|
1293
|
+
const allowEmpty = opts?.allowEmpty ?? true;
|
|
1294
|
+
const unique = opts?.unique ?? false;
|
|
1295
|
+
return {
|
|
1296
|
+
kind: "list",
|
|
1297
|
+
label: opts?.label ?? (of.label.includes(" | ") ? `(${of.label})[]` : `${of.label}[]`),
|
|
1298
|
+
of,
|
|
1299
|
+
allowEmpty,
|
|
1300
|
+
unique,
|
|
1301
|
+
parse: (arg, ctx) => {
|
|
1302
|
+
const literal = ArrayLiteralAst.cast(arg.syntax);
|
|
1303
|
+
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
|
|
1304
|
+
const parsed = [];
|
|
1305
|
+
let outcome = okVoid();
|
|
1306
|
+
let count = 0;
|
|
1307
|
+
for (const element of literal.elements()) {
|
|
1308
|
+
count += 1;
|
|
1309
|
+
const result = of.parse(element, ctx);
|
|
1310
|
+
if (result.ok) parsed.push({
|
|
1311
|
+
node: element,
|
|
1312
|
+
value: result.value
|
|
1313
|
+
});
|
|
1314
|
+
outcome = and(outcome, result);
|
|
961
1315
|
}
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
case "list":
|
|
968
|
-
case "record": {
|
|
969
|
-
const children = rule.kind === "list" ? ArrayLiteralAst.cast(expression.syntax)?.elements() : recordValues(expression);
|
|
970
|
-
if (children === void 0) return {
|
|
971
|
-
matched: false,
|
|
972
|
-
references,
|
|
973
|
-
diagnostics
|
|
974
|
-
};
|
|
975
|
-
let matched = true;
|
|
976
|
-
for (const child of children) {
|
|
977
|
-
const trial = tryBindExpression(rule.of, child, ctx, modelContext);
|
|
978
|
-
matched = trial.matched && matched;
|
|
979
|
-
for (const [node, resolution] of trial.references) references.set(node, resolution);
|
|
980
|
-
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
1316
|
+
if (!allowEmpty && count === 0) outcome = and(outcome, notOk([leafDiagnostic(ctx, arg, "Expected a non-empty list")]));
|
|
1317
|
+
if (unique) {
|
|
1318
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1319
|
+
for (const { node, value } of parsed) if (seen.has(value)) outcome = and(outcome, notOk([leafDiagnostic(ctx, node, "Duplicate list entry")]));
|
|
1320
|
+
else seen.add(value);
|
|
981
1321
|
}
|
|
982
|
-
return
|
|
983
|
-
|
|
984
|
-
references,
|
|
985
|
-
diagnostics
|
|
986
|
-
};
|
|
1322
|
+
if (!outcome.ok) return notOk(outcome.failure);
|
|
1323
|
+
return ok(parsed.map((entry) => entry.value));
|
|
987
1324
|
}
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
const
|
|
1002
|
-
if (
|
|
1003
|
-
|
|
1004
|
-
continue;
|
|
1005
|
-
}
|
|
1006
|
-
const trial = tryBindExpression(parameter.type, value, ctx, modelContext);
|
|
1007
|
-
matched = trial.matched && matched;
|
|
1008
|
-
for (const [node, resolution] of trial.references) references.set(node, resolution);
|
|
1009
|
-
for (const [node, diagnostic] of trial.diagnostics) diagnostics.set(node, diagnostic);
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
function oneOf(...alts) {
|
|
1328
|
+
const label = alts.map((alt) => alt.label).join(" | ");
|
|
1329
|
+
return {
|
|
1330
|
+
kind: "oneOf",
|
|
1331
|
+
label,
|
|
1332
|
+
alternatives: alts,
|
|
1333
|
+
parse: (arg, ctx) => {
|
|
1334
|
+
const [head, ...tail] = blindCast(alts);
|
|
1335
|
+
let rejection = head.parse(arg, ctx);
|
|
1336
|
+
if (rejection.ok) return rejection;
|
|
1337
|
+
for (const alt of tail) {
|
|
1338
|
+
const result = alt.parse(arg, ctx);
|
|
1339
|
+
if (result.ok) return result;
|
|
1340
|
+
rejection = or(rejection, result);
|
|
1010
1341
|
}
|
|
1011
|
-
return
|
|
1012
|
-
|
|
1013
|
-
references,
|
|
1014
|
-
diagnostics
|
|
1015
|
-
};
|
|
1016
|
-
}
|
|
1017
|
-
case "entityRef": {
|
|
1018
|
-
const node = expression.syntax;
|
|
1019
|
-
const name = IdentifierAst.cast(node)?.name();
|
|
1020
|
-
if (name === void 0) return {
|
|
1021
|
-
matched: false,
|
|
1022
|
-
references,
|
|
1023
|
-
diagnostics
|
|
1024
|
-
};
|
|
1025
|
-
const failures = [];
|
|
1026
|
-
const resolution = resolveEntity(name, node, {
|
|
1027
|
-
...ctx,
|
|
1028
|
-
diagnostics: failures
|
|
1029
|
-
});
|
|
1030
|
-
references.set(node, resolution);
|
|
1031
|
-
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
1032
|
-
return {
|
|
1033
|
-
matched: resolution.kind !== "unresolved",
|
|
1034
|
-
references,
|
|
1035
|
-
diagnostics
|
|
1036
|
-
};
|
|
1037
|
-
}
|
|
1038
|
-
case "fieldRef": {
|
|
1039
|
-
const node = expression.syntax;
|
|
1040
|
-
const name = IdentifierAst.cast(node)?.name();
|
|
1041
|
-
if (name === void 0 || modelContext === void 0) return {
|
|
1042
|
-
matched: false,
|
|
1043
|
-
references,
|
|
1044
|
-
diagnostics
|
|
1045
|
-
};
|
|
1046
|
-
const failures = [];
|
|
1047
|
-
const resolution = resolveOwnerField(name, node, {
|
|
1048
|
-
...modelContext,
|
|
1049
|
-
diagnostics: failures
|
|
1050
|
-
});
|
|
1051
|
-
references.set(node, resolution);
|
|
1052
|
-
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
1053
|
-
return {
|
|
1054
|
-
matched: resolution.kind !== "unresolved",
|
|
1055
|
-
references,
|
|
1056
|
-
diagnostics
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
case "referencedFieldRef": {
|
|
1060
|
-
const node = expression.syntax;
|
|
1061
|
-
const name = IdentifierAst.cast(node)?.name();
|
|
1062
|
-
if (name === void 0 || modelContext === void 0) return {
|
|
1063
|
-
matched: false,
|
|
1064
|
-
references,
|
|
1065
|
-
diagnostics
|
|
1066
|
-
};
|
|
1067
|
-
const failures = [];
|
|
1068
|
-
const resolution = resolveReferencedField(name, node, {
|
|
1069
|
-
...modelContext,
|
|
1070
|
-
diagnostics: failures
|
|
1071
|
-
});
|
|
1072
|
-
references.set(node, resolution);
|
|
1073
|
-
for (const diagnostic of failures) diagnostics.set(node, diagnostic);
|
|
1074
|
-
return {
|
|
1075
|
-
matched: resolution.kind !== "unresolved",
|
|
1076
|
-
references,
|
|
1077
|
-
diagnostics
|
|
1078
|
-
};
|
|
1342
|
+
if (!rejection.ok && rejection.failure.length === 0) return notOk([]);
|
|
1343
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
|
|
1079
1344
|
}
|
|
1080
|
-
|
|
1081
|
-
matched: true,
|
|
1082
|
-
references,
|
|
1083
|
-
diagnostics
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1345
|
+
};
|
|
1086
1346
|
}
|
|
1087
|
-
function
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1347
|
+
function record(of) {
|
|
1348
|
+
return {
|
|
1349
|
+
kind: "record",
|
|
1350
|
+
label: `{ [key]: ${of.label} }`,
|
|
1351
|
+
of,
|
|
1352
|
+
parse: (arg, ctx) => {
|
|
1353
|
+
const literal = ObjectLiteralExprAst.cast(arg.syntax);
|
|
1354
|
+
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected an object literal")]);
|
|
1355
|
+
const entries = [];
|
|
1356
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1357
|
+
let outcome = okVoid();
|
|
1358
|
+
for (const field of Array.from(literal.fields())) {
|
|
1359
|
+
const key = field.keyName();
|
|
1360
|
+
if (key === void 0) {
|
|
1361
|
+
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, "Expected a key")]));
|
|
1362
|
+
continue;
|
|
1363
|
+
}
|
|
1364
|
+
const value = field.value();
|
|
1365
|
+
if (value === void 0) {
|
|
1366
|
+
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Expected a value for key "${key}"`)]));
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
const parsed = of.parse(value, ctx);
|
|
1370
|
+
if (!parsed.ok) {
|
|
1371
|
+
outcome = and(outcome, parsed);
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
if (keys.has(key)) {
|
|
1375
|
+
outcome = and(outcome, notOk([leafDiagnostic(ctx, field, `Duplicate key "${key}"`)]));
|
|
1376
|
+
continue;
|
|
1377
|
+
}
|
|
1378
|
+
keys.add(key);
|
|
1379
|
+
entries.push([key, parsed.value]);
|
|
1380
|
+
}
|
|
1381
|
+
if (!outcome.ok) return notOk(outcome.failure);
|
|
1382
|
+
return ok(Object.fromEntries(entries));
|
|
1094
1383
|
}
|
|
1095
|
-
}
|
|
1384
|
+
};
|
|
1096
1385
|
}
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
});
|
|
1110
|
-
if (diagnostic !== void 0) ctx.diagnostics.push(diagnostic);
|
|
1111
|
-
return;
|
|
1386
|
+
function str(value) {
|
|
1387
|
+
if (value === void 0) return {
|
|
1388
|
+
kind: "str",
|
|
1389
|
+
label: "string",
|
|
1390
|
+
value: void 0,
|
|
1391
|
+
parse: (arg, ctx) => {
|
|
1392
|
+
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
1393
|
+
if (literal !== void 0) {
|
|
1394
|
+
const parsed = literal.value();
|
|
1395
|
+
if (parsed !== void 0) return ok(parsed);
|
|
1396
|
+
}
|
|
1397
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a string literal")]);
|
|
1112
1398
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
spec
|
|
1399
|
+
};
|
|
1400
|
+
return {
|
|
1401
|
+
kind: "str",
|
|
1402
|
+
label: JSON.stringify(value),
|
|
1403
|
+
value,
|
|
1404
|
+
parse: (arg, ctx) => {
|
|
1405
|
+
const literal = StringLiteralExprAst.cast(arg.syntax);
|
|
1406
|
+
if (literal !== void 0) {
|
|
1407
|
+
if (literal.value() === value) return ok(value);
|
|
1123
1408
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
function bindArguments(attribute, spec, ctx, modelContext) {
|
|
1129
|
-
let positional = 0;
|
|
1130
|
-
for (const arg of attribute.args) {
|
|
1131
|
-
const parameter = argumentParameter(spec, arg.name, arg.name === void 0 ? positional++ : positional);
|
|
1132
|
-
if (parameter === void 0 || arg.expression === void 0) continue;
|
|
1133
|
-
bindExpression(parameter.type, arg.expression, ctx, modelContext);
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
function argumentParameter(spec, name, position) {
|
|
1137
|
-
if (name === void 0) return spec.positional?.[position];
|
|
1138
|
-
return spec.named === void 0 ? void 0 : own(spec.named, name);
|
|
1409
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${JSON.stringify(value)}`)]);
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1139
1412
|
}
|
|
1140
|
-
function
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1413
|
+
function jsonValue() {
|
|
1414
|
+
const self = {
|
|
1415
|
+
kind: "oneOf",
|
|
1416
|
+
label: "JSON value",
|
|
1417
|
+
get alternatives() {
|
|
1418
|
+
return composed.alternatives;
|
|
1419
|
+
},
|
|
1420
|
+
parse: (arg, ctx) => composed.parse(arg, ctx)
|
|
1145
1421
|
};
|
|
1146
|
-
|
|
1422
|
+
const composed = oneOf(str(), finiteNumber(), bool(), jsonNull(), list(self), record(self));
|
|
1423
|
+
return self;
|
|
1424
|
+
}
|
|
1425
|
+
function finiteNumber() {
|
|
1147
1426
|
return {
|
|
1148
|
-
kind: "
|
|
1149
|
-
|
|
1427
|
+
kind: "num",
|
|
1428
|
+
value: void 0,
|
|
1429
|
+
label: "number",
|
|
1430
|
+
parse: (arg, ctx) => {
|
|
1431
|
+
const value = NumberLiteralExprAst.cast(arg.syntax)?.value();
|
|
1432
|
+
if (value === void 0 || Number.isNaN(value) || !Number.isFinite(value)) return notOk([leafDiagnostic(ctx, arg, "Expected a finite number literal")]);
|
|
1433
|
+
return ok(value);
|
|
1434
|
+
}
|
|
1150
1435
|
};
|
|
1151
1436
|
}
|
|
1152
|
-
function
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1437
|
+
function jsonNull() {
|
|
1438
|
+
return {
|
|
1439
|
+
kind: "null",
|
|
1440
|
+
label: "null",
|
|
1441
|
+
parse: (arg, ctx) => {
|
|
1442
|
+
if (IdentifierAst.cast(arg.syntax)?.name() === "null") return ok(null);
|
|
1443
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected null")]);
|
|
1444
|
+
}
|
|
1157
1445
|
};
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1446
|
+
}
|
|
1447
|
+
function num(value) {
|
|
1448
|
+
if (value === void 0) return {
|
|
1449
|
+
kind: "num",
|
|
1450
|
+
label: "number",
|
|
1451
|
+
value: void 0,
|
|
1452
|
+
parse: (arg, ctx) => {
|
|
1453
|
+
const literal = NumberLiteralExprAst.cast(arg.syntax);
|
|
1454
|
+
if (literal !== void 0) {
|
|
1455
|
+
const parsed = literal.value();
|
|
1456
|
+
if (parsed !== void 0) return ok(parsed);
|
|
1457
|
+
}
|
|
1458
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
|
|
1459
|
+
}
|
|
1164
1460
|
};
|
|
1165
|
-
report(`Cannot find field "${name}" on the type of "${ctx.owner.name}.${declaring.name}"`, node, ctx, "field");
|
|
1166
1461
|
return {
|
|
1167
|
-
kind: "
|
|
1168
|
-
|
|
1462
|
+
kind: "num",
|
|
1463
|
+
label: String(value),
|
|
1464
|
+
value,
|
|
1465
|
+
parse: (arg, ctx) => {
|
|
1466
|
+
const literal = NumberLiteralExprAst.cast(arg.syntax);
|
|
1467
|
+
if (literal !== void 0) {
|
|
1468
|
+
if (literal.value() === value) return ok(value);
|
|
1469
|
+
}
|
|
1470
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${value}`)]);
|
|
1471
|
+
}
|
|
1169
1472
|
};
|
|
1170
1473
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
}
|
|
1184
|
-
return found;
|
|
1474
|
+
/** A number literal kept as its source text, for consumers that must not round it through a JS number. */
|
|
1475
|
+
function numLiteral() {
|
|
1476
|
+
return {
|
|
1477
|
+
kind: "num",
|
|
1478
|
+
label: "number",
|
|
1479
|
+
value: void 0,
|
|
1480
|
+
parse: (arg, ctx) => {
|
|
1481
|
+
const text = NumberLiteralExprAst.cast(arg.syntax)?.token()?.text;
|
|
1482
|
+
if (text !== void 0) return ok({ text });
|
|
1483
|
+
return notOk([leafDiagnostic(ctx, arg, "Expected a number literal")]);
|
|
1484
|
+
}
|
|
1485
|
+
};
|
|
1185
1486
|
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1487
|
+
/**
|
|
1488
|
+
* A `` tag`...` ``, `tag"..."`, or `tag'...'` argument. `tags` and `documentation` describe the
|
|
1489
|
+
* registered tags for tooling; parsing accepts any tag.
|
|
1490
|
+
*/
|
|
1491
|
+
function taggedLiteral(tags, options) {
|
|
1492
|
+
return {
|
|
1493
|
+
kind: "taggedLiteral",
|
|
1494
|
+
label: `${tags[0] ?? "tag"}\`...\``,
|
|
1495
|
+
tags,
|
|
1496
|
+
documentation: options.documentation,
|
|
1497
|
+
parse: (arg, ctx) => {
|
|
1498
|
+
const literal = TaggedLiteralExprAst.cast(arg.syntax);
|
|
1499
|
+
if (literal === void 0) return notOk([leafDiagnostic(ctx, arg, "Expected a tagged literal")]);
|
|
1500
|
+
return ok({
|
|
1501
|
+
tag: literal.tagName(),
|
|
1502
|
+
canonicalization: literal.canonicalization(),
|
|
1503
|
+
span: nodePslSpan(literal.syntax, ctx.sources)
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1193
1507
|
}
|
|
1194
|
-
function
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
|
|
1203
|
-
return {
|
|
1204
|
-
resolution: {
|
|
1205
|
-
kind: "unresolved",
|
|
1206
|
-
name: written
|
|
1207
|
-
},
|
|
1208
|
-
message: `Cannot find type "${written}"`,
|
|
1209
|
-
name: written
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
if ("badQualifier" in found) return {
|
|
1213
|
-
resolution: {
|
|
1214
|
-
kind: "unresolved",
|
|
1215
|
-
name: found.qualifier
|
|
1216
|
-
},
|
|
1217
|
-
message: found.badQualifier,
|
|
1218
|
-
name: found.qualifier
|
|
1508
|
+
function fieldAttribute(name, config) {
|
|
1509
|
+
return {
|
|
1510
|
+
level: "field",
|
|
1511
|
+
name,
|
|
1512
|
+
documentation: config.documentation,
|
|
1513
|
+
positional: config.positional ?? [],
|
|
1514
|
+
named: Object.assign(Object.create(null), config.named),
|
|
1515
|
+
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
1219
1516
|
};
|
|
1220
|
-
if (found.kind === "namespace" || found.kind === "contributedNamespace") {
|
|
1221
|
-
const written = namespaceId === void 0 ? name : `${namespaceId}.${name}`;
|
|
1222
|
-
return {
|
|
1223
|
-
resolution: found,
|
|
1224
|
-
message: `"${written}" is a namespace; a type reference must name a model, composite type, enum, or named type`,
|
|
1225
|
-
name: written
|
|
1226
|
-
};
|
|
1227
|
-
}
|
|
1228
|
-
return { resolution: found };
|
|
1229
1517
|
}
|
|
1230
|
-
function
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1518
|
+
function modelAttribute(name, config) {
|
|
1519
|
+
return {
|
|
1520
|
+
level: "model",
|
|
1521
|
+
name,
|
|
1522
|
+
documentation: config.documentation,
|
|
1523
|
+
positional: config.positional ?? [],
|
|
1524
|
+
named: Object.assign(Object.create(null), config.named),
|
|
1525
|
+
...config.refine !== void 0 ? { refine: config.refine } : {}
|
|
1236
1526
|
};
|
|
1237
|
-
return lookupMember(qualifier, name);
|
|
1238
|
-
}
|
|
1239
|
-
function describeQualifier(resolution) {
|
|
1240
|
-
switch (resolution.kind) {
|
|
1241
|
-
case "model": return "a model";
|
|
1242
|
-
case "compositeType": return "a composite type";
|
|
1243
|
-
case "namedType": return "a named type";
|
|
1244
|
-
case "block": return `${resolution.symbol.keyword === "enum" ? "an" : "a"} ${resolution.symbol.keyword}`;
|
|
1245
|
-
default: return "a scalar type";
|
|
1246
|
-
}
|
|
1247
1527
|
}
|
|
1248
|
-
function
|
|
1249
|
-
|
|
1528
|
+
function optional(type, ...rest) {
|
|
1529
|
+
if (rest.length === 0) return {
|
|
1530
|
+
...type,
|
|
1531
|
+
optional: true,
|
|
1532
|
+
hasDefault: false
|
|
1533
|
+
};
|
|
1534
|
+
return {
|
|
1535
|
+
...type,
|
|
1536
|
+
optional: true,
|
|
1537
|
+
hasDefault: true,
|
|
1538
|
+
defaultValue: rest[0]
|
|
1539
|
+
};
|
|
1250
1540
|
}
|
|
1251
1541
|
function structBlock(config) {
|
|
1252
1542
|
return {
|
|
@@ -1483,237 +1773,7 @@ function isPrismaNextSchema(text) {
|
|
|
1483
1773
|
function renameLegacyDirective(text) {
|
|
1484
1774
|
return text.replace(DIRECTIVE, (whole, lead, name, trail) => name === LEGACY_NAME ? `${lead}prisma-8${trail}` : whole);
|
|
1485
1775
|
}
|
|
1486
|
-
/**
|
|
1487
|
-
* Owns duplicate-declaration detection for all PSL scopes; downstream consumers
|
|
1488
|
-
* should consume first-wins symbols rather than re-emitting duplicate diagnostics.
|
|
1489
|
-
*/
|
|
1490
|
-
function buildSymbolTable(options) {
|
|
1491
|
-
const { documents, sources } = options;
|
|
1492
|
-
const diagnostics = [];
|
|
1493
|
-
const namespaces = Object.create(null);
|
|
1494
|
-
const namedTypes = Object.create(null);
|
|
1495
|
-
const blocks = Object.create(null);
|
|
1496
|
-
const models = Object.create(null);
|
|
1497
|
-
const compositeTypes = Object.create(null);
|
|
1498
|
-
const topLevelNames = /* @__PURE__ */ new Set();
|
|
1499
|
-
for (const document of documents) {
|
|
1500
|
-
const sourceFile = sources.sourceFileFor(document.syntax);
|
|
1501
|
-
const claim = (taken, name) => {
|
|
1502
|
-
const text = name?.name();
|
|
1503
|
-
if (text === void 0) return void 0;
|
|
1504
|
-
if (taken.has(text)) {
|
|
1505
|
-
const range = nameRange(name, sources);
|
|
1506
|
-
if (range) diagnostics.push({
|
|
1507
|
-
code: "PSL_DUPLICATE_DECLARATION",
|
|
1508
|
-
message: `Duplicate declaration of "${text}"`,
|
|
1509
|
-
filename: sourceFile.filename,
|
|
1510
|
-
range
|
|
1511
|
-
});
|
|
1512
|
-
return;
|
|
1513
|
-
}
|
|
1514
|
-
taken.add(text);
|
|
1515
|
-
return text;
|
|
1516
|
-
};
|
|
1517
|
-
for (const declaration of document.declarations()) if (declaration instanceof ModelDeclarationAst) {
|
|
1518
|
-
const name = claim(topLevelNames, declaration.name());
|
|
1519
|
-
if (name !== void 0) models[name] = buildModel(name, declaration, sources, diagnostics);
|
|
1520
|
-
} else if (declaration instanceof CompositeTypeDeclarationAst) {
|
|
1521
|
-
const name = claim(topLevelNames, declaration.name());
|
|
1522
|
-
if (name !== void 0) compositeTypes[name] = buildCompositeType(name, declaration, sources, diagnostics);
|
|
1523
|
-
} else if (declaration instanceof GenericBlockDeclarationAst) {
|
|
1524
|
-
const name = claim(topLevelNames, declaration.name());
|
|
1525
|
-
if (name !== void 0) blocks[name] = buildBlock(name, declaration, sources);
|
|
1526
|
-
} else if (declaration instanceof NamespaceDeclarationAst) {
|
|
1527
|
-
const declaredName = declaration.name()?.name();
|
|
1528
|
-
if (declaredName === void 0) continue;
|
|
1529
|
-
let namespace = namespaces[declaredName];
|
|
1530
|
-
if (namespace === void 0) {
|
|
1531
|
-
const name = claim(topLevelNames, declaration.name());
|
|
1532
|
-
if (name === void 0) continue;
|
|
1533
|
-
namespace = {
|
|
1534
|
-
kind: "namespace",
|
|
1535
|
-
name,
|
|
1536
|
-
declarations: [{
|
|
1537
|
-
node: declaration,
|
|
1538
|
-
span: nodePslSpan(declaration.syntax, sources)
|
|
1539
|
-
}],
|
|
1540
|
-
models: Object.create(null),
|
|
1541
|
-
compositeTypes: Object.create(null),
|
|
1542
|
-
blocks: Object.create(null)
|
|
1543
|
-
};
|
|
1544
|
-
namespaces[name] = namespace;
|
|
1545
|
-
} else namespace.declarations.push({
|
|
1546
|
-
node: declaration,
|
|
1547
|
-
span: nodePslSpan(declaration.syntax, sources)
|
|
1548
|
-
});
|
|
1549
|
-
extendNamespace(namespace, declaration, diagnostics, sources);
|
|
1550
|
-
} else if (declaration instanceof TypesBlockAst) for (const binding of declaration.declarations()) {
|
|
1551
|
-
const name = claim(topLevelNames, binding.name());
|
|
1552
|
-
if (name === void 0) continue;
|
|
1553
|
-
const resolved = resolveNamedTypeBinding(binding, sources);
|
|
1554
|
-
namedTypes[name] = {
|
|
1555
|
-
kind: "namedType",
|
|
1556
|
-
name,
|
|
1557
|
-
node: binding,
|
|
1558
|
-
span: nodePslSpan(binding.syntax, sources),
|
|
1559
|
-
...resolved
|
|
1560
|
-
};
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
return {
|
|
1564
|
-
symbolTable: { topLevel: {
|
|
1565
|
-
namespaces,
|
|
1566
|
-
namedTypes,
|
|
1567
|
-
blocks,
|
|
1568
|
-
models,
|
|
1569
|
-
compositeTypes
|
|
1570
|
-
} },
|
|
1571
|
-
diagnostics
|
|
1572
|
-
};
|
|
1573
|
-
}
|
|
1574
|
-
function buildModel(name, node, sources, diagnostics) {
|
|
1575
|
-
return {
|
|
1576
|
-
kind: "model",
|
|
1577
|
-
name,
|
|
1578
|
-
node,
|
|
1579
|
-
span: nodePslSpan(node.syntax, sources),
|
|
1580
|
-
fields: buildFields(name, node.fields(), sources, diagnostics),
|
|
1581
|
-
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
1582
|
-
};
|
|
1583
|
-
}
|
|
1584
|
-
function buildCompositeType(name, node, sources, diagnostics) {
|
|
1585
|
-
return {
|
|
1586
|
-
kind: "compositeType",
|
|
1587
|
-
name,
|
|
1588
|
-
node,
|
|
1589
|
-
span: nodePslSpan(node.syntax, sources),
|
|
1590
|
-
fields: buildFields(name, node.fields(), sources, diagnostics),
|
|
1591
|
-
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
1592
|
-
};
|
|
1593
|
-
}
|
|
1594
|
-
function buildBlock(name, node, sources) {
|
|
1595
|
-
return {
|
|
1596
|
-
kind: "block",
|
|
1597
|
-
name,
|
|
1598
|
-
keyword: node.keyword()?.text ?? "",
|
|
1599
|
-
node,
|
|
1600
|
-
span: nodePslSpan(node.syntax, sources)
|
|
1601
|
-
};
|
|
1602
|
-
}
|
|
1603
|
-
function extendNamespace(namespace, node, diagnostics, sources) {
|
|
1604
|
-
const { models, compositeTypes, blocks } = namespace;
|
|
1605
|
-
for (const member of node.declarations()) {
|
|
1606
|
-
const memberName = member.name()?.name();
|
|
1607
|
-
if (memberName === void 0) continue;
|
|
1608
|
-
if (Object.hasOwn(models, memberName) || Object.hasOwn(compositeTypes, memberName) || Object.hasOwn(blocks, memberName)) {
|
|
1609
|
-
const range = nameRange(member.name(), sources);
|
|
1610
|
-
if (range) diagnostics.push({
|
|
1611
|
-
code: "PSL_DUPLICATE_DECLARATION",
|
|
1612
|
-
message: `Duplicate declaration of "${memberName}"`,
|
|
1613
|
-
filename: sources.sourceFileFor(member.syntax).filename,
|
|
1614
|
-
range
|
|
1615
|
-
});
|
|
1616
|
-
continue;
|
|
1617
|
-
}
|
|
1618
|
-
if (member instanceof ModelDeclarationAst) models[memberName] = buildModel(memberName, member, sources, diagnostics);
|
|
1619
|
-
else if (member instanceof CompositeTypeDeclarationAst) compositeTypes[memberName] = buildCompositeType(memberName, member, sources, diagnostics);
|
|
1620
|
-
else if (member instanceof GenericBlockDeclarationAst) blocks[memberName] = buildBlock(memberName, member, sources);
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
function buildFields(ownerName, fields, sources, diagnostics) {
|
|
1624
|
-
const result = Object.create(null);
|
|
1625
|
-
for (const field of fields) {
|
|
1626
|
-
const nameNode = field.name();
|
|
1627
|
-
const name = nameNode?.name();
|
|
1628
|
-
if (name === void 0) continue;
|
|
1629
|
-
if (Object.hasOwn(result, name)) {
|
|
1630
|
-
const range = nameRange(nameNode, sources);
|
|
1631
|
-
if (range) diagnostics.push({
|
|
1632
|
-
code: "PSL_DUPLICATE_DECLARATION",
|
|
1633
|
-
message: `Duplicate declaration of "${name}"`,
|
|
1634
|
-
filename: sources.sourceFileFor(field.syntax).filename,
|
|
1635
|
-
range
|
|
1636
|
-
});
|
|
1637
|
-
continue;
|
|
1638
|
-
}
|
|
1639
|
-
result[name] = buildField(ownerName, name, field, sources, diagnostics);
|
|
1640
|
-
}
|
|
1641
|
-
return result;
|
|
1642
|
-
}
|
|
1643
|
-
function buildField(ownerName, name, node, sources, diagnostics) {
|
|
1644
|
-
const attributes = readResolvedAttributes(node.attributes(), sources);
|
|
1645
|
-
const span = nodePslSpan(node.syntax, sources);
|
|
1646
|
-
const annotation = node.typeAnnotation();
|
|
1647
|
-
const typeName = annotation?.name();
|
|
1648
|
-
if (typeName?.isOverQualified()) {
|
|
1649
|
-
const path = typeName.path();
|
|
1650
|
-
diagnostics.push({
|
|
1651
|
-
code: "PSL_INVALID_QUALIFIED_TYPE",
|
|
1652
|
-
message: `Field "${ownerName}.${name}" has an invalid qualified type "${path.join(".")}"; use at most one namespace qualifier (e.g. "ns.TypeName")`,
|
|
1653
|
-
filename: sources.sourceFileFor(typeName.syntax).filename,
|
|
1654
|
-
range: nodeRange(typeName.syntax, sources)
|
|
1655
|
-
});
|
|
1656
|
-
return {
|
|
1657
|
-
kind: "field",
|
|
1658
|
-
name,
|
|
1659
|
-
node,
|
|
1660
|
-
span,
|
|
1661
|
-
typeName: path[path.length - 1] ?? "",
|
|
1662
|
-
optional: false,
|
|
1663
|
-
list: false,
|
|
1664
|
-
elementOptional: false,
|
|
1665
|
-
malformedType: true,
|
|
1666
|
-
attributes
|
|
1667
|
-
};
|
|
1668
|
-
}
|
|
1669
|
-
const typeConstructor = annotation?.isConstructor() ? readResolvedConstructorCall(annotation, sources) : void 0;
|
|
1670
|
-
const typeNamespaceId = typeName?.namespace()?.name();
|
|
1671
|
-
const typeContractSpaceId = typeName?.space()?.name();
|
|
1672
|
-
return {
|
|
1673
|
-
kind: "field",
|
|
1674
|
-
name,
|
|
1675
|
-
node,
|
|
1676
|
-
span,
|
|
1677
|
-
typeName: typeName?.identifier()?.name() ?? "",
|
|
1678
|
-
...typeNamespaceId !== void 0 ? { typeNamespaceId } : {},
|
|
1679
|
-
...typeContractSpaceId !== void 0 ? { typeContractSpaceId } : {},
|
|
1680
|
-
optional: annotation?.isOptional() ?? false,
|
|
1681
|
-
list: annotation?.isList() ?? false,
|
|
1682
|
-
elementOptional: annotation?.isElementOptional() ?? false,
|
|
1683
|
-
...typeConstructor !== void 0 ? { typeConstructor } : {},
|
|
1684
|
-
attributes
|
|
1685
|
-
};
|
|
1686
|
-
}
|
|
1687
|
-
function resolveNamedTypeBinding(node, sources) {
|
|
1688
|
-
const annotation = node.typeAnnotation();
|
|
1689
|
-
const isConstructor = annotation?.isConstructor() ?? false;
|
|
1690
|
-
const baseType = annotation?.name()?.identifier()?.name();
|
|
1691
|
-
const typeConstructor = readResolvedConstructorCall(annotation, sources);
|
|
1692
|
-
return {
|
|
1693
|
-
isConstructor,
|
|
1694
|
-
...!isConstructor && baseType !== void 0 ? { baseType } : {},
|
|
1695
|
-
...typeConstructor !== void 0 ? { typeConstructor } : {},
|
|
1696
|
-
attributes: readResolvedAttributes(node.attributes(), sources)
|
|
1697
|
-
};
|
|
1698
|
-
}
|
|
1699
|
-
function nameRange(name, sources) {
|
|
1700
|
-
if (name === void 0) return void 0;
|
|
1701
|
-
const sourceFile = sources.sourceFileFor(name.syntax);
|
|
1702
|
-
for (const token of name.syntax.tokens()) if (token.kind === "Ident") return {
|
|
1703
|
-
start: sourceFile.positionAt(token.offset),
|
|
1704
|
-
end: sourceFile.positionAt(token.offset + token.text.length)
|
|
1705
|
-
};
|
|
1706
|
-
}
|
|
1707
|
-
function nodeRange(node, sources) {
|
|
1708
|
-
const sourceFile = sources.sourceFileFor(node);
|
|
1709
|
-
const start = node.offset;
|
|
1710
|
-
const end = start + node.green.textLength;
|
|
1711
|
-
return {
|
|
1712
|
-
start: sourceFile.positionAt(start),
|
|
1713
|
-
end: sourceFile.positionAt(end)
|
|
1714
|
-
};
|
|
1715
|
-
}
|
|
1716
1776
|
//#endregion
|
|
1717
|
-
export { NAME_THE_PSL_SOURCE_LOSES, PSL_UNRESOLVED_REFERENCE, assembleAttributeSpecs, blockAttribute, blockSpecFactoryOf, bool, buildSymbolTable, createBinder, createPslDiagnosticCollector, diagnosticFromSpan, diagnosticSource, entityRef, entityReference, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, funcCall, getPositionalArgument, identifier, int, interpretArgs, interpretAttribute, interpretExtensionBlock, interpretExtensionBlockAttributes, interpretExtensionBlocks, isNamespaceLike, isPrismaNextSchema, isPslIdentifier, json, jsonValue, keywordPslSpan, leafDiagnostic, list, mapBlock, mapPslDiagnostics, matchesSelector, memberEntries, modelAttribute, namespacePslExtensionBlocks, nodePslSpan, num, numLiteral, oneOf, optional, parseQuotedStringLiteral, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, record, referencedFieldRef, renameLegacyDirective, str, structBlock, taggedLiteral, typeReferenceNode };
|
|
1777
|
+
export { NAME_THE_PSL_SOURCE_LOSES, PSL_UNRESOLVED_REFERENCE, assembleAttributeSpecs, blockAttribute, blockSpecFactoryOf, bool, buildSymbolTable, contributedTypeOf, createBinder, createPslDiagnosticCollector, diagnosticFromSpan, diagnosticSource, entityRef, entityReference, fieldAttribute, fieldRef, findBlockDescriptor, flatPslModels, funcCall, getPositionalArgument, identifier, int, interpretArgs, interpretAttribute, interpretExtensionBlock, interpretExtensionBlockAttributes, interpretExtensionBlocks, isNamespaceLike, isPrismaNextSchema, isPslIdentifier, json, jsonValue, keywordPslSpan, leafDiagnostic, list, mapBlock, mapPslDiagnostics, matchesSelector, memberEntries, modelAttribute, namespacePslExtensionBlocks, nodePslSpan, num, numLiteral, oneOf, optional, parseQuotedStringLiteral, readResolvedAttribute, readResolvedAttributes, readResolvedConstructorCall, record, referencedFieldRef, renameLegacyDirective, str, structBlock, taggedLiteral, typeReferenceNode };
|
|
1718
1778
|
|
|
1719
1779
|
//# sourceMappingURL=psl-parser.mjs.map
|