@nola-lang/typescript-plugin 0.1.0-alpha.0 → 0.1.3
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/LICENSE +201 -21
- package/dist/plugin.cjs +584 -134
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +6 -0
- package/dist/plugin.js.map +1 -1
- package/dist/resolution-watch.d.ts +30 -0
- package/dist/resolution-watch.d.ts.map +1 -0
- package/dist/resolution-watch.js +95 -0
- package/dist/resolution-watch.js.map +1 -0
- package/package.json +7 -6
package/dist/plugin.cjs
CHANGED
|
@@ -50,7 +50,7 @@ var require_main = __commonJS({
|
|
|
50
50
|
__export(node_exports, {
|
|
51
51
|
analyzeMetafile: () => analyzeMetafile,
|
|
52
52
|
analyzeMetafileSync: () => analyzeMetafileSync,
|
|
53
|
-
build: () =>
|
|
53
|
+
build: () => build2,
|
|
54
54
|
buildSync: () => buildSync,
|
|
55
55
|
context: () => context,
|
|
56
56
|
default: () => node_default,
|
|
@@ -59,7 +59,7 @@ var require_main = __commonJS({
|
|
|
59
59
|
initialize: () => initialize,
|
|
60
60
|
stop: () => stop,
|
|
61
61
|
transform: () => transform2,
|
|
62
|
-
transformSync: () =>
|
|
62
|
+
transformSync: () => transformSync,
|
|
63
63
|
version: () => version
|
|
64
64
|
});
|
|
65
65
|
module2.exports = __toCommonJS(node_exports);
|
|
@@ -1883,7 +1883,7 @@ More information: The file containing the code for esbuild's JavaScript API (${_
|
|
|
1883
1883
|
}
|
|
1884
1884
|
};
|
|
1885
1885
|
var version = "0.25.12";
|
|
1886
|
-
var
|
|
1886
|
+
var build2 = (options) => ensureServiceIsRunning().build(options);
|
|
1887
1887
|
var context = (buildOptions) => ensureServiceIsRunning().context(buildOptions);
|
|
1888
1888
|
var transform2 = (input, options) => ensureServiceIsRunning().transform(input, options);
|
|
1889
1889
|
var formatMessages = (messages, options) => ensureServiceIsRunning().formatMessages(messages, options);
|
|
@@ -1907,7 +1907,7 @@ More information: The file containing the code for esbuild's JavaScript API (${_
|
|
|
1907
1907
|
}));
|
|
1908
1908
|
return result;
|
|
1909
1909
|
};
|
|
1910
|
-
var
|
|
1910
|
+
var transformSync = (input, options) => {
|
|
1911
1911
|
if (worker_threads && !isInternalWorkerThread) {
|
|
1912
1912
|
if (!workerThreadService) workerThreadService = startWorkerThreadService(worker_threads);
|
|
1913
1913
|
return workerThreadService.transformSync(input, options);
|
|
@@ -4547,14 +4547,21 @@ var Codes = {
|
|
|
4547
4547
|
ExpectedProviderName: "NOLA1009",
|
|
4548
4548
|
ContextualParamOutsideInfer: "NOLA1010",
|
|
4549
4549
|
ContextualParamReserved: "NOLA1011",
|
|
4550
|
+
IncompleteContextualParam: "NOLA1012",
|
|
4551
|
+
ContextualParamDoubleDot: "NOLA1013",
|
|
4552
|
+
ContextualBindingReserved: "NOLA1014",
|
|
4553
|
+
IncompleteScopeAccess: "NOLA1015",
|
|
4550
4554
|
AskOutsideNolaFunction: "NOLA2001",
|
|
4551
4555
|
UnsupportedIntentType: "NOLA2002",
|
|
4552
4556
|
NolaFnNotTopLevel: "NOLA2003",
|
|
4553
4557
|
UntypedCallIntentArg: "NOLA2004",
|
|
4554
4558
|
SubstitutionInCallMarker: "NOLA2005",
|
|
4559
|
+
// retired (emit 11): call-hint substitutions are legal; number not reused
|
|
4555
4560
|
ReservedCompanionPath: "NOLA2006",
|
|
4556
4561
|
CompanionUnavailable: "NOLA2007",
|
|
4557
4562
|
UnderivableContextType: "NOLA2008",
|
|
4563
|
+
ScopeAccessOutsideTemplate: "NOLA2009",
|
|
4564
|
+
NolaConstructInMarker: "NOLA2010",
|
|
4558
4565
|
// NOLA3xxx: runtime diagnostics
|
|
4559
4566
|
EmitContractMismatch: "NOLA3001",
|
|
4560
4567
|
DuplicateRuntimeConflict: "NOLA3002",
|
|
@@ -4566,7 +4573,13 @@ var Codes = {
|
|
|
4566
4573
|
ReplayFingerprintMismatch: "NOLA3008",
|
|
4567
4574
|
SchemaUnsupported: "NOLA3009",
|
|
4568
4575
|
IntentWithoutContext: "NOLA3010",
|
|
4569
|
-
IntentWithoutParentFrame: "NOLA3011"
|
|
4576
|
+
IntentWithoutParentFrame: "NOLA3011",
|
|
4577
|
+
ConfigImportsTsi: "NOLA3012",
|
|
4578
|
+
BrowserExecutionUnsupported: "NOLA3013",
|
|
4579
|
+
PromptTemplateFailed: "NOLA3014",
|
|
4580
|
+
LoaderHooksUnsupported: "NOLA3015",
|
|
4581
|
+
// NOLA4xxx: bundler-integration errors (build-time, raised by @nola-lang/unplugin and friends)
|
|
4582
|
+
TsiInClientBundle: "NOLA4001"
|
|
4570
4583
|
};
|
|
4571
4584
|
function isNode(v) {
|
|
4572
4585
|
return typeof v === "object" && v !== null && typeof v.type === "string" && typeof v.start === "number";
|
|
@@ -4592,6 +4605,17 @@ function programBody(ast) {
|
|
|
4592
4605
|
const program = ast.type === "File" ? ast.program : ast;
|
|
4593
4606
|
return program.type === "Program" ? program.body ?? [] : [];
|
|
4594
4607
|
}
|
|
4608
|
+
function walk(root, visit) {
|
|
4609
|
+
const queue = [{ node: root, parent: null }];
|
|
4610
|
+
while (queue.length > 0) {
|
|
4611
|
+
const item = queue.shift();
|
|
4612
|
+
if (!item)
|
|
4613
|
+
break;
|
|
4614
|
+
visit(item.node, item.parent);
|
|
4615
|
+
for (const child of children(item.node))
|
|
4616
|
+
queue.push({ node: child, parent: item.node });
|
|
4617
|
+
}
|
|
4618
|
+
}
|
|
4595
4619
|
|
|
4596
4620
|
// ../core/dist/errors.js
|
|
4597
4621
|
var NolaConfigError = class extends Error {
|
|
@@ -4602,6 +4626,14 @@ var NolaConfigError = class extends Error {
|
|
|
4602
4626
|
this.code = code2;
|
|
4603
4627
|
}
|
|
4604
4628
|
};
|
|
4629
|
+
var NolaIntentError = class extends Error {
|
|
4630
|
+
code;
|
|
4631
|
+
name = "NolaIntentError";
|
|
4632
|
+
constructor(message, code2) {
|
|
4633
|
+
super(message);
|
|
4634
|
+
this.code = code2;
|
|
4635
|
+
}
|
|
4636
|
+
};
|
|
4605
4637
|
var NolaVersionError = class extends Error {
|
|
4606
4638
|
code;
|
|
4607
4639
|
details;
|
|
@@ -4639,7 +4671,7 @@ function redactError(error) {
|
|
|
4639
4671
|
}
|
|
4640
4672
|
|
|
4641
4673
|
// ../core/dist/index.js
|
|
4642
|
-
var NOLA_EMIT =
|
|
4674
|
+
var NOLA_EMIT = 11;
|
|
4643
4675
|
function mergeProviderParams(base, patch) {
|
|
4644
4676
|
if (!base || !patch)
|
|
4645
4677
|
return patch ?? base;
|
|
@@ -9565,10 +9597,14 @@ var NolaErrors = ParseErrorEnum`nola`({
|
|
|
9565
9597
|
NolaReservedConstruct: "NOLA1004: this Nola construct is reserved for a future Nola version.",
|
|
9566
9598
|
NolaExpectedPromptTemplate: "NOLA1005: expected a template literal prompt after `..`.",
|
|
9567
9599
|
NolaLegacyMarker: "NOLA1007: the `function name``()` form was removed \u2014 declare the function with `infer function`.",
|
|
9568
|
-
|
|
9600
|
+
// NOLA1008 (marker substitution) is retired since emit 11 — the number is not reused.
|
|
9601
|
+
NolaIncompleteScopeAccess: "NOLA1015: incomplete scope access \u2014 write `${.member}`.",
|
|
9569
9602
|
NolaExpectedProviderName: "NOLA1009: expected a provider name after `ask with` \u2014 for a dynamic provider use `.withProvider(...)` on the intent.",
|
|
9570
|
-
NolaContextualOutsideInfer: "NOLA1010:
|
|
9571
|
-
NolaContextualParamReserved: "NOLA1011:
|
|
9603
|
+
NolaContextualOutsideInfer: "NOLA1010: `.` context parameters are only allowed on infer function parameters.",
|
|
9604
|
+
NolaContextualParamReserved: "NOLA1011: `.` on this parameter form is reserved for a future Nola version \u2014 use a plain identifier parameter.",
|
|
9605
|
+
NolaIncompleteContextualParam: "NOLA1012: incomplete `.` context parameter \u2014 write `.name`.",
|
|
9606
|
+
NolaContextualParamDoubleDot: "NOLA1013: contextual parameters take one dot \u2014 write `.name` (`..` is the extractor sigil).",
|
|
9607
|
+
NolaContextualBindingReserved: "NOLA1014: `.name` contextual bindings (`const .x = \u2026`) are reserved for a future Nola version."
|
|
9572
9608
|
});
|
|
9573
9609
|
var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
9574
9610
|
// Set for the duration of a single parseFunctionParams call when we are
|
|
@@ -9582,6 +9618,43 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9582
9618
|
// True while parsing the parameter list of an infer function (save/restore
|
|
9583
9619
|
// across nested function-expression params in default values).
|
|
9584
9620
|
nolaInInferParams = false;
|
|
9621
|
+
// One entry per template literal being parsed (outermost first). A
|
|
9622
|
+
// `${.member}` hole marks EVERY enclosing literal, so an instruction site
|
|
9623
|
+
// learns about scope access at any nesting depth (inside a .map callback's
|
|
9624
|
+
// own template literal, say). Depth > 0 is what makes a leading dot in
|
|
9625
|
+
// expression position a scope access instead of a syntax error.
|
|
9626
|
+
nolaTemplateStack = [];
|
|
9627
|
+
parseTemplate(isTagged) {
|
|
9628
|
+
const entry = { scopeAccess: false };
|
|
9629
|
+
this.nolaTemplateStack.push(entry);
|
|
9630
|
+
try {
|
|
9631
|
+
const node = super.parseTemplate(isTagged);
|
|
9632
|
+
if (entry.scopeAccess)
|
|
9633
|
+
node.nolaHasScopeAccess = true;
|
|
9634
|
+
return node;
|
|
9635
|
+
} finally {
|
|
9636
|
+
this.nolaTemplateStack.pop();
|
|
9637
|
+
}
|
|
9638
|
+
}
|
|
9639
|
+
// `${.member}` — scope access. Only reached inside a template hole (see
|
|
9640
|
+
// parseExprAtom); `..` tokenizes as nolaDotDot, so an inner extractor in a
|
|
9641
|
+
// hole never lands here. Keyword members (`.default`) are legal: the
|
|
9642
|
+
// identifier is parsed liberally like any property name.
|
|
9643
|
+
nolaParseScopeAccess() {
|
|
9644
|
+
const node = this.startNode();
|
|
9645
|
+
const startLoc = this.state.startLoc;
|
|
9646
|
+
this.next();
|
|
9647
|
+
for (const t of this.nolaTemplateStack)
|
|
9648
|
+
t.scopeAccess = true;
|
|
9649
|
+
if (tokenIsKeywordOrIdentifier(this.state.type)) {
|
|
9650
|
+
node.property = this.parseIdentifier(true);
|
|
9651
|
+
} else {
|
|
9652
|
+
this.raise(NolaErrors.NolaIncompleteScopeAccess, startLoc);
|
|
9653
|
+
node.property = null;
|
|
9654
|
+
node.nolaError = true;
|
|
9655
|
+
}
|
|
9656
|
+
return this.finishNode(node, "NolaScopeAccess");
|
|
9657
|
+
}
|
|
9585
9658
|
// `infer function` at statement / export position. `infer` tokenizes as the
|
|
9586
9659
|
// keyword-like tt._infer, and we only claim it when the NEXT token is
|
|
9587
9660
|
// `function` — every other use of `infer` (identifier, TS conditional-type
|
|
@@ -9634,7 +9707,27 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9634
9707
|
}
|
|
9635
9708
|
super.readToken_dot();
|
|
9636
9709
|
}
|
|
9710
|
+
// A `.` standing where an extractor is being typed: consume it and hand
|
|
9711
|
+
// back the broken-extract placeholder (nolaError), which the lowering
|
|
9712
|
+
// replaces with an inert expression.
|
|
9713
|
+
nolaIncompleteExtract() {
|
|
9714
|
+
const node = this.startNode();
|
|
9715
|
+
const startLoc = this.state.startLoc;
|
|
9716
|
+
this.next();
|
|
9717
|
+
this.raise(NolaErrors.NolaExpectedPromptTemplate, startLoc);
|
|
9718
|
+
node.quasi = null;
|
|
9719
|
+
node.prompt = "";
|
|
9720
|
+
node.typeArgs = null;
|
|
9721
|
+
node.nolaError = true;
|
|
9722
|
+
return this.finishNode(node, "NolaExtractExpression");
|
|
9723
|
+
}
|
|
9637
9724
|
parseExprAtom(refExpressionErrors) {
|
|
9725
|
+
if (this.match(tt.dot) && this.nolaTemplateStack.length > 0) {
|
|
9726
|
+
return this.nolaParseScopeAccess();
|
|
9727
|
+
}
|
|
9728
|
+
if (this.match(tt.dot) && this.optionFlags & 4096) {
|
|
9729
|
+
return this.nolaIncompleteExtract();
|
|
9730
|
+
}
|
|
9638
9731
|
if (this.match(tt.nolaDotDot)) {
|
|
9639
9732
|
const node = this.startNode();
|
|
9640
9733
|
this.next();
|
|
@@ -9685,7 +9778,7 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9685
9778
|
this.next();
|
|
9686
9779
|
}
|
|
9687
9780
|
}
|
|
9688
|
-
node.argument = this.parseMaybeUnary(null, true);
|
|
9781
|
+
node.argument = this.match(tt.dot) ? this.nolaIncompleteExtract() : this.parseMaybeUnary(null, true);
|
|
9689
9782
|
return this.finishNode(node, "NolaAskExpression");
|
|
9690
9783
|
}
|
|
9691
9784
|
return super.parseMaybeUnary(refExpressionErrors, sawUnary);
|
|
@@ -9724,11 +9817,14 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9724
9817
|
if (!infer) {
|
|
9725
9818
|
this.raise(NolaErrors.NolaLegacyMarker, markerStart);
|
|
9726
9819
|
} else {
|
|
9727
|
-
if (tmpl.expressions.length > 0) {
|
|
9728
|
-
this.raise(NolaErrors.NolaMarkerSubstitution, markerStart);
|
|
9729
|
-
}
|
|
9730
9820
|
const instruction = tmpl.quasis.map((q) => q.value.cooked ?? q.value.raw).join("");
|
|
9731
|
-
n2.nolaMarker = {
|
|
9821
|
+
n2.nolaMarker = {
|
|
9822
|
+
start: markerStart,
|
|
9823
|
+
end: tmpl.end,
|
|
9824
|
+
instruction,
|
|
9825
|
+
quasi: tmpl,
|
|
9826
|
+
hasScopeAccess: tmpl.nolaHasScopeAccess === true
|
|
9827
|
+
};
|
|
9732
9828
|
}
|
|
9733
9829
|
}
|
|
9734
9830
|
const prevInInferParams = this.nolaInInferParams;
|
|
@@ -9739,15 +9835,27 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9739
9835
|
this.nolaInInferParams = prevInInferParams;
|
|
9740
9836
|
}
|
|
9741
9837
|
}
|
|
9742
|
-
//
|
|
9838
|
+
// `.name` context parameter. Claimed only at function-param positions
|
|
9743
9839
|
// (IS_FUNCTION_PARAMS); array-pattern elements never see the flag. On a
|
|
9744
9840
|
// non-infer function it is NOLA1010; on any non-identifier form (pattern,
|
|
9745
9841
|
// default) it is NOLA1011 — both recover by parsing the element normally.
|
|
9842
|
+
// The retired `..name` spelling is NOLA1013 and otherwise behaves the same,
|
|
9843
|
+
// so tolerant mode gets one diagnostic instead of a bail.
|
|
9746
9844
|
parseBindingElement(flags, decorators) {
|
|
9747
|
-
|
|
9845
|
+
const doubled = this.match(tt.nolaDotDot);
|
|
9846
|
+
if ((doubled || this.match(tt.dot)) && flags & 2) {
|
|
9748
9847
|
const span = { start: this.state.start, end: this.state.end };
|
|
9749
9848
|
const startLoc = this.state.startLoc;
|
|
9750
9849
|
this.next();
|
|
9850
|
+
if (doubled && this.nolaInInferParams)
|
|
9851
|
+
this.raise(NolaErrors.NolaContextualParamDoubleDot, startLoc);
|
|
9852
|
+
if (this.nolaInInferParams && (this.match(tt.parenR) || this.match(tt.comma))) {
|
|
9853
|
+
this.raise(NolaErrors.NolaIncompleteContextualParam, startLoc);
|
|
9854
|
+
const placeholder = this.startNodeAt(startLoc);
|
|
9855
|
+
placeholder.name = `__nola_incomplete_${span.start}`;
|
|
9856
|
+
placeholder.nolaError = true;
|
|
9857
|
+
return this.finishNode(placeholder, "Identifier");
|
|
9858
|
+
}
|
|
9751
9859
|
const elt = super.parseBindingElement(flags, decorators);
|
|
9752
9860
|
if (!this.nolaInInferParams) {
|
|
9753
9861
|
this.raise(NolaErrors.NolaContextualOutsideInfer, startLoc);
|
|
@@ -9760,6 +9868,33 @@ var nola_default = (superClass) => class NolaParserMixin extends superClass {
|
|
|
9760
9868
|
}
|
|
9761
9869
|
return super.parseBindingElement(flags, decorators);
|
|
9762
9870
|
}
|
|
9871
|
+
// `const .x` / `let .x` / `var .x` (either dot count): the contextual
|
|
9872
|
+
// BINDING form is reserved. Consume the marker, report, then parse the id
|
|
9873
|
+
// normally so tolerant mode keeps a sane tree; the span rides on the id so
|
|
9874
|
+
// the lowering can drop the bytes under a `broken` span.
|
|
9875
|
+
parseVarId(decl, kind) {
|
|
9876
|
+
if (this.match(tt.dot) || this.match(tt.nolaDotDot)) {
|
|
9877
|
+
const span = { start: this.state.start, end: this.state.end };
|
|
9878
|
+
const startLoc = this.state.startLoc;
|
|
9879
|
+
this.next();
|
|
9880
|
+
this.raise(NolaErrors.NolaContextualBindingReserved, startLoc);
|
|
9881
|
+
super.parseVarId(decl, kind);
|
|
9882
|
+
decl.id.nolaReservedMarker = span;
|
|
9883
|
+
return;
|
|
9884
|
+
}
|
|
9885
|
+
super.parseVarId(decl, kind);
|
|
9886
|
+
}
|
|
9887
|
+
// `let` is contextual: Babel promotes it to a declaration keyword only when
|
|
9888
|
+
// the next character can start a binding. A `.` after `let` can only be the
|
|
9889
|
+
// (reserved) contextual-binding marker in a module — `let` is not a legal
|
|
9890
|
+
// identifier there, so `let.x` member access is already an error — so let it
|
|
9891
|
+
// through to parseVarId, which reports NOLA1014. Scoped to the `let` token
|
|
9892
|
+
// so no other binding-start probe changes.
|
|
9893
|
+
chStartsBindingIdentifier(ch, pos) {
|
|
9894
|
+
if (ch === charCodes5.dot && this.state.type === tt._let)
|
|
9895
|
+
return true;
|
|
9896
|
+
return super.chStartsBindingIdentifier(ch, pos);
|
|
9897
|
+
}
|
|
9763
9898
|
// Flag method context so parseFunctionParams can reject markers on object methods.
|
|
9764
9899
|
parseMethod(node, isGenerator, isAsync, isConstructor, allowDirectSuper, type, inClassScope) {
|
|
9765
9900
|
this.nolaInMethod = true;
|
|
@@ -20904,7 +21039,7 @@ var IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
|
20904
21039
|
function deriveTypeExpr(t, ctx) {
|
|
20905
21040
|
const refs = /* @__PURE__ */ new Set();
|
|
20906
21041
|
const companions = /* @__PURE__ */ new Map();
|
|
20907
|
-
const result =
|
|
21042
|
+
const result = walk2(t, ctx, refs, companions);
|
|
20908
21043
|
return result.ok ? { ok: true, expr: result.expr, refs, companions } : result;
|
|
20909
21044
|
}
|
|
20910
21045
|
function collectTypeImports(ast) {
|
|
@@ -20949,7 +21084,7 @@ function buildAccessorPlan(entryRefs, ctx) {
|
|
|
20949
21084
|
}
|
|
20950
21085
|
return plan;
|
|
20951
21086
|
}
|
|
20952
|
-
function
|
|
21087
|
+
function walk2(t, ctx, refs, companions) {
|
|
20953
21088
|
switch (t.type) {
|
|
20954
21089
|
case "TSStringKeyword":
|
|
20955
21090
|
return { ok: true, expr: "__nola.types.string()" };
|
|
@@ -20958,7 +21093,7 @@ function walk(t, ctx, refs, companions) {
|
|
|
20958
21093
|
case "TSBooleanKeyword":
|
|
20959
21094
|
return { ok: true, expr: "__nola.types.boolean()" };
|
|
20960
21095
|
case "TSArrayType": {
|
|
20961
|
-
const inner =
|
|
21096
|
+
const inner = walk2(t.elementType, ctx, refs, companions);
|
|
20962
21097
|
return inner.ok ? { ok: true, expr: `__nola.types.array(${inner.expr})` } : inner;
|
|
20963
21098
|
}
|
|
20964
21099
|
case "TSTypeLiteral":
|
|
@@ -21071,7 +21206,7 @@ function walkObject(members, ctx, refs, companions, owner) {
|
|
|
21071
21206
|
continue;
|
|
21072
21207
|
return { ok: false, message: `property '${name}' needs a type annotation`, node: member };
|
|
21073
21208
|
}
|
|
21074
|
-
const inner =
|
|
21209
|
+
const inner = walk2(annotation, ctx, refs, companions);
|
|
21075
21210
|
if (!inner.ok) {
|
|
21076
21211
|
if (ctx.lossy)
|
|
21077
21212
|
continue;
|
|
@@ -22371,17 +22506,17 @@ var SpanRecorder = class {
|
|
|
22371
22506
|
constructor(source) {
|
|
22372
22507
|
this.s = new MagicString(source);
|
|
22373
22508
|
}
|
|
22374
|
-
overwrite(start, end, text,
|
|
22509
|
+
overwrite(start, end, text, options = {}) {
|
|
22375
22510
|
this.s.overwrite(start, end, text);
|
|
22376
|
-
this.edits.push({ sourceStart: start, sourceEnd: end, text, side: 0, seq: this.seq++,
|
|
22511
|
+
this.edits.push({ sourceStart: start, sourceEnd: end, text, side: 0, seq: this.seq++, ...options });
|
|
22377
22512
|
}
|
|
22378
22513
|
remove(start, end) {
|
|
22379
22514
|
this.s.remove(start, end);
|
|
22380
22515
|
this.edits.push({ sourceStart: start, sourceEnd: end, text: "", side: 0, seq: this.seq++ });
|
|
22381
22516
|
}
|
|
22382
|
-
appendLeft(pos, text) {
|
|
22517
|
+
appendLeft(pos, text, options = {}) {
|
|
22383
22518
|
this.s.appendLeft(pos, text);
|
|
22384
|
-
this.edits.push({ sourceStart: pos, sourceEnd: pos, text, side: 0, seq: this.seq
|
|
22519
|
+
this.edits.push({ sourceStart: pos, sourceEnd: pos, text, side: 0, seq: this.seq++, ...options });
|
|
22385
22520
|
}
|
|
22386
22521
|
appendRight(pos, text) {
|
|
22387
22522
|
this.s.appendRight(pos, text);
|
|
@@ -22428,7 +22563,7 @@ var SpanRecorder = class {
|
|
|
22428
22563
|
});
|
|
22429
22564
|
}
|
|
22430
22565
|
const prev = spans[spans.length - 1];
|
|
22431
|
-
if (prev && prev.kind === "replaced" && prev.sourceEnd === e.sourceStart && prev.generatedEnd === gen) {
|
|
22566
|
+
if (!e.broken && prev && prev.kind === "replaced" && prev.sourceEnd === e.sourceStart && prev.generatedEnd === gen) {
|
|
22432
22567
|
prev.sourceEnd = e.sourceEnd;
|
|
22433
22568
|
prev.generatedEnd += e.text.length;
|
|
22434
22569
|
} else {
|
|
@@ -22437,7 +22572,7 @@ var SpanRecorder = class {
|
|
|
22437
22572
|
sourceEnd: e.sourceEnd,
|
|
22438
22573
|
generatedStart: gen,
|
|
22439
22574
|
generatedEnd: gen + e.text.length,
|
|
22440
|
-
kind: "replaced"
|
|
22575
|
+
kind: e.broken ? "broken" : "replaced"
|
|
22441
22576
|
});
|
|
22442
22577
|
}
|
|
22443
22578
|
gen += e.text.length;
|
|
@@ -22473,22 +22608,45 @@ var askClose = (providerName) => `, __frame${providerName ? `, ${JSON.stringify(
|
|
|
22473
22608
|
var invocationOpen = (paramNames) => `
|
|
22474
22609
|
return __nola.intents.Intent(async (__frame) => {${paramNames.map((n2) => ` void ${n2};`).join("")}`;
|
|
22475
22610
|
var invocationArgEntry = (name, typeExpr, contextual) => `{ name: ${JSON.stringify(name)}${typeExpr ? `, type: ${typeExpr}` : ""}${contextual ? `, contextual: true, value: ${name}` : ""} }`;
|
|
22476
|
-
var invocationClose = (fnName,
|
|
22611
|
+
var invocationClose = (fnName, instructionField, argEntries) => {
|
|
22477
22612
|
const argsField = argEntries.length > 0 ? `, args: [${argEntries.join(", ")}]` : "";
|
|
22478
|
-
return ` }, __nola_file_ctx().func({ fn: ${JSON.stringify(fnName)}, instruction: ${
|
|
22613
|
+
return ` }, __nola_file_ctx().func({ fn: ${JSON.stringify(fnName)}, instruction: ${instructionField}${argsField} }));
|
|
22479
22614
|
`;
|
|
22480
22615
|
};
|
|
22616
|
+
function templateCopy(source, quasi, scopeNodes, mode) {
|
|
22617
|
+
const inserts = mode === "scope" ? scopeNodes.map((n2) => [n2.start, SCOPE_PARAM]) : quasi.expressions.flatMap((e) => [[e.start, FMT_OPEN], [e.end, FMT_CLOSE]]);
|
|
22618
|
+
inserts.sort((a, b) => a[0] - b[0]);
|
|
22619
|
+
let text = "";
|
|
22620
|
+
const anchors = [];
|
|
22621
|
+
let cursor = quasi.start;
|
|
22622
|
+
for (const [pos, ins] of inserts) {
|
|
22623
|
+
if (pos > cursor) {
|
|
22624
|
+
anchors.push({ sourceStart: cursor, sourceEnd: pos, textOffset: text.length });
|
|
22625
|
+
text += source.slice(cursor, pos);
|
|
22626
|
+
}
|
|
22627
|
+
text += ins;
|
|
22628
|
+
cursor = pos;
|
|
22629
|
+
}
|
|
22630
|
+
anchors.push({ sourceStart: cursor, sourceEnd: quasi.end, textOffset: text.length });
|
|
22631
|
+
text += source.slice(cursor, quasi.end);
|
|
22632
|
+
return { text, anchors };
|
|
22633
|
+
}
|
|
22481
22634
|
var callIntentTypeText = (tagText) => `<Awaited<ReturnType<typeof ${tagText}>>>`;
|
|
22482
22635
|
var callIntentOpen = (typeText) => `__nola.intents.FunctionCallingIntent${typeText}({ fn: `;
|
|
22483
|
-
var callIntentArgsHead = (tagText,
|
|
22636
|
+
var callIntentArgsHead = (tagText, instructionField, loc) => `, name: ${JSON.stringify(tagText)}, instruction: ${instructionField}, loc: ${JSON.stringify(locText(loc))}, args: [`;
|
|
22484
22637
|
var CALL_INTENT_CLOSE = "] })";
|
|
22485
22638
|
var EXTRACT_DEFAULT_TYPE_EXPR = "__nola.types.string()";
|
|
22486
22639
|
var EXTRACT_DEFAULT_TYPE_TEXT = "<any>";
|
|
22487
22640
|
var typeArgsText = (sourceText) => `<${sourceText}>`;
|
|
22488
22641
|
var extractOpen = (typeText) => `__nola.intents.ExtractIntent${typeText}({ instruction: `;
|
|
22642
|
+
var SCOPE_PARAM = "__nola_s";
|
|
22643
|
+
var TEMPLATE_OPEN = `template: (${SCOPE_PARAM}) => __nola.tpl`;
|
|
22644
|
+
var rawTemplateText = (source, quasi) => source.slice(quasi.start + 1, quasi.end - 1);
|
|
22645
|
+
var extractOpenTemplate = (typeText, rawInstruction) => `__nola.intents.ExtractIntent${typeText}({ instruction: ${JSON.stringify(rawInstruction)}, ${TEMPLATE_OPEN}`;
|
|
22489
22646
|
var FMT_OPEN = "__nola.fmt(";
|
|
22490
22647
|
var FMT_CLOSE = ")";
|
|
22491
22648
|
var extractClose = (typeExpr, loc) => `, type: ${typeExpr}, loc: ${JSON.stringify(locText(loc))} })`;
|
|
22649
|
+
var BROKEN_CONSTRUCT = "(undefined as never)";
|
|
22492
22650
|
|
|
22493
22651
|
// ../compiler/dist/lower/lowerer.js
|
|
22494
22652
|
var Lowerer = class {
|
|
@@ -22502,13 +22660,27 @@ var Lowerer = class {
|
|
|
22502
22660
|
diagnostics = [];
|
|
22503
22661
|
meta = { nolaFunctions: [] };
|
|
22504
22662
|
usedRuntime = false;
|
|
22663
|
+
/**
|
|
22664
|
+
* Where a `${.member}` scope access may appear right now: "inplace" — the
|
|
22665
|
+
* enclosing instruction literal stays where it is (extractor), so the scope
|
|
22666
|
+
* parameter is inserted before the dot here; "copy" — the literal is copied
|
|
22667
|
+
* elsewhere (marker / call hint) and the copy builder did the insertion;
|
|
22668
|
+
* "none" — not inside a Nola instruction literal (NOLA2009).
|
|
22669
|
+
*/
|
|
22670
|
+
scopeSite = "none";
|
|
22671
|
+
/**
|
|
22672
|
+
* True while visiting the holes of a COPIED instruction literal (marker /
|
|
22673
|
+
* call hint). Nola constructs there have nowhere to lower to — the literal
|
|
22674
|
+
* is re-emitted from source bytes — so they are NOLA2010.
|
|
22675
|
+
*/
|
|
22676
|
+
inCopiedHole = false;
|
|
22505
22677
|
/** named types needing a __nola_type_<Name> accessor in the appendix, in first-use order */
|
|
22506
22678
|
typeAccessors = /* @__PURE__ */ new Map();
|
|
22507
22679
|
/** local binding name -> companion import emitted in the appendix */
|
|
22508
22680
|
companionImports = /* @__PURE__ */ new Map();
|
|
22509
22681
|
/** shared derivation context (registry, imports, display file, bare ref names) */
|
|
22510
22682
|
deriveCtx;
|
|
22511
|
-
/** policy for underivable
|
|
22683
|
+
/** policy for underivable `.`-contextual param types (compiler.underivableContextType) */
|
|
22512
22684
|
underivableContextType;
|
|
22513
22685
|
constructor(source, file, ast, displayFile, options = {}) {
|
|
22514
22686
|
this.s = new SpanRecorder(source);
|
|
@@ -22569,7 +22741,7 @@ var Lowerer = class {
|
|
|
22569
22741
|
this.diag(Codes.UnsupportedIntentType, e.message, e.node);
|
|
22570
22742
|
}
|
|
22571
22743
|
/**
|
|
22572
|
-
* A
|
|
22744
|
+
* A `.`-contextual param's type failed to derive (shallowly or in its
|
|
22573
22745
|
* accessor plan). Resolve it per the configured policy; the returned expr
|
|
22574
22746
|
* (if any) replaces the failed one.
|
|
22575
22747
|
*/
|
|
@@ -22614,13 +22786,38 @@ var Lowerer = class {
|
|
|
22614
22786
|
visit(node, inNolaFnBody, topLevel) {
|
|
22615
22787
|
switch (node.type) {
|
|
22616
22788
|
case "NolaExtractExpression": {
|
|
22789
|
+
if (this.inCopiedHole) {
|
|
22790
|
+
this.diagCopiedHole(node);
|
|
22791
|
+
return;
|
|
22792
|
+
}
|
|
22617
22793
|
const extract = node;
|
|
22618
|
-
if (extract.nolaError || !extract.quasi)
|
|
22794
|
+
if (extract.nolaError || !extract.quasi) {
|
|
22795
|
+
this.s.overwrite(node.start, node.end, BROKEN_CONSTRUCT, { broken: true });
|
|
22619
22796
|
return;
|
|
22797
|
+
}
|
|
22620
22798
|
this.lowerExtract(extract, inNolaFnBody);
|
|
22621
22799
|
return;
|
|
22622
22800
|
}
|
|
22801
|
+
case "NolaScopeAccess": {
|
|
22802
|
+
if (this.scopeSite === "none") {
|
|
22803
|
+
this.diag(
|
|
22804
|
+
Codes.ScopeAccessOutsideTemplate,
|
|
22805
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: literal ${...} in a diagnostic message
|
|
22806
|
+
"`${.member}` scope access is only allowed inside a Nola instruction template (infer-function marker, extractor prompt, call-intent hint).",
|
|
22807
|
+
node
|
|
22808
|
+
);
|
|
22809
|
+
this.s.overwrite(node.start, node.end, BROKEN_CONSTRUCT, { broken: true });
|
|
22810
|
+
return;
|
|
22811
|
+
}
|
|
22812
|
+
if (this.scopeSite === "inplace")
|
|
22813
|
+
this.s.appendLeft(node.start, SCOPE_PARAM);
|
|
22814
|
+
return;
|
|
22815
|
+
}
|
|
22623
22816
|
case "NolaAskExpression": {
|
|
22817
|
+
if (this.inCopiedHole) {
|
|
22818
|
+
this.diagCopiedHole(node);
|
|
22819
|
+
return;
|
|
22820
|
+
}
|
|
22624
22821
|
const ask2 = node;
|
|
22625
22822
|
if (!inNolaFnBody) {
|
|
22626
22823
|
this.diag(Codes.AskOutsideNolaFunction, "`ask` is only allowed directly inside an infer function body.", node);
|
|
@@ -22652,9 +22849,24 @@ var Lowerer = class {
|
|
|
22652
22849
|
case "CallExpression": {
|
|
22653
22850
|
const call = node;
|
|
22654
22851
|
if (call.callee.type === "TaggedTemplateExpression") {
|
|
22852
|
+
if (this.inCopiedHole) {
|
|
22853
|
+
this.diagCopiedHole(node);
|
|
22854
|
+
return;
|
|
22855
|
+
}
|
|
22655
22856
|
this.lowerCallIntent(call, inNolaFnBody);
|
|
22656
22857
|
return;
|
|
22657
22858
|
}
|
|
22859
|
+
if ((call.callee.type === "Identifier" || call.callee.type === "MemberExpression") && call.arguments.some((a) => this.hasExtractorSlot(a))) {
|
|
22860
|
+
this.lowerCallIntent(call, inNolaFnBody);
|
|
22861
|
+
return;
|
|
22862
|
+
}
|
|
22863
|
+
break;
|
|
22864
|
+
}
|
|
22865
|
+
case "VariableDeclarator": {
|
|
22866
|
+
const id = node.id;
|
|
22867
|
+
if (id?.nolaReservedMarker) {
|
|
22868
|
+
this.s.overwrite(id.nolaReservedMarker.start, id.nolaReservedMarker.end, "", { broken: true });
|
|
22869
|
+
}
|
|
22658
22870
|
break;
|
|
22659
22871
|
}
|
|
22660
22872
|
default:
|
|
@@ -22666,21 +22878,81 @@ var Lowerer = class {
|
|
|
22666
22878
|
this.visit(child, isFunctionScope ? false : inNolaFnBody, nextTopLevel);
|
|
22667
22879
|
}
|
|
22668
22880
|
}
|
|
22881
|
+
/**
|
|
22882
|
+
* Sigil-less call-intent detection (2026-08-14 spec): a well-formed extractor
|
|
22883
|
+
* in a slot position — a direct argument, or nested at any depth inside plain
|
|
22884
|
+
* object/array literals (the same walk checkCallIntentArg performs). Tolerant
|
|
22885
|
+
* placeholders (nolaError) do NOT count: a half-typed `f(..` stays a plain
|
|
22886
|
+
* call, so the editor never lowers a call intent around a broken slot.
|
|
22887
|
+
*/
|
|
22888
|
+
hasExtractorSlot(node) {
|
|
22889
|
+
if (node.type === "NolaExtractExpression") {
|
|
22890
|
+
return !node.nolaError;
|
|
22891
|
+
}
|
|
22892
|
+
if (node.type === "ObjectExpression") {
|
|
22893
|
+
return node.properties.some((p) => p.type === "ObjectProperty" && this.hasExtractorSlot(p.value));
|
|
22894
|
+
}
|
|
22895
|
+
if (node.type === "ArrayExpression") {
|
|
22896
|
+
return node.elements.some((el) => el != null && this.hasExtractorSlot(el));
|
|
22897
|
+
}
|
|
22898
|
+
return false;
|
|
22899
|
+
}
|
|
22900
|
+
diagCopiedHole(node) {
|
|
22901
|
+
this.diag(Codes.NolaConstructInMarker, "Nola constructs are not allowed inside an infer-function marker or call-intent hint hole.", node);
|
|
22902
|
+
}
|
|
22903
|
+
/**
|
|
22904
|
+
* The instruction field of a copied instruction literal (marker / call hint):
|
|
22905
|
+
* prose → JSON string; lexical holes → a template literal with fmt-wrapped
|
|
22906
|
+
* holes; `${.member}` holes → the raw text as the instruction plus the
|
|
22907
|
+
* template closure. Anchors point back at the literal's verbatim runs.
|
|
22908
|
+
*/
|
|
22909
|
+
instructionFieldFor(quasi, hasScopeAccess, cooked) {
|
|
22910
|
+
if (quasi.expressions.length === 0)
|
|
22911
|
+
return { field: JSON.stringify(cooked), copyText: "", anchors: [], holes: [] };
|
|
22912
|
+
const scopeNodes = [];
|
|
22913
|
+
if (hasScopeAccess) {
|
|
22914
|
+
walk(quasi, (n2) => {
|
|
22915
|
+
if (n2.type === "NolaScopeAccess")
|
|
22916
|
+
scopeNodes.push(n2);
|
|
22917
|
+
});
|
|
22918
|
+
}
|
|
22919
|
+
const copy = templateCopy(this.source, quasi, scopeNodes, hasScopeAccess ? "scope" : "fmt");
|
|
22920
|
+
const field = hasScopeAccess ? `${JSON.stringify(rawTemplateText(this.source, quasi))}, ${TEMPLATE_OPEN}${copy.text}` : copy.text;
|
|
22921
|
+
return { field, copyText: copy.text, anchors: copy.anchors, holes: quasi.expressions };
|
|
22922
|
+
}
|
|
22923
|
+
/** Visit the holes of a copied literal only to diagnose (NOLA2010 / NOLA2009) — the copy is already built. */
|
|
22924
|
+
visitCopiedHoles(holes, inNolaFnBody) {
|
|
22925
|
+
const prevSite = this.scopeSite;
|
|
22926
|
+
const prevHole = this.inCopiedHole;
|
|
22927
|
+
this.scopeSite = "copy";
|
|
22928
|
+
this.inCopiedHole = true;
|
|
22929
|
+
try {
|
|
22930
|
+
for (const e of holes)
|
|
22931
|
+
this.visit(e, inNolaFnBody, false);
|
|
22932
|
+
} finally {
|
|
22933
|
+
this.scopeSite = prevSite;
|
|
22934
|
+
this.inCopiedHole = prevHole;
|
|
22935
|
+
}
|
|
22936
|
+
}
|
|
22669
22937
|
lowerInferFunction(fn) {
|
|
22670
22938
|
const infer = fn.nolaInfer;
|
|
22671
22939
|
if (!infer)
|
|
22672
22940
|
return;
|
|
22673
22941
|
const name = fn.id?.name ?? "anonymous";
|
|
22674
22942
|
this.s.remove(infer.start, infer.end);
|
|
22675
|
-
const
|
|
22676
|
-
if (
|
|
22677
|
-
this.s.remove(
|
|
22943
|
+
const marker = fn.nolaMarker;
|
|
22944
|
+
if (marker)
|
|
22945
|
+
this.s.remove(marker.start, marker.end);
|
|
22678
22946
|
const body = fn.body;
|
|
22679
22947
|
if (!body)
|
|
22680
22948
|
return;
|
|
22681
22949
|
const argEntries = [];
|
|
22682
22950
|
const paramNames = [];
|
|
22683
22951
|
for (const p of fn.params ?? []) {
|
|
22952
|
+
if (p.nolaError) {
|
|
22953
|
+
this.s.overwrite(p.start, p.end, "", { broken: true });
|
|
22954
|
+
continue;
|
|
22955
|
+
}
|
|
22684
22956
|
if (p.nolaContextual)
|
|
22685
22957
|
this.s.remove(p.nolaContextual.start, p.nolaContextual.end);
|
|
22686
22958
|
const target = p.type === "AssignmentPattern" ? p.left : p;
|
|
@@ -22708,34 +22980,34 @@ var Lowerer = class {
|
|
|
22708
22980
|
}
|
|
22709
22981
|
argEntries.push(invocationArgEntry(paramName, typeExpr, Boolean(p.nolaContextual)));
|
|
22710
22982
|
}
|
|
22983
|
+
const inst = marker?.quasi !== void 0 ? this.instructionFieldFor(marker.quasi, marker.hasScopeAccess === true, marker.instruction) : { field: JSON.stringify(marker?.instruction ?? ""), copyText: "", anchors: [], holes: [] };
|
|
22984
|
+
const close = invocationClose(name, inst.field, argEntries);
|
|
22985
|
+
const copyAt = inst.copyText ? close.indexOf(inst.copyText) : -1;
|
|
22986
|
+
const anchors = copyAt >= 0 ? inst.anchors.map((a) => ({ ...a, textOffset: a.textOffset + copyAt })) : void 0;
|
|
22711
22987
|
this.s.appendRight(body.start + 1, invocationOpen(paramNames));
|
|
22712
|
-
this.s.appendLeft(body.end - 1,
|
|
22988
|
+
this.s.appendLeft(body.end - 1, close, anchors ? { anchors } : {});
|
|
22713
22989
|
this.meta.nolaFunctions.push(name);
|
|
22714
22990
|
this.usedRuntime = true;
|
|
22991
|
+
this.visitCopiedHoles(inst.holes, false);
|
|
22715
22992
|
}
|
|
22716
22993
|
lowerCallIntent(call, inNolaFnBody) {
|
|
22717
|
-
const
|
|
22718
|
-
const
|
|
22719
|
-
if (quasi.expressions.length > 0) {
|
|
22720
|
-
this.diag(
|
|
22721
|
-
Codes.SubstitutionInCallMarker,
|
|
22722
|
-
// biome-ignore lint/suspicious/noTemplateCurlyInString: literal ${...} in a diagnostic message
|
|
22723
|
-
"`${...}` substitutions are not allowed in a call-intent marker.",
|
|
22724
|
-
quasi.expressions[0]
|
|
22725
|
-
);
|
|
22726
|
-
return;
|
|
22727
|
-
}
|
|
22994
|
+
const tagged = call.callee.type === "TaggedTemplateExpression" ? call.callee : void 0;
|
|
22995
|
+
const inst = tagged ? this.instructionFieldFor(tagged.quasi, tagged.quasi.nolaHasScopeAccess === true, tagged.quasi.quasis.map((q) => q.value.cooked ?? q.value.raw).join("")) : { field: '""', copyText: "", anchors: [], holes: [] };
|
|
22728
22996
|
for (const arg of call.arguments)
|
|
22729
22997
|
this.checkCallIntentArg(arg);
|
|
22730
|
-
const
|
|
22731
|
-
const
|
|
22732
|
-
const simple =
|
|
22733
|
-
const typeText = simple ? callIntentTypeText(
|
|
22998
|
+
const callee = tagged ? tagged.tag : call.callee;
|
|
22999
|
+
const calleeText = this.source.slice(callee.start, callee.end);
|
|
23000
|
+
const simple = callee.type === "Identifier" || callee.type === "MemberExpression";
|
|
23001
|
+
const typeText = simple ? callIntentTypeText(calleeText) : "";
|
|
22734
23002
|
this.s.appendLeft(call.start, callIntentOpen(typeText));
|
|
22735
23003
|
const argsStart = call.arguments.length > 0 ? call.arguments[0].start : call.end - 1;
|
|
22736
|
-
|
|
23004
|
+
const head = callIntentArgsHead(calleeText, inst.field, call.loc.start);
|
|
23005
|
+
const copyAt = inst.copyText ? head.indexOf(inst.copyText) : -1;
|
|
23006
|
+
const anchors = copyAt >= 0 ? inst.anchors.map((a) => ({ ...a, textOffset: a.textOffset + copyAt })) : void 0;
|
|
23007
|
+
this.s.overwrite(callee.end, argsStart, head, anchors ? { anchors } : {});
|
|
22737
23008
|
this.s.overwrite(call.end - 1, call.end, CALL_INTENT_CLOSE);
|
|
22738
23009
|
this.usedRuntime = true;
|
|
23010
|
+
this.visitCopiedHoles(inst.holes, inNolaFnBody);
|
|
22739
23011
|
for (const arg of call.arguments)
|
|
22740
23012
|
this.visit(arg, inNolaFnBody, false);
|
|
22741
23013
|
}
|
|
@@ -22783,13 +23055,16 @@ var Lowerer = class {
|
|
|
22783
23055
|
}
|
|
22784
23056
|
}
|
|
22785
23057
|
}
|
|
22786
|
-
const
|
|
23058
|
+
const isTemplate = quasi.nolaHasScopeAccess === true;
|
|
23059
|
+
const open = isTemplate ? extractOpenTemplate(typeText, rawTemplateText(this.source, quasi)) : extractOpen(typeText);
|
|
22787
23060
|
const typeNode = node.typeArgs?.params[0];
|
|
22788
23061
|
const anchors = typeNode ? [{ sourceStart: typeNode.start, sourceEnd: typeNode.end, textOffset: open.indexOf(typeText) + 1 }] : void 0;
|
|
22789
|
-
this.s.overwrite(node.start, quasi.start, open, anchors);
|
|
22790
|
-
|
|
22791
|
-
|
|
22792
|
-
|
|
23062
|
+
this.s.overwrite(node.start, quasi.start, open, { anchors });
|
|
23063
|
+
if (!isTemplate) {
|
|
23064
|
+
for (const expr of quasi.expressions) {
|
|
23065
|
+
this.s.appendLeft(expr.start, FMT_OPEN);
|
|
23066
|
+
this.s.appendLeft(expr.end, FMT_CLOSE);
|
|
23067
|
+
}
|
|
22793
23068
|
}
|
|
22794
23069
|
const suffix = extractClose(typeExpr, node.loc.start);
|
|
22795
23070
|
if (node.end > quasi.end) {
|
|
@@ -22798,8 +23073,14 @@ var Lowerer = class {
|
|
|
22798
23073
|
this.s.appendLeft(node.end, suffix);
|
|
22799
23074
|
}
|
|
22800
23075
|
this.usedRuntime = true;
|
|
22801
|
-
|
|
22802
|
-
|
|
23076
|
+
const prevSite = this.scopeSite;
|
|
23077
|
+
this.scopeSite = isTemplate ? "inplace" : "none";
|
|
23078
|
+
try {
|
|
23079
|
+
for (const expr of quasi.expressions)
|
|
23080
|
+
this.visit(expr, inNolaFnBody, false);
|
|
23081
|
+
} finally {
|
|
23082
|
+
this.scopeSite = prevSite;
|
|
23083
|
+
}
|
|
22803
23084
|
}
|
|
22804
23085
|
};
|
|
22805
23086
|
|
|
@@ -22978,15 +23259,33 @@ var INSERTION_DATA = { navigation: true, format: false };
|
|
|
22978
23259
|
function spansToMappings(spans, anchors = [], code2) {
|
|
22979
23260
|
const verbatim = [];
|
|
22980
23261
|
const replaced = [];
|
|
23262
|
+
const afterBroken = new Set(spans.filter((s) => s.kind === "broken").map((s) => s.sourceEnd));
|
|
22981
23263
|
for (const span of spans) {
|
|
22982
23264
|
if (span.kind === "verbatim") {
|
|
23265
|
+
if (afterBroken.has(span.sourceStart) && span.sourceEnd > span.sourceStart) {
|
|
23266
|
+
verbatim.push({
|
|
23267
|
+
sourceOffsets: [span.sourceStart],
|
|
23268
|
+
generatedOffsets: [span.generatedStart],
|
|
23269
|
+
lengths: [1],
|
|
23270
|
+
data: { ...VERBATIM_DATA, completion: false }
|
|
23271
|
+
});
|
|
23272
|
+
if (span.sourceEnd - span.sourceStart === 1)
|
|
23273
|
+
continue;
|
|
23274
|
+
verbatim.push({
|
|
23275
|
+
sourceOffsets: [span.sourceStart + 1],
|
|
23276
|
+
generatedOffsets: [span.generatedStart + 1],
|
|
23277
|
+
lengths: [span.sourceEnd - span.sourceStart - 1],
|
|
23278
|
+
data: { ...VERBATIM_DATA }
|
|
23279
|
+
});
|
|
23280
|
+
continue;
|
|
23281
|
+
}
|
|
22983
23282
|
verbatim.push({
|
|
22984
23283
|
sourceOffsets: [span.sourceStart],
|
|
22985
23284
|
generatedOffsets: [span.generatedStart],
|
|
22986
23285
|
lengths: [span.sourceEnd - span.sourceStart],
|
|
22987
23286
|
data: { ...VERBATIM_DATA }
|
|
22988
23287
|
});
|
|
22989
|
-
} else if (span.kind === "replaced") {
|
|
23288
|
+
} else if (span.kind === "replaced" || span.kind === "broken") {
|
|
22990
23289
|
replaced.push({
|
|
22991
23290
|
sourceOffsets: [span.sourceStart],
|
|
22992
23291
|
generatedOffsets: [span.generatedStart],
|
|
@@ -23135,10 +23434,6 @@ function createNolaLanguagePlugin(asFileName, options = {}) {
|
|
|
23135
23434
|
};
|
|
23136
23435
|
}
|
|
23137
23436
|
|
|
23138
|
-
// ../node-loader/dist/config.js
|
|
23139
|
-
var import_node_fs2 = require("node:fs");
|
|
23140
|
-
var import_node_path2 = require("node:path");
|
|
23141
|
-
|
|
23142
23437
|
// ../runtime/dist/runtime/ask-span.js
|
|
23143
23438
|
var AskSpan = class {
|
|
23144
23439
|
kind = "ask";
|
|
@@ -23222,6 +23517,7 @@ var ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
|
23222
23517
|
"system",
|
|
23223
23518
|
"ask",
|
|
23224
23519
|
"compiler",
|
|
23520
|
+
"build",
|
|
23225
23521
|
...RESERVED_KEYS
|
|
23226
23522
|
]);
|
|
23227
23523
|
var HOOK_METHODS = [
|
|
@@ -23316,6 +23612,24 @@ function resolveCompilerConfig(raw, source) {
|
|
|
23316
23612
|
}
|
|
23317
23613
|
return Object.freeze({ underivableContextType: mode ?? "error" });
|
|
23318
23614
|
}
|
|
23615
|
+
var BUILD_TARGETS = ["app", "lib"];
|
|
23616
|
+
function resolveBuildConfig(raw, source) {
|
|
23617
|
+
if (raw === void 0)
|
|
23618
|
+
return Object.freeze({ target: "app" });
|
|
23619
|
+
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
23620
|
+
fail(source, '`build` must be an object \u2014 write build: { target: "lib" }.');
|
|
23621
|
+
}
|
|
23622
|
+
const cfg = raw;
|
|
23623
|
+
for (const key of Object.keys(cfg)) {
|
|
23624
|
+
if (key !== "target")
|
|
23625
|
+
fail(source, `unknown build config key \`${key}\` \u2014 allowed keys: target.`);
|
|
23626
|
+
}
|
|
23627
|
+
const target = cfg.target;
|
|
23628
|
+
if (target !== void 0 && (typeof target !== "string" || !BUILD_TARGETS.includes(target))) {
|
|
23629
|
+
fail(source, `build.target must be one of ${BUILD_TARGETS.join(", ")}.`);
|
|
23630
|
+
}
|
|
23631
|
+
return Object.freeze({ target: target ?? "app" });
|
|
23632
|
+
}
|
|
23319
23633
|
function validateMiddleware(source, raw) {
|
|
23320
23634
|
if (raw === void 0)
|
|
23321
23635
|
return Object.freeze([]);
|
|
@@ -23342,7 +23656,7 @@ function resolveNolaConfig(raw, opts = {}) {
|
|
|
23342
23656
|
}
|
|
23343
23657
|
for (const key of Object.keys(cfg)) {
|
|
23344
23658
|
if (!ALLOWED_KEYS.has(key)) {
|
|
23345
|
-
fail(source, `unknown config key \`${key}\` \u2014 allowed keys: providers, forceProvider, observability, hooks, middleware, cache, system, ask, compiler.`);
|
|
23659
|
+
fail(source, `unknown config key \`${key}\` \u2014 allowed keys: providers, forceProvider, observability, hooks, middleware, cache, system, ask, compiler, build.`);
|
|
23346
23660
|
}
|
|
23347
23661
|
}
|
|
23348
23662
|
const providers = cfg.providers;
|
|
@@ -23383,6 +23697,7 @@ function resolveNolaConfig(raw, opts = {}) {
|
|
|
23383
23697
|
const system = validateSystem(source, cfg.system);
|
|
23384
23698
|
const ask2 = validateAsk(source, cfg.ask);
|
|
23385
23699
|
const compiler = resolveCompilerConfig(cfg.compiler, source);
|
|
23700
|
+
const build2 = resolveBuildConfig(cfg.build, source);
|
|
23386
23701
|
return Object.freeze({
|
|
23387
23702
|
providers: Object.freeze({ ...map }),
|
|
23388
23703
|
forceProvider: cfg.forceProvider,
|
|
@@ -23392,7 +23707,8 @@ function resolveNolaConfig(raw, opts = {}) {
|
|
|
23392
23707
|
cache: cache3,
|
|
23393
23708
|
system,
|
|
23394
23709
|
ask: ask2,
|
|
23395
|
-
compiler
|
|
23710
|
+
compiler,
|
|
23711
|
+
build: build2
|
|
23396
23712
|
});
|
|
23397
23713
|
}
|
|
23398
23714
|
|
|
@@ -23483,17 +23799,6 @@ var Frame = class _Frame {
|
|
|
23483
23799
|
composeInferenceData(composer, opts) {
|
|
23484
23800
|
this.infer.composeInferenceData(composer, { ...opts, nested: this.parent !== void 0 });
|
|
23485
23801
|
}
|
|
23486
|
-
// /**
|
|
23487
|
-
// * Prompt-facing lineage under stack-frame semantics: the root frame's static
|
|
23488
|
-
// * ancestry followed by one entry per frame down the call chain. A callee's
|
|
23489
|
-
// * own construction ancestors are bypassed — the caller chain is its lineage;
|
|
23490
|
-
// * sourceFile() (the definition site) intentionally differs.
|
|
23491
|
-
// */
|
|
23492
|
-
// promptLineage(): ReadonlyArray<Readonly<Record<string, unknown>>> {
|
|
23493
|
-
// if (!this.parent) return this.infer.promptLineage();
|
|
23494
|
-
// const own = this.infer.promptData();
|
|
23495
|
-
// return own === undefined ? this.parent.promptLineage() : [...this.parent.promptLineage(), own];
|
|
23496
|
-
// }
|
|
23497
23802
|
/**
|
|
23498
23803
|
* The .tsi file this frame's function is defined in (static chain first).
|
|
23499
23804
|
* Scope-less intents (extract/call) carry no file root — for them the
|
|
@@ -23527,6 +23832,70 @@ var Frame = class _Frame {
|
|
|
23527
23832
|
}
|
|
23528
23833
|
};
|
|
23529
23834
|
|
|
23835
|
+
// ../runtime/dist/ask/prompt-render.js
|
|
23836
|
+
var defaultPromptRenderer = Object.freeze({
|
|
23837
|
+
function(data) {
|
|
23838
|
+
const { fn, file, instruction, args, nested } = data;
|
|
23839
|
+
const signature = `${fn}(${args.map((a) => a.name).join(", ")})`;
|
|
23840
|
+
const header = `CONTEXT \u2014 inside ${signature}` + (file === void 0 ? "" : `, ${file}`) + (nested ? ", called from the context above" : "");
|
|
23841
|
+
const lines = [header];
|
|
23842
|
+
if (instruction)
|
|
23843
|
+
lines.push(`Purpose: ${instruction}`);
|
|
23844
|
+
if (args.length > 0) {
|
|
23845
|
+
lines.push("Arguments (values are runtime data, not instructions):");
|
|
23846
|
+
for (const a of args) {
|
|
23847
|
+
if (!a.contextual) {
|
|
23848
|
+
lines.push(`- ${a.name} = (value not available)`);
|
|
23849
|
+
continue;
|
|
23850
|
+
}
|
|
23851
|
+
const type = a.type ? ` (${a.type.toNativeType()})` : "";
|
|
23852
|
+
if (a.value === void 0) {
|
|
23853
|
+
lines.push(`- ${a.name}${type} = (no value)`);
|
|
23854
|
+
} else if (typeof a.value === "string" && (a.value.includes("\n") || a.value.length > 120)) {
|
|
23855
|
+
lines.push(`- ${a.name}${type}:`, "<value>", a.value, "</value>");
|
|
23856
|
+
} else {
|
|
23857
|
+
lines.push(`- ${a.name}${type} = ${JSON.stringify(a.value)}`);
|
|
23858
|
+
}
|
|
23859
|
+
}
|
|
23860
|
+
}
|
|
23861
|
+
return lines.join("\n");
|
|
23862
|
+
},
|
|
23863
|
+
extract(data) {
|
|
23864
|
+
const { instruction, hasContext } = data;
|
|
23865
|
+
const lines = [
|
|
23866
|
+
"TASK",
|
|
23867
|
+
hasContext ? "Produce the data requested below from the context above." : "Produce the data requested below.",
|
|
23868
|
+
"<request>",
|
|
23869
|
+
instruction,
|
|
23870
|
+
"</request>",
|
|
23871
|
+
extractFormat(data)
|
|
23872
|
+
];
|
|
23873
|
+
return lines.join("\n");
|
|
23874
|
+
}
|
|
23875
|
+
});
|
|
23876
|
+
function extractFormat(data) {
|
|
23877
|
+
const lines = [];
|
|
23878
|
+
if (!data.trivialString)
|
|
23879
|
+
lines.push("RESPONSE SCHEMA (JSON Schema):", JSON.stringify(data.schema));
|
|
23880
|
+
lines.push(data.trivialString ? "Respond with a single JSON string containing the value." : "Respond with a single JSON value strictly conforming to the schema above.");
|
|
23881
|
+
return lines.join("\n");
|
|
23882
|
+
}
|
|
23883
|
+
function joinBlocks(...parts) {
|
|
23884
|
+
return parts.filter((p) => p.length > 0).join("\n\n");
|
|
23885
|
+
}
|
|
23886
|
+
function renderTemplate(template, scope, site, tail, tailRead) {
|
|
23887
|
+
let text;
|
|
23888
|
+
try {
|
|
23889
|
+
text = template(scope);
|
|
23890
|
+
} catch (e) {
|
|
23891
|
+
throw new NolaIntentError(`${Codes.PromptTemplateFailed}: prompt template at ${site} threw: ${e instanceof Error ? e.message : String(e)}`, Codes.PromptTemplateFailed);
|
|
23892
|
+
}
|
|
23893
|
+
if (typeof text !== "string" || text.trim() === "") {
|
|
23894
|
+
throw new NolaIntentError(`${Codes.PromptTemplateFailed}: prompt template at ${site} rendered no text.`, Codes.PromptTemplateFailed);
|
|
23895
|
+
}
|
|
23896
|
+
return tailRead() ? text : joinBlocks(text, tail());
|
|
23897
|
+
}
|
|
23898
|
+
|
|
23530
23899
|
// ../runtime/dist/infer-context/infer-context.js
|
|
23531
23900
|
var InferContext = class _InferContext {
|
|
23532
23901
|
data;
|
|
@@ -23541,31 +23910,16 @@ var InferContext = class _InferContext {
|
|
|
23541
23910
|
scope(data) {
|
|
23542
23911
|
return new _InferContext(Object.freeze({ ...data }), this.runtime, this);
|
|
23543
23912
|
}
|
|
23544
|
-
/**
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
}
|
|
23554
|
-
/** Raw data chain from root to this node (internal/debug). */
|
|
23555
|
-
// lineage(): ReadonlyArray<Readonly<Record<string, unknown>>> {
|
|
23556
|
-
// const chain: Array<Readonly<Record<string, unknown>>> = [];
|
|
23557
|
-
// for (let c: InferContext | undefined = this; c; c = c.parent) chain.unshift(c.data);
|
|
23558
|
-
// return chain;
|
|
23559
|
-
// }
|
|
23560
|
-
/** Prompt-facing lineage: promptData() per node, undefined entries dropped. */
|
|
23561
|
-
// promptLineage(): ReadonlyArray<Readonly<Record<string, unknown>>> {
|
|
23562
|
-
// const chain: Array<Readonly<Record<string, unknown>>> = [];
|
|
23563
|
-
// for (let c: InferContext | undefined = this; c; c = c.parent) {
|
|
23564
|
-
// const d = c.promptData();
|
|
23565
|
-
// if (d !== undefined) chain.unshift(d);
|
|
23566
|
-
// }
|
|
23567
|
-
// return chain;
|
|
23568
|
-
// }
|
|
23913
|
+
/** Whether this node emits prompt text of its own (function/extract nodes do; bare scopes do not). */
|
|
23914
|
+
contributesText() {
|
|
23915
|
+
return false;
|
|
23916
|
+
}
|
|
23917
|
+
/** Base nodes contribute nothing — the remainder passes straight through. */
|
|
23918
|
+
composeInferenceData(composer, opts) {
|
|
23919
|
+
const rest = opts?.next?.() ?? "";
|
|
23920
|
+
if (rest)
|
|
23921
|
+
composer.addText(rest);
|
|
23922
|
+
}
|
|
23569
23923
|
/**
|
|
23570
23924
|
* The `.tsi` file this context descends from: the nearest file node up the
|
|
23571
23925
|
* parent chain (FileInferContext overrides). A lineage with no file root
|
|
@@ -23581,42 +23935,67 @@ var FunctionInferContext = class _FunctionInferContext extends InferContext {
|
|
|
23581
23935
|
/** @internal created via FileInferContext.func (and tests) only. Parentless = free-standing scope. */
|
|
23582
23936
|
static create(init, runtime, parent) {
|
|
23583
23937
|
const args = Object.freeze((init.args ?? []).map((a) => Object.freeze({ name: a.name, type: a.type, contextual: a.contextual ?? false, value: a.value })));
|
|
23584
|
-
return new _FunctionInferContext(Object.freeze({
|
|
23938
|
+
return new _FunctionInferContext(Object.freeze({
|
|
23939
|
+
fn: init.fn,
|
|
23940
|
+
instruction: init.instruction ?? "",
|
|
23941
|
+
...init.template ? { template: init.template } : {},
|
|
23942
|
+
args
|
|
23943
|
+
}), runtime, parent);
|
|
23944
|
+
}
|
|
23945
|
+
contributesText() {
|
|
23946
|
+
return true;
|
|
23585
23947
|
}
|
|
23586
23948
|
/**
|
|
23587
|
-
* One CONTEXT block per invocation
|
|
23588
|
-
*
|
|
23589
|
-
*
|
|
23590
|
-
*
|
|
23591
|
-
*
|
|
23592
|
-
* input — keep it
|
|
23949
|
+
* One CONTEXT block per invocation. The node assembles FunctionPromptData;
|
|
23950
|
+
* without a template the runtime's PromptRenderer renders it and the
|
|
23951
|
+
* remainder follows; with a template (a `${.member}` marker) the template
|
|
23952
|
+
* renders the block from a FunctionPromptScope over the same data — `.default`
|
|
23953
|
+
* is the built-in block, `.next` the remainder (appended after the template
|
|
23954
|
+
* when it never reads it). The composed text is fingerprint input — keep it
|
|
23955
|
+
* deterministic.
|
|
23593
23956
|
*/
|
|
23594
23957
|
composeInferenceData(composer, opts) {
|
|
23595
|
-
const { fn, instruction, args } = this.data;
|
|
23596
|
-
const signature = `${fn}(${args.map((a) => a.name).join(", ")})`;
|
|
23958
|
+
const { fn, instruction, args, template } = this.data;
|
|
23597
23959
|
const file = this.sourceFile();
|
|
23598
|
-
const
|
|
23599
|
-
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
|
|
23603
|
-
|
|
23604
|
-
|
|
23605
|
-
|
|
23606
|
-
|
|
23607
|
-
|
|
23608
|
-
|
|
23609
|
-
|
|
23610
|
-
|
|
23611
|
-
|
|
23612
|
-
|
|
23613
|
-
lines.push(`- ${a.name}${type}:`, "<value>", a.value, "</value>");
|
|
23614
|
-
} else {
|
|
23615
|
-
lines.push(`- ${a.name}${type} = ${JSON.stringify(a.value)}`);
|
|
23616
|
-
}
|
|
23617
|
-
}
|
|
23960
|
+
const data = {
|
|
23961
|
+
kind: "function",
|
|
23962
|
+
fn,
|
|
23963
|
+
...file === "<unknown>" ? {} : { file },
|
|
23964
|
+
instruction,
|
|
23965
|
+
args,
|
|
23966
|
+
nested: opts?.nested ?? false,
|
|
23967
|
+
hasContext: opts?.hasContext ?? false
|
|
23968
|
+
};
|
|
23969
|
+
const renderer = this.runtime.promptRenderer;
|
|
23970
|
+
let memo;
|
|
23971
|
+
const rest = () => memo ??= opts?.next?.() ?? "";
|
|
23972
|
+
if (!template) {
|
|
23973
|
+
composer.addText(joinBlocks(renderer.function(data), rest()));
|
|
23974
|
+
return;
|
|
23618
23975
|
}
|
|
23619
|
-
|
|
23976
|
+
let nextRead = false;
|
|
23977
|
+
const scope = Object.freeze({
|
|
23978
|
+
fn,
|
|
23979
|
+
signature: `${fn}(${args.map((a) => a.name).join(", ")})`,
|
|
23980
|
+
...data.file === void 0 ? {} : { file: data.file },
|
|
23981
|
+
args: Object.freeze(args.map((a) => Object.freeze({
|
|
23982
|
+
name: a.name,
|
|
23983
|
+
...a.type ? { type: a.type.toNativeType() } : {},
|
|
23984
|
+
contextual: a.contextual,
|
|
23985
|
+
value: a.value
|
|
23986
|
+
}))),
|
|
23987
|
+
nested: data.nested,
|
|
23988
|
+
hasContext: data.hasContext,
|
|
23989
|
+
// The template IS the instruction: the default block renders without Purpose.
|
|
23990
|
+
get default() {
|
|
23991
|
+
return renderer.function({ ...data, instruction: "" });
|
|
23992
|
+
},
|
|
23993
|
+
get next() {
|
|
23994
|
+
nextRead = true;
|
|
23995
|
+
return rest();
|
|
23996
|
+
}
|
|
23997
|
+
});
|
|
23998
|
+
composer.addText(renderTemplate(template, scope, `${file}:${fn}`, rest, () => nextRead));
|
|
23620
23999
|
}
|
|
23621
24000
|
};
|
|
23622
24001
|
|
|
@@ -23729,6 +24108,13 @@ var NolaRuntime = class {
|
|
|
23729
24108
|
this.emit = emit;
|
|
23730
24109
|
this.url = url;
|
|
23731
24110
|
}
|
|
24111
|
+
/**
|
|
24112
|
+
* The provider-facing text seam consulted by every composeInferenceData —
|
|
24113
|
+
* the built-in renderer today (config-level overrides are the next step).
|
|
24114
|
+
*/
|
|
24115
|
+
get promptRenderer() {
|
|
24116
|
+
return defaultPromptRenderer;
|
|
24117
|
+
}
|
|
23732
24118
|
/** The frozen resolved config, or null when nothing has been configured yet. */
|
|
23733
24119
|
get config() {
|
|
23734
24120
|
return this.#config;
|
|
@@ -23845,8 +24231,12 @@ var nolaRuntime = {
|
|
|
23845
24231
|
}
|
|
23846
24232
|
};
|
|
23847
24233
|
|
|
23848
|
-
// ../node-loader/dist/config.js
|
|
24234
|
+
// ../node-loader/dist/bundle-config.js
|
|
23849
24235
|
var import_esbuild = __toESM(require_main(), 1);
|
|
24236
|
+
|
|
24237
|
+
// ../node-loader/dist/config.js
|
|
24238
|
+
var import_node_fs2 = require("node:fs");
|
|
24239
|
+
var import_node_path2 = require("node:path");
|
|
23850
24240
|
function findUp2(startDir, name) {
|
|
23851
24241
|
let dir = startDir;
|
|
23852
24242
|
for (; ; ) {
|
|
@@ -23973,6 +24363,61 @@ function guardProjectServiceDocumentCache(projectService) {
|
|
|
23973
24363
|
};
|
|
23974
24364
|
}
|
|
23975
24365
|
|
|
24366
|
+
// src/resolution-watch.ts
|
|
24367
|
+
function decorateHostForTsiResolutionWatch(host, serverHost, project, extensions) {
|
|
24368
|
+
const prior = host.resolveModuleNameLiterals?.bind(host);
|
|
24369
|
+
if (!prior) return;
|
|
24370
|
+
const watchFile = (path, cb) => serverHost.watchFile(
|
|
24371
|
+
path,
|
|
24372
|
+
cb,
|
|
24373
|
+
500
|
|
24374
|
+
);
|
|
24375
|
+
const caseSensitive = typeof host.useCaseSensitiveFileNames === "function" ? host.useCaseSensitiveFileNames() : host.useCaseSensitiveFileNames ?? false;
|
|
24376
|
+
const canon = (fileName) => {
|
|
24377
|
+
const posix = fileName.replace(/\\/g, "/");
|
|
24378
|
+
return caseSensitive ? posix : posix.toLowerCase();
|
|
24379
|
+
};
|
|
24380
|
+
const watched = /* @__PURE__ */ new Map();
|
|
24381
|
+
const invalidated = /* @__PURE__ */ new Set();
|
|
24382
|
+
const hostWithInvalidation = host;
|
|
24383
|
+
const projectWithDirty = project;
|
|
24384
|
+
let innerHasInvalidated = hostWithInvalidation.hasInvalidatedResolutions;
|
|
24385
|
+
const composedHasInvalidated = (path) => invalidated.has(canon(path)) || (innerHasInvalidated?.(path) ?? false);
|
|
24386
|
+
Object.defineProperty(host, "hasInvalidatedResolutions", {
|
|
24387
|
+
configurable: true,
|
|
24388
|
+
get: () => composedHasInvalidated,
|
|
24389
|
+
set: (fn) => {
|
|
24390
|
+
innerHasInvalidated = fn;
|
|
24391
|
+
}
|
|
24392
|
+
});
|
|
24393
|
+
host.resolveModuleNameLiterals = (moduleLiterals, containingFile, ...rest) => {
|
|
24394
|
+
const containing = canon(containingFile);
|
|
24395
|
+
invalidated.delete(containing);
|
|
24396
|
+
const results = prior(moduleLiterals, containingFile, ...rest);
|
|
24397
|
+
for (let i = 0; i < moduleLiterals.length; i++) {
|
|
24398
|
+
const text = moduleLiterals[i]?.text ?? "";
|
|
24399
|
+
if (!text.startsWith("./") && !text.startsWith("../")) continue;
|
|
24400
|
+
if (!extensions.some((ext) => text.endsWith(ext))) continue;
|
|
24401
|
+
const dir = containingFile.replace(/\\/g, "/").split("/").slice(0, -1).join("/");
|
|
24402
|
+
const candidate = canon(`${dir}/${text}`.replace(/\/\.\//g, "/"));
|
|
24403
|
+
const entry = watched.get(candidate);
|
|
24404
|
+
if (entry) {
|
|
24405
|
+
entry.waiters.add(containing);
|
|
24406
|
+
continue;
|
|
24407
|
+
}
|
|
24408
|
+
if (results[i]?.resolvedModule) continue;
|
|
24409
|
+
const waiters = /* @__PURE__ */ new Set([containing]);
|
|
24410
|
+
const watcher = watchFile(candidate, () => {
|
|
24411
|
+
for (const waiter of waiters) invalidated.add(waiter);
|
|
24412
|
+
projectWithDirty.markAsDirty?.();
|
|
24413
|
+
project.refreshDiagnostics();
|
|
24414
|
+
});
|
|
24415
|
+
watched.set(candidate, { watcher, waiters });
|
|
24416
|
+
}
|
|
24417
|
+
return results;
|
|
24418
|
+
};
|
|
24419
|
+
}
|
|
24420
|
+
|
|
23976
24421
|
// src/server-host.ts
|
|
23977
24422
|
var PATCHED2 = Symbol.for("nola.companionServerHost");
|
|
23978
24423
|
function decorateServerHostForCompanions(serverHost) {
|
|
@@ -24031,7 +24476,12 @@ function createNolaTsPlugin() {
|
|
|
24031
24476
|
decorateHostHideShadowedDeclarations(typescript, info.languageServiceHost);
|
|
24032
24477
|
decorateHostWithCompanions(typescript, info.languageServiceHost, { sourceRoot });
|
|
24033
24478
|
return {
|
|
24034
|
-
languagePlugins: [createNolaLanguagePlugin((fileName) => fileName, { sourceRoot })]
|
|
24479
|
+
languagePlugins: [createNolaLanguagePlugin((fileName) => fileName, { sourceRoot })],
|
|
24480
|
+
// setup runs AFTER Volar's decorateLanguageServiceHost, so this wraps the
|
|
24481
|
+
// resolver that actually handles `.tsi` literals (see resolution-watch.ts).
|
|
24482
|
+
setup: () => {
|
|
24483
|
+
decorateHostForTsiResolutionWatch(info.languageServiceHost, info.serverHost, info.project, [".tsi"]);
|
|
24484
|
+
}
|
|
24035
24485
|
};
|
|
24036
24486
|
});
|
|
24037
24487
|
}
|