@neocompose/cli 0.61.3 → 0.61.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.61.4] - 2026-10-01
|
|
4
|
+
|
|
5
|
+
- Narrow implicit instance members after null and type checks just like their `this.Member` spelling, including nested conditions, assignments, and loop invalidation.
|
|
6
|
+
- Keep symbol rename scoped to resolved references in test files, including declarations without an assigned ID.
|
|
7
|
+
|
|
3
8
|
## [0.61.3] - 2026-10-01
|
|
4
9
|
|
|
5
10
|
- Resolve `collectionValue: Reference(root.Assets.Quests.Daily)` through construction defaults, including classes and empty collections declared in the same push. Preparation creates the required rows and associations together; no preliminary push or manually assigned value IDs are needed.
|
package/dist/neo.mjs
CHANGED
|
@@ -5112,8 +5112,8 @@ function pathRoot(path) {
|
|
|
5112
5112
|
const dot = path.indexOf(".");
|
|
5113
5113
|
return dot === -1 ? path : path.slice(0, dot);
|
|
5114
5114
|
}
|
|
5115
|
-
function factsFromIsCheck(expression, whenTrue) {
|
|
5116
|
-
const path =
|
|
5115
|
+
function factsFromIsCheck(expression, whenTrue, pathOf) {
|
|
5116
|
+
const path = pathOf(expression.operand);
|
|
5117
5117
|
const nullCheck = expression.type.kind === "primitive" && expression.type.name === "null";
|
|
5118
5118
|
if (path === null && (!whenTrue || nullCheck || !expression.bindingName)) {
|
|
5119
5119
|
return [];
|
|
@@ -5137,58 +5137,72 @@ function extractNullCheckSide(expression) {
|
|
|
5137
5137
|
if (!leftNull && !rightNull) return null;
|
|
5138
5138
|
return leftNull ? expression.right : expression.left;
|
|
5139
5139
|
}
|
|
5140
|
-
function
|
|
5141
|
-
|
|
5140
|
+
function pathsAfterBindings(pathOf, facts) {
|
|
5141
|
+
const bindings = new Set(
|
|
5142
|
+
facts.flatMap((fact) => fact.bindingName ? [fact.bindingName] : [])
|
|
5143
|
+
);
|
|
5144
|
+
if (bindings.size === 0) return pathOf;
|
|
5145
|
+
return (expression) => {
|
|
5146
|
+
const path = canonicalPath(expression);
|
|
5147
|
+
return path !== null && bindings.has(pathRoot(path)) ? path : pathOf(expression);
|
|
5148
|
+
};
|
|
5149
|
+
}
|
|
5150
|
+
function factsWhenTrue(expression, pathOf) {
|
|
5151
|
+
if (expression.kind === "is")
|
|
5152
|
+
return factsFromIsCheck(expression, true, pathOf);
|
|
5142
5153
|
if (expression.kind === "binary") {
|
|
5143
5154
|
if (expression.op === "&&") {
|
|
5155
|
+
const left = factsWhenTrue(expression.left, pathOf);
|
|
5144
5156
|
return [
|
|
5145
|
-
...
|
|
5146
|
-
...factsWhenTrue(expression.right)
|
|
5157
|
+
...left,
|
|
5158
|
+
...factsWhenTrue(expression.right, pathsAfterBindings(pathOf, left))
|
|
5147
5159
|
];
|
|
5148
5160
|
}
|
|
5149
5161
|
if (expression.op === "||") {
|
|
5150
5162
|
return mergeFactSets([
|
|
5151
|
-
factsWhenTrue(expression.left),
|
|
5152
|
-
factsWhenTrue(expression.right)
|
|
5163
|
+
factsWhenTrue(expression.left, pathOf),
|
|
5164
|
+
factsWhenTrue(expression.right, pathOf)
|
|
5153
5165
|
]);
|
|
5154
5166
|
}
|
|
5155
5167
|
if (expression.op === "==" || expression.op === "!=") {
|
|
5156
5168
|
const value = extractNullCheckSide(expression);
|
|
5157
|
-
const path2 = value ?
|
|
5169
|
+
const path2 = value ? pathOf(value) : null;
|
|
5158
5170
|
return value && path2 ? [{ expression: value, path: path2, nullValue: expression.op === "==" }] : [];
|
|
5159
5171
|
}
|
|
5160
5172
|
}
|
|
5161
5173
|
if (expression.kind === "unary" && expression.op === "!") {
|
|
5162
|
-
return factsWhenFalse(expression.operand);
|
|
5174
|
+
return factsWhenFalse(expression.operand, pathOf);
|
|
5163
5175
|
}
|
|
5164
|
-
const path =
|
|
5176
|
+
const path = pathOf(expression);
|
|
5165
5177
|
return path && (expression.kind === "ident" || expression.kind === "member") ? [{ expression, path, nullValue: false, loose: true }] : [];
|
|
5166
5178
|
}
|
|
5167
|
-
function factsWhenFalse(expression) {
|
|
5168
|
-
if (expression.kind === "is")
|
|
5179
|
+
function factsWhenFalse(expression, pathOf) {
|
|
5180
|
+
if (expression.kind === "is")
|
|
5181
|
+
return factsFromIsCheck(expression, false, pathOf);
|
|
5169
5182
|
if (expression.kind === "binary") {
|
|
5170
5183
|
if (expression.op === "||") {
|
|
5184
|
+
const left = factsWhenFalse(expression.left, pathOf);
|
|
5171
5185
|
return [
|
|
5172
|
-
...
|
|
5173
|
-
...factsWhenFalse(expression.right)
|
|
5186
|
+
...left,
|
|
5187
|
+
...factsWhenFalse(expression.right, pathsAfterBindings(pathOf, left))
|
|
5174
5188
|
];
|
|
5175
5189
|
}
|
|
5176
5190
|
if (expression.op === "&&") {
|
|
5177
5191
|
return mergeFactSets([
|
|
5178
|
-
factsWhenFalse(expression.left),
|
|
5179
|
-
factsWhenFalse(expression.right)
|
|
5192
|
+
factsWhenFalse(expression.left, pathOf),
|
|
5193
|
+
factsWhenFalse(expression.right, pathOf)
|
|
5180
5194
|
]);
|
|
5181
5195
|
}
|
|
5182
5196
|
if (expression.op === "==" || expression.op === "!=") {
|
|
5183
5197
|
const value = extractNullCheckSide(expression);
|
|
5184
|
-
const path2 = value ?
|
|
5198
|
+
const path2 = value ? pathOf(value) : null;
|
|
5185
5199
|
return value && path2 ? [{ expression: value, path: path2, nullValue: expression.op !== "==" }] : [];
|
|
5186
5200
|
}
|
|
5187
5201
|
}
|
|
5188
5202
|
if (expression.kind === "unary" && expression.op === "!") {
|
|
5189
|
-
return factsWhenTrue(expression.operand);
|
|
5203
|
+
return factsWhenTrue(expression.operand, pathOf);
|
|
5190
5204
|
}
|
|
5191
|
-
const path =
|
|
5205
|
+
const path = pathOf(expression);
|
|
5192
5206
|
return path && (expression.kind === "ident" || expression.kind === "member") ? [{ expression, path, nullValue: true, loose: true }] : [];
|
|
5193
5207
|
}
|
|
5194
5208
|
function mergeFactSets(sets) {
|
|
@@ -5350,156 +5364,440 @@ function scopeVariable(name, value, sourceType, writability, ownership, writeRoo
|
|
|
5350
5364
|
...readonlyBinding ? { readonlyBinding } : {}
|
|
5351
5365
|
};
|
|
5352
5366
|
}
|
|
5353
|
-
function
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5367
|
+
function statementFlow(statements, cache) {
|
|
5368
|
+
const cached = cache.get(statements);
|
|
5369
|
+
if (cached) return cached;
|
|
5370
|
+
const flow = /* @__PURE__ */ new Set(["fallthrough"]);
|
|
5371
|
+
for (const statement of statements) {
|
|
5372
|
+
if (!flow.delete("fallthrough")) break;
|
|
5373
|
+
let next;
|
|
5374
|
+
switch (statement.kind) {
|
|
5375
|
+
case "return":
|
|
5376
|
+
case "throw":
|
|
5377
|
+
next = /* @__PURE__ */ new Set(["exit"]);
|
|
5378
|
+
break;
|
|
5379
|
+
case "break":
|
|
5380
|
+
next = /* @__PURE__ */ new Set(["break"]);
|
|
5381
|
+
break;
|
|
5382
|
+
case "continue":
|
|
5383
|
+
next = /* @__PURE__ */ new Set(["continue"]);
|
|
5384
|
+
break;
|
|
5385
|
+
case "if":
|
|
5386
|
+
next = new Set(statementFlow(statement.elseBody ?? [], cache));
|
|
5387
|
+
for (const branch of statement.branches)
|
|
5388
|
+
for (const outcome of statementFlow(branch.body, cache))
|
|
5389
|
+
next.add(outcome);
|
|
5390
|
+
break;
|
|
5391
|
+
case "try":
|
|
5392
|
+
next = new Set(statementFlow(statement.body, cache));
|
|
5393
|
+
for (const clause of statement.catches)
|
|
5394
|
+
for (const outcome of statementFlow(clause.body, cache))
|
|
5395
|
+
next.add(outcome);
|
|
5396
|
+
break;
|
|
5397
|
+
case "switch":
|
|
5398
|
+
next = /* @__PURE__ */ new Set();
|
|
5399
|
+
if (!statement.sections.some(
|
|
5400
|
+
(section) => section.labels.some((label) => label.kind === "default")
|
|
5401
|
+
)) {
|
|
5402
|
+
next.add("fallthrough");
|
|
5403
|
+
}
|
|
5404
|
+
for (const section of statement.sections)
|
|
5405
|
+
for (const outcome of statementFlow(section.body, cache))
|
|
5406
|
+
next.add(outcome);
|
|
5407
|
+
if (next.delete("break")) next.add("fallthrough");
|
|
5408
|
+
break;
|
|
5409
|
+
case "doWhile":
|
|
5410
|
+
next = new Set(statementFlow(statement.body, cache));
|
|
5411
|
+
if (next.delete("break")) next.add("fallthrough");
|
|
5412
|
+
if (next.delete("continue")) next.add("fallthrough");
|
|
5413
|
+
break;
|
|
5414
|
+
default:
|
|
5415
|
+
next = /* @__PURE__ */ new Set(["fallthrough"]);
|
|
5416
|
+
break;
|
|
5358
5417
|
}
|
|
5418
|
+
for (const outcome of next) flow.add(outcome);
|
|
5359
5419
|
}
|
|
5420
|
+
cache.set(statements, flow);
|
|
5421
|
+
return flow;
|
|
5422
|
+
}
|
|
5423
|
+
function localsWithBindings(locals, expression, whenTrue) {
|
|
5424
|
+
const facts = whenTrue ? factsWhenTrue(expression, canonicalPath) : factsWhenFalse(expression, canonicalPath);
|
|
5425
|
+
return /* @__PURE__ */ new Set([
|
|
5426
|
+
...locals,
|
|
5427
|
+
...facts.flatMap((fact) => fact.bindingName ? [fact.bindingName] : [])
|
|
5428
|
+
]);
|
|
5360
5429
|
}
|
|
5361
|
-
function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set()) {
|
|
5430
|
+
function collectAssignedPathRoots(statements, roots = /* @__PURE__ */ new Set(), inheritedLocals = /* @__PURE__ */ new Set(), flowCache = /* @__PURE__ */ new WeakMap()) {
|
|
5431
|
+
const locals = new Set(inheritedLocals);
|
|
5362
5432
|
for (const statement of statements) {
|
|
5363
5433
|
if (statement.kind === "assign") {
|
|
5364
5434
|
const assignedPath = canonicalPath(statement.target);
|
|
5365
|
-
if (assignedPath
|
|
5366
|
-
|
|
5435
|
+
if (assignedPath && !locals.has(pathRoot(assignedPath))) {
|
|
5436
|
+
roots.add(pathRoot(assignedPath));
|
|
5437
|
+
}
|
|
5438
|
+
collectAssignedPathRootsInExpression(
|
|
5439
|
+
statement.target,
|
|
5440
|
+
roots,
|
|
5441
|
+
locals,
|
|
5442
|
+
flowCache
|
|
5443
|
+
);
|
|
5367
5444
|
if (statement.value)
|
|
5368
|
-
collectAssignedPathRootsInExpression(
|
|
5445
|
+
collectAssignedPathRootsInExpression(
|
|
5446
|
+
statement.value,
|
|
5447
|
+
roots,
|
|
5448
|
+
locals,
|
|
5449
|
+
flowCache
|
|
5450
|
+
);
|
|
5369
5451
|
continue;
|
|
5370
5452
|
}
|
|
5371
5453
|
if (statement.kind === "varDecl") {
|
|
5372
|
-
collectAssignedPathRootsInExpression(
|
|
5454
|
+
collectAssignedPathRootsInExpression(
|
|
5455
|
+
statement.init,
|
|
5456
|
+
roots,
|
|
5457
|
+
locals,
|
|
5458
|
+
flowCache
|
|
5459
|
+
);
|
|
5460
|
+
locals.add(statement.name);
|
|
5373
5461
|
continue;
|
|
5374
5462
|
}
|
|
5375
5463
|
if (statement.kind === "if") {
|
|
5464
|
+
let falseLocals = locals;
|
|
5465
|
+
const falseFacts = [];
|
|
5466
|
+
const fallthroughFacts = [];
|
|
5376
5467
|
for (const branch of statement.branches) {
|
|
5377
|
-
collectAssignedPathRootsInExpression(
|
|
5378
|
-
|
|
5468
|
+
collectAssignedPathRootsInExpression(
|
|
5469
|
+
branch.cond,
|
|
5470
|
+
roots,
|
|
5471
|
+
falseLocals,
|
|
5472
|
+
flowCache
|
|
5473
|
+
);
|
|
5474
|
+
const branchFacts = [
|
|
5475
|
+
...falseFacts,
|
|
5476
|
+
...factsWhenTrue(branch.cond, canonicalPath)
|
|
5477
|
+
];
|
|
5478
|
+
collectAssignedPathRoots(
|
|
5479
|
+
branch.body,
|
|
5480
|
+
roots,
|
|
5481
|
+
localsWithBindings(falseLocals, branch.cond, true),
|
|
5482
|
+
flowCache
|
|
5483
|
+
);
|
|
5484
|
+
if (statementFlow(branch.body, flowCache).has("fallthrough"))
|
|
5485
|
+
fallthroughFacts.push(branchFacts);
|
|
5486
|
+
falseFacts.push(...factsWhenFalse(branch.cond, canonicalPath));
|
|
5487
|
+
falseLocals = localsWithBindings(falseLocals, branch.cond, false);
|
|
5379
5488
|
}
|
|
5380
5489
|
if (statement.elseBody) {
|
|
5381
|
-
collectAssignedPathRoots(
|
|
5490
|
+
collectAssignedPathRoots(
|
|
5491
|
+
statement.elseBody,
|
|
5492
|
+
roots,
|
|
5493
|
+
falseLocals,
|
|
5494
|
+
flowCache
|
|
5495
|
+
);
|
|
5496
|
+
if (statementFlow(statement.elseBody, flowCache).has("fallthrough"))
|
|
5497
|
+
fallthroughFacts.push(falseFacts);
|
|
5498
|
+
} else {
|
|
5499
|
+
fallthroughFacts.push(falseFacts);
|
|
5500
|
+
}
|
|
5501
|
+
for (const fact of mergeFactSets(fallthroughFacts)) {
|
|
5502
|
+
if (fact.bindingName) locals.add(fact.bindingName);
|
|
5382
5503
|
}
|
|
5383
5504
|
continue;
|
|
5384
5505
|
}
|
|
5385
5506
|
if (statement.kind === "try") {
|
|
5386
|
-
collectAssignedPathRoots(statement.body, roots);
|
|
5507
|
+
collectAssignedPathRoots(statement.body, roots, locals, flowCache);
|
|
5387
5508
|
for (const clause of statement.catches) {
|
|
5509
|
+
const catchLocals = /* @__PURE__ */ new Set([...locals, clause.name]);
|
|
5388
5510
|
if (clause.filter) {
|
|
5389
|
-
collectAssignedPathRootsInExpression(
|
|
5511
|
+
collectAssignedPathRootsInExpression(
|
|
5512
|
+
clause.filter,
|
|
5513
|
+
roots,
|
|
5514
|
+
catchLocals,
|
|
5515
|
+
flowCache
|
|
5516
|
+
);
|
|
5390
5517
|
}
|
|
5391
|
-
collectAssignedPathRoots(
|
|
5518
|
+
collectAssignedPathRoots(
|
|
5519
|
+
clause.body,
|
|
5520
|
+
roots,
|
|
5521
|
+
clause.filter ? localsWithBindings(catchLocals, clause.filter, true) : catchLocals,
|
|
5522
|
+
flowCache
|
|
5523
|
+
);
|
|
5392
5524
|
}
|
|
5393
5525
|
continue;
|
|
5394
5526
|
}
|
|
5395
5527
|
if (statement.kind === "while" || statement.kind === "doWhile") {
|
|
5396
|
-
collectAssignedPathRootsInExpression(
|
|
5397
|
-
|
|
5528
|
+
collectAssignedPathRootsInExpression(
|
|
5529
|
+
statement.condition,
|
|
5530
|
+
roots,
|
|
5531
|
+
locals,
|
|
5532
|
+
flowCache
|
|
5533
|
+
);
|
|
5534
|
+
collectAssignedPathRoots(
|
|
5535
|
+
statement.body,
|
|
5536
|
+
roots,
|
|
5537
|
+
statement.kind === "while" ? localsWithBindings(locals, statement.condition, true) : locals,
|
|
5538
|
+
flowCache
|
|
5539
|
+
);
|
|
5398
5540
|
continue;
|
|
5399
5541
|
}
|
|
5400
5542
|
if (statement.kind === "for") {
|
|
5401
|
-
collectAssignedPathRootsInExpression(
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5543
|
+
collectAssignedPathRootsInExpression(
|
|
5544
|
+
statement.initializer.init,
|
|
5545
|
+
roots,
|
|
5546
|
+
locals,
|
|
5547
|
+
flowCache
|
|
5548
|
+
);
|
|
5549
|
+
const loopLocals = /* @__PURE__ */ new Set([...locals, statement.initializer.name]);
|
|
5550
|
+
collectAssignedPathRootsInExpression(
|
|
5551
|
+
statement.condition,
|
|
5552
|
+
roots,
|
|
5553
|
+
loopLocals,
|
|
5554
|
+
flowCache
|
|
5555
|
+
);
|
|
5556
|
+
const iterationLocals = localsWithBindings(
|
|
5557
|
+
loopLocals,
|
|
5558
|
+
statement.condition,
|
|
5559
|
+
true
|
|
5560
|
+
);
|
|
5561
|
+
collectAssignedPathRoots(
|
|
5562
|
+
[statement.iterator],
|
|
5563
|
+
roots,
|
|
5564
|
+
iterationLocals,
|
|
5565
|
+
flowCache
|
|
5566
|
+
);
|
|
5567
|
+
collectAssignedPathRoots(
|
|
5568
|
+
statement.body,
|
|
5569
|
+
roots,
|
|
5570
|
+
iterationLocals,
|
|
5571
|
+
flowCache
|
|
5572
|
+
);
|
|
5405
5573
|
continue;
|
|
5406
5574
|
}
|
|
5407
5575
|
if (statement.kind === "forEach") {
|
|
5408
|
-
collectAssignedPathRootsInExpression(
|
|
5409
|
-
|
|
5576
|
+
collectAssignedPathRootsInExpression(
|
|
5577
|
+
statement.collection,
|
|
5578
|
+
roots,
|
|
5579
|
+
locals,
|
|
5580
|
+
flowCache
|
|
5581
|
+
);
|
|
5582
|
+
const loopLocals = /* @__PURE__ */ new Set([...locals, statement.name]);
|
|
5583
|
+
if (statement.key) loopLocals.add(statement.key.name);
|
|
5584
|
+
collectAssignedPathRoots(statement.body, roots, loopLocals, flowCache);
|
|
5410
5585
|
continue;
|
|
5411
5586
|
}
|
|
5412
5587
|
if (statement.kind === "switch") {
|
|
5413
|
-
collectAssignedPathRootsInExpression(
|
|
5588
|
+
collectAssignedPathRootsInExpression(
|
|
5589
|
+
statement.selector,
|
|
5590
|
+
roots,
|
|
5591
|
+
locals,
|
|
5592
|
+
flowCache
|
|
5593
|
+
);
|
|
5414
5594
|
for (const section of statement.sections) {
|
|
5415
5595
|
for (const label of section.labels) {
|
|
5416
5596
|
if (label.kind === "case") {
|
|
5417
|
-
collectAssignedPathRootsInExpression(
|
|
5597
|
+
collectAssignedPathRootsInExpression(
|
|
5598
|
+
label.expression,
|
|
5599
|
+
roots,
|
|
5600
|
+
locals,
|
|
5601
|
+
flowCache
|
|
5602
|
+
);
|
|
5418
5603
|
}
|
|
5419
5604
|
}
|
|
5420
|
-
collectAssignedPathRoots(section.body, roots);
|
|
5605
|
+
collectAssignedPathRoots(section.body, roots, locals, flowCache);
|
|
5421
5606
|
}
|
|
5422
5607
|
continue;
|
|
5423
5608
|
}
|
|
5424
5609
|
if (statement.kind === "return" || statement.kind === "throw") {
|
|
5425
5610
|
if (statement.expr)
|
|
5426
|
-
collectAssignedPathRootsInExpression(
|
|
5611
|
+
collectAssignedPathRootsInExpression(
|
|
5612
|
+
statement.expr,
|
|
5613
|
+
roots,
|
|
5614
|
+
locals,
|
|
5615
|
+
flowCache
|
|
5616
|
+
);
|
|
5427
5617
|
continue;
|
|
5428
5618
|
}
|
|
5429
5619
|
if (statement.kind === "exprStmt") {
|
|
5430
|
-
collectAssignedPathRootsInExpression(
|
|
5620
|
+
collectAssignedPathRootsInExpression(
|
|
5621
|
+
statement.expr,
|
|
5622
|
+
roots,
|
|
5623
|
+
locals,
|
|
5624
|
+
flowCache
|
|
5625
|
+
);
|
|
5431
5626
|
}
|
|
5432
5627
|
}
|
|
5433
5628
|
return roots;
|
|
5434
5629
|
}
|
|
5435
|
-
function collectAssignedPathRootsInExpression(expression, roots) {
|
|
5630
|
+
function collectAssignedPathRootsInExpression(expression, roots, locals, flowCache) {
|
|
5436
5631
|
switch (expression.kind) {
|
|
5437
5632
|
case "litInterp":
|
|
5438
5633
|
for (const part of expression.parts) {
|
|
5439
5634
|
if (part.kind === "expr") {
|
|
5440
|
-
collectAssignedPathRootsInExpression(
|
|
5635
|
+
collectAssignedPathRootsInExpression(
|
|
5636
|
+
part.expr,
|
|
5637
|
+
roots,
|
|
5638
|
+
locals,
|
|
5639
|
+
flowCache
|
|
5640
|
+
);
|
|
5441
5641
|
}
|
|
5442
5642
|
}
|
|
5443
5643
|
return;
|
|
5444
5644
|
case "litList":
|
|
5445
5645
|
for (const element of expression.elements) {
|
|
5446
|
-
collectAssignedPathRootsInExpression(element, roots);
|
|
5646
|
+
collectAssignedPathRootsInExpression(element, roots, locals, flowCache);
|
|
5447
5647
|
}
|
|
5448
5648
|
return;
|
|
5449
5649
|
case "litDict":
|
|
5450
5650
|
for (const entry of expression.entries) {
|
|
5451
|
-
collectAssignedPathRootsInExpression(
|
|
5452
|
-
|
|
5651
|
+
collectAssignedPathRootsInExpression(
|
|
5652
|
+
entry.key,
|
|
5653
|
+
roots,
|
|
5654
|
+
locals,
|
|
5655
|
+
flowCache
|
|
5656
|
+
);
|
|
5657
|
+
collectAssignedPathRootsInExpression(
|
|
5658
|
+
entry.value,
|
|
5659
|
+
roots,
|
|
5660
|
+
locals,
|
|
5661
|
+
flowCache
|
|
5662
|
+
);
|
|
5453
5663
|
}
|
|
5454
5664
|
return;
|
|
5455
5665
|
case "member":
|
|
5456
|
-
collectAssignedPathRootsInExpression(
|
|
5666
|
+
collectAssignedPathRootsInExpression(
|
|
5667
|
+
expression.receiver,
|
|
5668
|
+
roots,
|
|
5669
|
+
locals,
|
|
5670
|
+
flowCache
|
|
5671
|
+
);
|
|
5457
5672
|
return;
|
|
5458
5673
|
case "index":
|
|
5459
|
-
collectAssignedPathRootsInExpression(
|
|
5460
|
-
|
|
5674
|
+
collectAssignedPathRootsInExpression(
|
|
5675
|
+
expression.receiver,
|
|
5676
|
+
roots,
|
|
5677
|
+
locals,
|
|
5678
|
+
flowCache
|
|
5679
|
+
);
|
|
5680
|
+
collectAssignedPathRootsInExpression(
|
|
5681
|
+
expression.index,
|
|
5682
|
+
roots,
|
|
5683
|
+
locals,
|
|
5684
|
+
flowCache
|
|
5685
|
+
);
|
|
5461
5686
|
return;
|
|
5462
5687
|
case "call":
|
|
5463
|
-
collectAssignedPathRootsInExpression(
|
|
5688
|
+
collectAssignedPathRootsInExpression(
|
|
5689
|
+
expression.callee,
|
|
5690
|
+
roots,
|
|
5691
|
+
locals,
|
|
5692
|
+
flowCache
|
|
5693
|
+
);
|
|
5464
5694
|
for (const argument2 of expression.args) {
|
|
5465
|
-
collectAssignedPathRootsInExpression(
|
|
5695
|
+
collectAssignedPathRootsInExpression(
|
|
5696
|
+
argument2,
|
|
5697
|
+
roots,
|
|
5698
|
+
locals,
|
|
5699
|
+
flowCache
|
|
5700
|
+
);
|
|
5466
5701
|
}
|
|
5467
5702
|
return;
|
|
5468
5703
|
case "new":
|
|
5469
5704
|
for (const argument2 of expression.args) {
|
|
5470
|
-
collectAssignedPathRootsInExpression(
|
|
5705
|
+
collectAssignedPathRootsInExpression(
|
|
5706
|
+
argument2,
|
|
5707
|
+
roots,
|
|
5708
|
+
locals,
|
|
5709
|
+
flowCache
|
|
5710
|
+
);
|
|
5471
5711
|
}
|
|
5472
5712
|
for (const initializer of expression.initializer ?? []) {
|
|
5473
|
-
collectAssignedPathRootsInExpression(
|
|
5713
|
+
collectAssignedPathRootsInExpression(
|
|
5714
|
+
initializer.value,
|
|
5715
|
+
roots,
|
|
5716
|
+
locals,
|
|
5717
|
+
flowCache
|
|
5718
|
+
);
|
|
5474
5719
|
}
|
|
5475
5720
|
return;
|
|
5476
5721
|
case "annotated":
|
|
5477
5722
|
for (const annotation2 of expression.annotations) {
|
|
5478
5723
|
for (const argument2 of annotation2.args) {
|
|
5479
|
-
collectAssignedPathRootsInExpression(
|
|
5724
|
+
collectAssignedPathRootsInExpression(
|
|
5725
|
+
argument2,
|
|
5726
|
+
roots,
|
|
5727
|
+
locals,
|
|
5728
|
+
flowCache
|
|
5729
|
+
);
|
|
5480
5730
|
}
|
|
5481
5731
|
}
|
|
5482
|
-
collectAssignedPathRootsInExpression(
|
|
5732
|
+
collectAssignedPathRootsInExpression(
|
|
5733
|
+
expression.expression,
|
|
5734
|
+
roots,
|
|
5735
|
+
locals,
|
|
5736
|
+
flowCache
|
|
5737
|
+
);
|
|
5483
5738
|
return;
|
|
5484
5739
|
case "binary":
|
|
5485
5740
|
case "coalesce":
|
|
5486
|
-
collectAssignedPathRootsInExpression(
|
|
5487
|
-
|
|
5741
|
+
collectAssignedPathRootsInExpression(
|
|
5742
|
+
expression.left,
|
|
5743
|
+
roots,
|
|
5744
|
+
locals,
|
|
5745
|
+
flowCache
|
|
5746
|
+
);
|
|
5747
|
+
collectAssignedPathRootsInExpression(
|
|
5748
|
+
expression.right,
|
|
5749
|
+
roots,
|
|
5750
|
+
locals,
|
|
5751
|
+
flowCache
|
|
5752
|
+
);
|
|
5488
5753
|
return;
|
|
5489
5754
|
case "conditional":
|
|
5490
|
-
collectAssignedPathRootsInExpression(
|
|
5491
|
-
|
|
5492
|
-
|
|
5755
|
+
collectAssignedPathRootsInExpression(
|
|
5756
|
+
expression.condition,
|
|
5757
|
+
roots,
|
|
5758
|
+
locals,
|
|
5759
|
+
flowCache
|
|
5760
|
+
);
|
|
5761
|
+
collectAssignedPathRootsInExpression(
|
|
5762
|
+
expression.whenTrue,
|
|
5763
|
+
roots,
|
|
5764
|
+
locals,
|
|
5765
|
+
flowCache
|
|
5766
|
+
);
|
|
5767
|
+
collectAssignedPathRootsInExpression(
|
|
5768
|
+
expression.whenFalse,
|
|
5769
|
+
roots,
|
|
5770
|
+
locals,
|
|
5771
|
+
flowCache
|
|
5772
|
+
);
|
|
5493
5773
|
return;
|
|
5494
5774
|
case "unary":
|
|
5495
5775
|
case "force":
|
|
5496
|
-
collectAssignedPathRootsInExpression(
|
|
5776
|
+
collectAssignedPathRootsInExpression(
|
|
5777
|
+
expression.operand,
|
|
5778
|
+
roots,
|
|
5779
|
+
locals,
|
|
5780
|
+
flowCache
|
|
5781
|
+
);
|
|
5497
5782
|
return;
|
|
5498
5783
|
case "is":
|
|
5499
|
-
collectAssignedPathRootsInExpression(
|
|
5784
|
+
collectAssignedPathRootsInExpression(
|
|
5785
|
+
expression.operand,
|
|
5786
|
+
roots,
|
|
5787
|
+
locals,
|
|
5788
|
+
flowCache
|
|
5789
|
+
);
|
|
5500
5790
|
return;
|
|
5501
5791
|
case "lambda":
|
|
5502
|
-
collectAssignedPathRoots(
|
|
5792
|
+
collectAssignedPathRoots(
|
|
5793
|
+
expression.body,
|
|
5794
|
+
roots,
|
|
5795
|
+
/* @__PURE__ */ new Set([
|
|
5796
|
+
...locals,
|
|
5797
|
+
...expression.params.map((parameter4) => parameter4.name)
|
|
5798
|
+
]),
|
|
5799
|
+
flowCache
|
|
5800
|
+
);
|
|
5503
5801
|
return;
|
|
5504
5802
|
case "litNull":
|
|
5505
5803
|
case "litBool":
|
|
@@ -6846,16 +7144,18 @@ var init_strict_resolver = __esm({
|
|
|
6846
7144
|
const child = new Scope(scope);
|
|
6847
7145
|
const branchFacts = [
|
|
6848
7146
|
...cumulativeFalseFacts,
|
|
6849
|
-
...
|
|
7147
|
+
...this.conditionFacts(branch.cond, scope, true)
|
|
6850
7148
|
];
|
|
6851
|
-
this.applyFactsToScope(
|
|
7149
|
+
this.applyFactsToScope(child, branchFacts);
|
|
6852
7150
|
const instructions = this.resolveStatements(branch.body, child);
|
|
6853
7151
|
if (!instructionsTerminate(instructions)) {
|
|
6854
7152
|
branchExitFacts.push(branchFacts);
|
|
6855
7153
|
branchExitNarrowings.push(new Map(child.narrowedPaths));
|
|
6856
7154
|
branchExitOwnershipScopes.push(child);
|
|
6857
7155
|
}
|
|
6858
|
-
cumulativeFalseFacts.push(
|
|
7156
|
+
cumulativeFalseFacts.push(
|
|
7157
|
+
...this.conditionFacts(branch.cond, scope, false)
|
|
7158
|
+
);
|
|
6859
7159
|
return {
|
|
6860
7160
|
expression: pointerToBooleanExpression(condition.pointer),
|
|
6861
7161
|
instructions
|
|
@@ -6864,7 +7164,7 @@ var init_strict_resolver = __esm({
|
|
|
6864
7164
|
let otherwise = null;
|
|
6865
7165
|
if (statement.elseBody) {
|
|
6866
7166
|
const elseScope = new Scope(scope);
|
|
6867
|
-
this.applyFactsToScope(
|
|
7167
|
+
this.applyFactsToScope(elseScope, cumulativeFalseFacts);
|
|
6868
7168
|
otherwise = this.resolveStatements(statement.elseBody, elseScope);
|
|
6869
7169
|
if (!instructionsTerminate(otherwise)) {
|
|
6870
7170
|
branchExitFacts.push([...cumulativeFalseFacts]);
|
|
@@ -6873,7 +7173,7 @@ var init_strict_resolver = __esm({
|
|
|
6873
7173
|
}
|
|
6874
7174
|
} else {
|
|
6875
7175
|
const noBranchScope = new Scope(scope);
|
|
6876
|
-
this.applyFactsToScope(
|
|
7176
|
+
this.applyFactsToScope(noBranchScope, cumulativeFalseFacts);
|
|
6877
7177
|
branchExitFacts.push([...cumulativeFalseFacts]);
|
|
6878
7178
|
branchExitNarrowings.push(new Map(noBranchScope.narrowedPaths));
|
|
6879
7179
|
branchExitOwnershipScopes.push(noBranchScope);
|
|
@@ -6891,7 +7191,6 @@ var init_strict_resolver = __esm({
|
|
|
6891
7191
|
}
|
|
6892
7192
|
mergeBranchOwnership(scope, branchExitOwnershipScopes);
|
|
6893
7193
|
this.applyFactsToScope(
|
|
6894
|
-
scope,
|
|
6895
7194
|
scope,
|
|
6896
7195
|
mergeFactSets(branchExitFacts),
|
|
6897
7196
|
"bindings-only"
|
|
@@ -7001,10 +7300,11 @@ var init_strict_resolver = __esm({
|
|
|
7001
7300
|
case "while":
|
|
7002
7301
|
case "doWhile": {
|
|
7003
7302
|
const loopScope = new Scope(scope);
|
|
7004
|
-
invalidateLoopEntryNarrowingsAssignedBy(
|
|
7303
|
+
this.invalidateLoopEntryNarrowingsAssignedBy(
|
|
7005
7304
|
loopScope,
|
|
7006
7305
|
scope,
|
|
7007
|
-
statement.body
|
|
7306
|
+
statement.body,
|
|
7307
|
+
statement.kind === "while" ? localsWithBindings(/* @__PURE__ */ new Set(), statement.condition, true) : /* @__PURE__ */ new Set()
|
|
7008
7308
|
);
|
|
7009
7309
|
const iterationScope = new Scope(loopScope);
|
|
7010
7310
|
let condition;
|
|
@@ -7013,8 +7313,8 @@ var init_strict_resolver = __esm({
|
|
|
7013
7313
|
this.resolveExpression(statement.condition, loopScope),
|
|
7014
7314
|
statement.condition.pos
|
|
7015
7315
|
);
|
|
7016
|
-
this.applyFactsToScope(
|
|
7017
|
-
...
|
|
7316
|
+
this.applyFactsToScope(iterationScope, [
|
|
7317
|
+
...this.conditionFacts(statement.condition, loopScope, true)
|
|
7018
7318
|
]);
|
|
7019
7319
|
}
|
|
7020
7320
|
const bodyScope = new Scope(iterationScope);
|
|
@@ -7051,15 +7351,19 @@ var init_strict_resolver = __esm({
|
|
|
7051
7351
|
);
|
|
7052
7352
|
}
|
|
7053
7353
|
const normalExitScope = new Scope(nextConditionScope);
|
|
7054
|
-
this.applyFactsToScope(
|
|
7055
|
-
...
|
|
7354
|
+
this.applyFactsToScope(normalExitScope, [
|
|
7355
|
+
...this.conditionFacts(
|
|
7356
|
+
statement.condition,
|
|
7357
|
+
nextConditionScope,
|
|
7358
|
+
false
|
|
7359
|
+
)
|
|
7056
7360
|
]);
|
|
7057
7361
|
const effectScopes = nextConditionEffects.length > 0 ? [nextConditionScope] : [];
|
|
7058
7362
|
const exitNarrowings = nextConditionEffects.length > 0 ? [normalExitScope.effectiveNarrowedPaths()] : [];
|
|
7059
7363
|
if (statement.kind === "while") {
|
|
7060
7364
|
const initialExitScope = new Scope(loopScope);
|
|
7061
|
-
this.applyFactsToScope(
|
|
7062
|
-
...
|
|
7365
|
+
this.applyFactsToScope(initialExitScope, [
|
|
7366
|
+
...this.conditionFacts(statement.condition, loopScope, false)
|
|
7063
7367
|
]);
|
|
7064
7368
|
effectScopes.push(loopScope);
|
|
7065
7369
|
exitNarrowings.push(initialExitScope.effectiveNarrowedPaths());
|
|
@@ -7087,17 +7391,30 @@ var init_strict_resolver = __esm({
|
|
|
7087
7391
|
);
|
|
7088
7392
|
}
|
|
7089
7393
|
const loopEntryScope = new Scope(loopScope);
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
statement.
|
|
7093
|
-
|
|
7394
|
+
const conditionLocals = localsWithBindings(
|
|
7395
|
+
/* @__PURE__ */ new Set(),
|
|
7396
|
+
statement.condition,
|
|
7397
|
+
true
|
|
7398
|
+
);
|
|
7399
|
+
this.invalidateLoopEntryNarrowingsAssignedBy(
|
|
7400
|
+
loopEntryScope,
|
|
7401
|
+
loopScope,
|
|
7402
|
+
statement.body,
|
|
7403
|
+
conditionLocals
|
|
7404
|
+
);
|
|
7405
|
+
this.invalidateLoopEntryNarrowingsAssignedBy(
|
|
7406
|
+
loopEntryScope,
|
|
7407
|
+
loopScope,
|
|
7408
|
+
[statement.iterator],
|
|
7409
|
+
conditionLocals
|
|
7410
|
+
);
|
|
7094
7411
|
const condition = this.toBool(
|
|
7095
7412
|
this.resolveExpression(statement.condition, loopEntryScope),
|
|
7096
7413
|
statement.condition.pos
|
|
7097
7414
|
);
|
|
7098
7415
|
const iterationScope = new Scope(loopEntryScope);
|
|
7099
|
-
this.applyFactsToScope(
|
|
7100
|
-
...
|
|
7416
|
+
this.applyFactsToScope(iterationScope, [
|
|
7417
|
+
...this.conditionFacts(statement.condition, loopEntryScope, true)
|
|
7101
7418
|
]);
|
|
7102
7419
|
const bodyScope = new Scope(iterationScope);
|
|
7103
7420
|
const loopFlow = {
|
|
@@ -7133,8 +7450,8 @@ var init_strict_resolver = __esm({
|
|
|
7133
7450
|
);
|
|
7134
7451
|
}
|
|
7135
7452
|
const initialConditionFalseScope = new Scope(loopScope);
|
|
7136
|
-
this.applyFactsToScope(
|
|
7137
|
-
...
|
|
7453
|
+
this.applyFactsToScope(initialConditionFalseScope, [
|
|
7454
|
+
...this.conditionFacts(statement.condition, loopScope, false)
|
|
7138
7455
|
]);
|
|
7139
7456
|
const effectScopes = [loopScope];
|
|
7140
7457
|
const normalExitScopes = [initialConditionFalseScope];
|
|
@@ -7145,11 +7462,13 @@ var init_strict_resolver = __esm({
|
|
|
7145
7462
|
]);
|
|
7146
7463
|
effectScopes.push(postIterationScope);
|
|
7147
7464
|
const subsequentConditionFalseScope = new Scope(postIterationScope);
|
|
7148
|
-
this.applyFactsToScope(
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7465
|
+
this.applyFactsToScope(subsequentConditionFalseScope, [
|
|
7466
|
+
...this.conditionFacts(
|
|
7467
|
+
statement.condition,
|
|
7468
|
+
postIterationScope,
|
|
7469
|
+
false
|
|
7470
|
+
)
|
|
7471
|
+
]);
|
|
7153
7472
|
normalExitScopes.push(subsequentConditionFalseScope);
|
|
7154
7473
|
}
|
|
7155
7474
|
this.mergeLoopEffects(scope, effectScopes, loopFlow.breakEffects);
|
|
@@ -7269,9 +7588,9 @@ var init_strict_resolver = __esm({
|
|
|
7269
7588
|
});
|
|
7270
7589
|
}
|
|
7271
7590
|
const iterationScope = new Scope(loopScope);
|
|
7272
|
-
invalidateLoopEntryNarrowingsAssignedBy(
|
|
7591
|
+
this.invalidateLoopEntryNarrowingsAssignedBy(
|
|
7273
7592
|
iterationScope,
|
|
7274
|
-
|
|
7593
|
+
loopScope,
|
|
7275
7594
|
statement.body
|
|
7276
7595
|
);
|
|
7277
7596
|
const bodyScope = new Scope(iterationScope);
|
|
@@ -7563,8 +7882,8 @@ var init_strict_resolver = __esm({
|
|
|
7563
7882
|
}
|
|
7564
7883
|
const bodyScope = new Scope(catchScope);
|
|
7565
7884
|
if (clause.filter) {
|
|
7566
|
-
this.applyFactsToScope(
|
|
7567
|
-
...
|
|
7885
|
+
this.applyFactsToScope(bodyScope, [
|
|
7886
|
+
...this.conditionFacts(clause.filter, catchScope, true)
|
|
7568
7887
|
]);
|
|
7569
7888
|
}
|
|
7570
7889
|
const catchPointer = {
|
|
@@ -7857,7 +8176,10 @@ var init_strict_resolver = __esm({
|
|
|
7857
8176
|
value.writability ?? "runtime" /* Runtime */
|
|
7858
8177
|
);
|
|
7859
8178
|
}
|
|
7860
|
-
const assignedPath =
|
|
8179
|
+
const assignedPath = this.narrowingPath(
|
|
8180
|
+
canonicalPath(statement.target),
|
|
8181
|
+
scope
|
|
8182
|
+
);
|
|
7861
8183
|
if (assignedPath) {
|
|
7862
8184
|
const rootEntry = scope.lookup(pathRoot(assignedPath));
|
|
7863
8185
|
if (rootEntry) {
|
|
@@ -7896,7 +8218,20 @@ var init_strict_resolver = __esm({
|
|
|
7896
8218
|
* lookup `resolveMember` performs before it overlays a narrowed type.
|
|
7897
8219
|
*/
|
|
7898
8220
|
assignmentStorageType(targetAst, resolvedTarget, local, scope) {
|
|
7899
|
-
if (targetAst.kind === "ident")
|
|
8221
|
+
if (targetAst.kind === "ident") {
|
|
8222
|
+
if (local) return local.type;
|
|
8223
|
+
const path = this.narrowingPath(targetAst.name, scope);
|
|
8224
|
+
if (path === `this.${targetAst.name}`) {
|
|
8225
|
+
return this.resolveMemberNatural(
|
|
8226
|
+
{ kind: "ident", name: "this", pos: targetAst.pos },
|
|
8227
|
+
targetAst.name,
|
|
8228
|
+
scope,
|
|
8229
|
+
targetAst.pos,
|
|
8230
|
+
false
|
|
8231
|
+
).type;
|
|
8232
|
+
}
|
|
8233
|
+
return resolvedTarget.type;
|
|
8234
|
+
}
|
|
7900
8235
|
if (targetAst.kind !== "member") return resolvedTarget.type;
|
|
7901
8236
|
return this.resolveMemberNatural(
|
|
7902
8237
|
targetAst.receiver,
|
|
@@ -7957,7 +8292,10 @@ var init_strict_resolver = __esm({
|
|
|
7957
8292
|
actionType,
|
|
7958
8293
|
scope
|
|
7959
8294
|
);
|
|
7960
|
-
const assignedPath =
|
|
8295
|
+
const assignedPath = this.narrowingPath(
|
|
8296
|
+
canonicalPath(statement.target),
|
|
8297
|
+
scope
|
|
8298
|
+
);
|
|
7961
8299
|
if (assignedPath) {
|
|
7962
8300
|
const rootEntry = scope.lookup(pathRoot(assignedPath));
|
|
7963
8301
|
if (rootEntry) {
|
|
@@ -9108,11 +9446,42 @@ var init_strict_resolver = __esm({
|
|
|
9108
9446
|
pos
|
|
9109
9447
|
);
|
|
9110
9448
|
}
|
|
9111
|
-
|
|
9449
|
+
narrowingPath(path, scope) {
|
|
9450
|
+
if (path === null) return null;
|
|
9451
|
+
const root = pathRoot(path);
|
|
9452
|
+
if (scope.lookup(root)) return path;
|
|
9453
|
+
if (this.context.project.globals.some((symbol) => symbol.name === root)) {
|
|
9454
|
+
return path;
|
|
9455
|
+
}
|
|
9456
|
+
const implicit = this.implicitMember(root);
|
|
9457
|
+
return implicit && implicit.symbol.static !== true ? `this.${path}` : path;
|
|
9458
|
+
}
|
|
9459
|
+
conditionFacts(expression, scope, whenTrue) {
|
|
9460
|
+
const pathOf = (value) => this.narrowingPath(canonicalPath(value), scope);
|
|
9461
|
+
return whenTrue ? factsWhenTrue(expression, pathOf) : factsWhenFalse(expression, pathOf);
|
|
9462
|
+
}
|
|
9463
|
+
/**
|
|
9464
|
+
* A loop body is resolved once but can execute repeatedly. Any narrowing rooted
|
|
9465
|
+
* in an outer binding that the body or iterator may write is therefore stale
|
|
9466
|
+
* at a later iteration entry. Invalidate those roots before resolving the
|
|
9467
|
+
* shared iteration so only the loop's own condition can narrow them again.
|
|
9468
|
+
*/
|
|
9469
|
+
invalidateLoopEntryNarrowingsAssignedBy(loopEntryScope, outerScope, statements, locals = /* @__PURE__ */ new Set()) {
|
|
9470
|
+
for (const rootName of collectAssignedPathRoots(
|
|
9471
|
+
statements,
|
|
9472
|
+
/* @__PURE__ */ new Set(),
|
|
9473
|
+
locals
|
|
9474
|
+
)) {
|
|
9475
|
+
const path = this.narrowingPath(rootName, outerScope);
|
|
9476
|
+
const outerEntry = path === null ? null : outerScope.lookup(pathRoot(path));
|
|
9477
|
+
if (outerEntry) loopEntryScope.hideInheritedNarrowing(outerEntry);
|
|
9478
|
+
}
|
|
9479
|
+
}
|
|
9480
|
+
applyFactsToScope(targetScope, facts, mode = "all") {
|
|
9112
9481
|
for (const fact of facts) {
|
|
9113
9482
|
if (mode === "bindings-only" && !fact.bindingName) continue;
|
|
9114
|
-
const natural = this.resolveExpression(fact.expression,
|
|
9115
|
-
const rootEntry = fact.path === null ? null :
|
|
9483
|
+
const natural = this.resolveExpression(fact.expression, targetScope);
|
|
9484
|
+
const rootEntry = fact.path === null ? null : targetScope.lookup(pathRoot(fact.path));
|
|
9116
9485
|
if (fact.nullValue) {
|
|
9117
9486
|
if (fact.path === null || rootEntry === null) continue;
|
|
9118
9487
|
if (fact.loose === true && natural.type.kind === "primitive" && (natural.type.name === "string" || natural.type.name === "int" || natural.type.name === "float" || natural.type.name === "bool")) {
|
|
@@ -9418,7 +9787,10 @@ var init_strict_resolver = __esm({
|
|
|
9418
9787
|
optional2
|
|
9419
9788
|
);
|
|
9420
9789
|
if (!optional2) {
|
|
9421
|
-
const receiverPath =
|
|
9790
|
+
const receiverPath = this.narrowingPath(
|
|
9791
|
+
canonicalPath(receiverAst),
|
|
9792
|
+
scope
|
|
9793
|
+
);
|
|
9422
9794
|
if (receiverPath) {
|
|
9423
9795
|
const rootEntry = scope.lookup(pathRoot(receiverPath));
|
|
9424
9796
|
if (rootEntry) {
|
|
@@ -12507,7 +12879,10 @@ var init_strict_resolver = __esm({
|
|
|
12507
12879
|
scope,
|
|
12508
12880
|
true
|
|
12509
12881
|
);
|
|
12510
|
-
const path =
|
|
12882
|
+
const path = this.narrowingPath(
|
|
12883
|
+
canonicalPath(expression.callee.receiver),
|
|
12884
|
+
scope
|
|
12885
|
+
);
|
|
12511
12886
|
if (path) {
|
|
12512
12887
|
const rootEntry = scope.lookup(pathRoot(path));
|
|
12513
12888
|
if (rootEntry) scope.invalidate(rootEntry);
|
|
@@ -12568,15 +12943,13 @@ var init_strict_resolver = __esm({
|
|
|
12568
12943
|
);
|
|
12569
12944
|
const trueScope = new Scope(scope);
|
|
12570
12945
|
this.applyFactsToScope(
|
|
12571
|
-
scope,
|
|
12572
12946
|
trueScope,
|
|
12573
|
-
|
|
12947
|
+
this.conditionFacts(expression.condition, scope, true)
|
|
12574
12948
|
);
|
|
12575
12949
|
const falseScope = new Scope(scope);
|
|
12576
12950
|
this.applyFactsToScope(
|
|
12577
|
-
scope,
|
|
12578
12951
|
falseScope,
|
|
12579
|
-
|
|
12952
|
+
this.conditionFacts(expression.condition, scope, false)
|
|
12580
12953
|
);
|
|
12581
12954
|
let whenTrue;
|
|
12582
12955
|
let whenFalse;
|
|
@@ -12658,9 +13031,8 @@ var init_strict_resolver = __esm({
|
|
|
12658
13031
|
if (expression.op === "&&" || expression.op === "||") {
|
|
12659
13032
|
rightScope = new Scope(scope);
|
|
12660
13033
|
this.applyFactsToScope(
|
|
12661
|
-
scope,
|
|
12662
13034
|
rightScope,
|
|
12663
|
-
expression.op === "&&" ?
|
|
13035
|
+
expression.op === "&&" ? this.conditionFacts(expression.left, scope, true) : this.conditionFacts(expression.left, scope, false)
|
|
12664
13036
|
);
|
|
12665
13037
|
}
|
|
12666
13038
|
const right = preResolvedRight ?? this.resolveExpression(expression.right, rightScope, left.type);
|
|
@@ -35212,9 +35584,14 @@ var init_service = __esm({
|
|
|
35212
35584
|
if (state.context.projectSourceKind !== "spec") continue;
|
|
35213
35585
|
const snapshot = this.scriptSnapshot(state);
|
|
35214
35586
|
for (const candidate of snapshot.parsed.references) {
|
|
35215
|
-
if (
|
|
35216
|
-
|
|
35217
|
-
|
|
35587
|
+
if (candidate.name !== declaration.name) continue;
|
|
35588
|
+
const symbolId = resolveReferenceSymbolId(snapshot, candidate);
|
|
35589
|
+
if (symbolId === null) continue;
|
|
35590
|
+
const matches = declaration.id !== null ? symbolId === declaration.id : sameLocationInList(
|
|
35591
|
+
declaration.location,
|
|
35592
|
+
definition(snapshot, candidate.range.start)
|
|
35593
|
+
);
|
|
35594
|
+
if (!matches) continue;
|
|
35218
35595
|
locations.push({ uri: state.document.uri, range: candidate.range });
|
|
35219
35596
|
}
|
|
35220
35597
|
}
|
|
@@ -146022,7 +146399,7 @@ var init_registry2 = __esm({
|
|
|
146022
146399
|
"../packages/manifest/schema-contract/registry.mjs"() {
|
|
146023
146400
|
"use strict";
|
|
146024
146401
|
PROJECT_SCHEMA_CONTRACT = Object.freeze({
|
|
146025
|
-
cliVersion: "0.61.
|
|
146402
|
+
cliVersion: "0.61.4",
|
|
146026
146403
|
projectFileUploadBatchSize: 32,
|
|
146027
146404
|
documentRecords: {
|
|
146028
146405
|
member: {
|
|
@@ -154702,7 +155079,7 @@ There is no --keep-current: preserving current semantic state defines flatten.
|
|
|
154702
155079
|
async function main() {
|
|
154703
155080
|
const args = parseArgs(process.argv.slice(2));
|
|
154704
155081
|
if (args.command === "--version") {
|
|
154705
|
-
console.log("0.61.
|
|
155082
|
+
console.log("0.61.4");
|
|
154706
155083
|
return;
|
|
154707
155084
|
}
|
|
154708
155085
|
if (args.command === null || args.command === "help" || args.command === "--help" || args.command === "-h") {
|
package/package.json
CHANGED
|
@@ -110,7 +110,7 @@ wrappers.
|
|
|
110
110
|
The marker near the top of `SKILL.md` must exactly match the package version:
|
|
111
111
|
|
|
112
112
|
```html
|
|
113
|
-
<!-- reviewed-through-cli: 0.61.
|
|
113
|
+
<!-- reviewed-through-cli: 0.61.4 -->
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
The quoted version above is checked too, so this instruction cannot go stale
|
|
@@ -158,6 +158,11 @@ chain, so `config.Hat?.Head.Idle.Down.Frames` safely returns null when `Hat` is
|
|
|
158
158
|
null. A descendant that is itself nullable still needs its own `?.`, `??`, `!`,
|
|
159
159
|
or narrowing guard before the next access.
|
|
160
160
|
|
|
161
|
+
Inside an instance body, `Member` and `this.Member` share null and type-check
|
|
162
|
+
narrowing. A local or parameter named `Member` shadows the implicit member;
|
|
163
|
+
`this.Member` still names the instance field. Reassigning a narrowed path to a
|
|
164
|
+
nullable value clears its non-null fact.
|
|
165
|
+
|
|
161
166
|
Treat lookup-return values with the same nullable narrowing rules.
|
|
162
167
|
|
|
163
168
|
Runtime declaration patterns follow the possible runtime type, not only the
|