carrick 0.3.118 → 0.3.120
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/read.d.ts +5 -0
- package/dist/auth/read.js +5 -0
- package/dist/auth/read.js.map +1 -1
- package/dist/init/doctor.d.ts +22 -2
- package/dist/init/doctor.js +44 -4
- package/dist/init/doctor.js.map +1 -1
- package/dist/init/hosted.d.ts +5 -1
- package/dist/init/hosted.js +8 -2
- package/dist/init/hosted.js.map +1 -1
- package/dist/init/run.d.ts +9 -2
- package/dist/init/run.js +613 -344
- package/dist/init/run.js.map +1 -1
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/sidecar/dist/src/library-claims.js +128 -15
- package/sidecar/dist/src/position-rows.d.ts +27 -8
- package/sidecar/dist/src/position-rows.js +156 -14
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* | `compare` | `=== !== == != < > <= >= instanceof in` | the left operand | the left operand |
|
|
15
15
|
* | `ident` | an identifier in expression position | itself | itself |
|
|
16
16
|
* | `impl` | a `call` or `member` whose declaration has no body | an implementation of it | nothing |
|
|
17
|
+
* | `decl` | a `call` or `member` on a union of declaring types | one of those declarations | nothing |
|
|
17
18
|
* | `jsx` | a JSX opening or self-closing element's tag | the tag's name | the tag |
|
|
18
19
|
*
|
|
19
20
|
* An `impl` row (version 2, carrick#2430) follows the `call` or `member` row
|
|
@@ -24,9 +25,18 @@
|
|
|
24
25
|
* initializer. Its `decl_*` name the implementing declaration. Past
|
|
25
26
|
* {@link IMPL_CAP} the row is one, with {@link FLAG_TOO_MANY} and nothing else.
|
|
26
27
|
*
|
|
27
|
-
* A row
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* A `decl` row (version 3, carrick#2448) follows the `call` or `member` row
|
|
29
|
+
* it belongs to, before its `impl` rows, and has its span: one per
|
|
30
|
+
* declaration of the member when the receiver is a union whose constituents
|
|
31
|
+
* declare it at more than one place (`(pick ? a : b).get()` with two
|
|
32
|
+
* classes). That row names only the first of them. Each constituent's
|
|
33
|
+
* declaration is its own member's, or, for a member with none (a mapped
|
|
34
|
+
* type's), the declaration of the constituent type itself. Sorted and capped
|
|
35
|
+
* as `impl` rows are; `type_text` is `null`.
|
|
36
|
+
*
|
|
37
|
+
* A row's key is `(start, end, kind)`, except that several `impl` rows, and
|
|
38
|
+
* several `decl` rows, share one: TypeScript `getStart()`/`getEnd()` of the
|
|
39
|
+
* node, in UTF-16 code units from the start of the file, which is what the scanner's `sidecar_position`
|
|
30
40
|
* gives for an SWC span. Every path written is relative to the scanned repo's
|
|
31
41
|
* root, with `/` separators.
|
|
32
42
|
*
|
|
@@ -49,7 +59,7 @@ import { WriteGuard, installedPackageDirectory, isDeclarationFileName, moduleExp
|
|
|
49
59
|
import { attributedDeclaration, installedPackageOf } from './declaration-attribution.js';
|
|
50
60
|
import { typeToStringAsDeclared } from './print-type.js';
|
|
51
61
|
/** The format's version, written in the header. */
|
|
52
|
-
export const POSITION_ROWS_VERSION =
|
|
62
|
+
export const POSITION_ROWS_VERSION = 3;
|
|
53
63
|
/** The type is `any`, declared or inferred. Never set with the error type. */
|
|
54
64
|
export const FLAG_ANY = 1;
|
|
55
65
|
/** The type is the compiler's error type: something did not resolve. */
|
|
@@ -58,9 +68,18 @@ export const FLAG_ERROR_TYPE = 2;
|
|
|
58
68
|
export const FLAG_CHECKER_THREW = 4;
|
|
59
69
|
/** The declaration is outside the checkout, not the default library and in no installed package. */
|
|
60
70
|
export const FLAG_DECLARATION_UNNAMED = 8;
|
|
61
|
-
/** An `impl` row standing for more
|
|
71
|
+
/** An `impl` or `decl` row standing for more than {@link IMPL_CAP} rows of its kind; it names none. */
|
|
62
72
|
export const FLAG_TOO_MANY = 16;
|
|
63
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* The declaration is published under the row's symbol name: its module
|
|
75
|
+
* exports it by that name, or it is a global (a script's top-level
|
|
76
|
+
* declaration, or one in `declare global`). A member of a class, interface,
|
|
77
|
+
* type literal or object literal never is (carrick#2508).
|
|
78
|
+
*/
|
|
79
|
+
export const FLAG_PUBLISHED = 32;
|
|
80
|
+
/** The declaration is what its module exports as `export =` or `default` (carrick#2508). */
|
|
81
|
+
export const FLAG_MODULE_DEFAULT = 64;
|
|
82
|
+
/** The most `impl` rows one declaration lists, and the most `decl` rows one position lists. */
|
|
64
83
|
export const IMPL_CAP = 16;
|
|
65
84
|
const COMPARE_OPERATORS = new Set([
|
|
66
85
|
ts.SyntaxKind.EqualsEqualsEqualsToken,
|
|
@@ -379,6 +398,8 @@ class PositionWalker {
|
|
|
379
398
|
implementations = new Map();
|
|
380
399
|
/** The same for a member whose symbol has no declaration, keyed by symbol. */
|
|
381
400
|
undeclaredImplementations = new Map();
|
|
401
|
+
/** Each module's exports by name, and its `export =` and `default` targets, aliases followed. */
|
|
402
|
+
moduleExports = new Map();
|
|
382
403
|
constructor(program, service, paths, loader) {
|
|
383
404
|
this.program = program;
|
|
384
405
|
this.service = service;
|
|
@@ -394,6 +415,8 @@ class PositionWalker {
|
|
|
394
415
|
const row = this.row(kind, node, sourceFile);
|
|
395
416
|
rows.push(row);
|
|
396
417
|
if ((kind === 'call' || kind === 'member') && !(row[8] & FLAG_CHECKER_THREW)) {
|
|
418
|
+
for (const decl of this.declRows(kind, node))
|
|
419
|
+
rows.push(['decl', row[1], row[2], ...tail(decl)]);
|
|
397
420
|
for (const impl of this.implRows(kind, node))
|
|
398
421
|
rows.push(['impl', row[1], row[2], ...tail(impl)]);
|
|
399
422
|
}
|
|
@@ -424,6 +447,9 @@ class PositionWalker {
|
|
|
424
447
|
this.ownerDeclaration(kind, node, symbol);
|
|
425
448
|
if (!declaration)
|
|
426
449
|
return [kind, start, end, ts.symbolName(symbol), null, null, null, typeText, flags];
|
|
450
|
+
// A declaration named through its owner's type is a member.
|
|
451
|
+
if ((symbol.declarations ?? []).includes(declaration))
|
|
452
|
+
flags |= this.publication(symbol, declaration);
|
|
427
453
|
// A file's own module symbol is named by the compiler as the quoted
|
|
428
454
|
// absolute file name (`"/<checkout>/pkg/index"`). Name it as `decl_file`
|
|
429
455
|
// names the file. A symbol that merely lives in a file (CommonJS
|
|
@@ -566,20 +592,135 @@ class PositionWalker {
|
|
|
566
592
|
* constituent that has the property; with several the row is left as it is.
|
|
567
593
|
*/
|
|
568
594
|
ownerDeclaration(kind, node, symbol) {
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
const named = nameNodeOf(kind, node);
|
|
572
|
-
const access = named?.parent;
|
|
573
|
-
if (!access || !(ts.isPropertyAccessExpression(access) || ts.isElementAccessExpression(access))) {
|
|
595
|
+
const receiver = this.receiverOf(kind, node);
|
|
596
|
+
if (!receiver)
|
|
574
597
|
return undefined;
|
|
575
|
-
}
|
|
576
|
-
const receiver = this.checker.getTypeAtLocation(access.expression);
|
|
577
598
|
const holders = (receiver.isUnionOrIntersection() ? receiver.types : [receiver]).filter((constituent) => constituent.getProperty(symbol.name) !== undefined);
|
|
578
599
|
if (holders.length !== 1)
|
|
579
600
|
return undefined;
|
|
580
|
-
|
|
601
|
+
return this.typeDeclaration(holders[0]);
|
|
602
|
+
}
|
|
603
|
+
/** The declaration of a type's symbol, else of its alias symbol: a mapped type node, or the alias naming it. */
|
|
604
|
+
typeDeclaration(type) {
|
|
605
|
+
const owner = type.getSymbol() ?? type.aliasSymbol;
|
|
581
606
|
return attributedDeclaration(() => this.program, owner?.declarations ?? []);
|
|
582
607
|
}
|
|
608
|
+
/**
|
|
609
|
+
* How `declaration`'s module publishes `symbol`: {@link FLAG_PUBLISHED}
|
|
610
|
+
* when under the symbol's own name (or as a global), and
|
|
611
|
+
* {@link FLAG_MODULE_DEFAULT} when as the module's `export =` or `default`.
|
|
612
|
+
* The module is the nearest ambient `declare module "…"` or the file.
|
|
613
|
+
*/
|
|
614
|
+
publication(symbol, declaration) {
|
|
615
|
+
let container = declaration.parent;
|
|
616
|
+
while (container && !ts.isSourceFile(container) && !ts.isModuleBlock(container)) {
|
|
617
|
+
// Anything but a statement list between the declaration and its module
|
|
618
|
+
// (a class, interface, type or object literal, a function body) makes
|
|
619
|
+
// it a member or a local.
|
|
620
|
+
if (!ts.isVariableDeclarationList(container) && !ts.isVariableStatement(container))
|
|
621
|
+
return 0;
|
|
622
|
+
container = container.parent;
|
|
623
|
+
}
|
|
624
|
+
if (!container)
|
|
625
|
+
return 0;
|
|
626
|
+
const block = ts.isModuleBlock(container) ? container.parent : undefined;
|
|
627
|
+
if (block && block.flags & ts.NodeFlags.GlobalAugmentation)
|
|
628
|
+
return FLAG_PUBLISHED;
|
|
629
|
+
// A namespace's member is published when the module its file is publishes it.
|
|
630
|
+
if (block && !ts.isStringLiteral(block.name))
|
|
631
|
+
return this.publishedByExports(symbol, declaration);
|
|
632
|
+
const moduleSymbol = this.checker.getSymbolAtLocation(block ? block.name : container);
|
|
633
|
+
if (moduleSymbol)
|
|
634
|
+
return this.publishedIn(moduleSymbol, symbol);
|
|
635
|
+
// A script's top-level declaration is a global.
|
|
636
|
+
return ts.isSourceFile(container) && !ts.isExternalModule(container) ? FLAG_PUBLISHED : 0;
|
|
637
|
+
}
|
|
638
|
+
/** A namespace member, found among the exports of the module it sits in. */
|
|
639
|
+
publishedByExports(symbol, declaration) {
|
|
640
|
+
for (let node = declaration.parent; node; node = node.parent) {
|
|
641
|
+
if (ts.isModuleDeclaration(node) && ts.isStringLiteral(node.name)) {
|
|
642
|
+
const moduleSymbol = this.checker.getSymbolAtLocation(node.name);
|
|
643
|
+
return moduleSymbol ? this.publishedIn(moduleSymbol, symbol) : 0;
|
|
644
|
+
}
|
|
645
|
+
if (ts.isSourceFile(node)) {
|
|
646
|
+
const moduleSymbol = this.checker.getSymbolAtLocation(node);
|
|
647
|
+
return moduleSymbol ? this.publishedIn(moduleSymbol, symbol) & FLAG_PUBLISHED : 0;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return 0;
|
|
651
|
+
}
|
|
652
|
+
publishedIn(moduleSymbol, symbol) {
|
|
653
|
+
let exports = this.moduleExports.get(moduleSymbol);
|
|
654
|
+
if (!exports) {
|
|
655
|
+
const resolve = (s) => s.flags & ts.SymbolFlags.Alias ? this.checker.getAliasedSymbol(s) : s;
|
|
656
|
+
const byName = new Map();
|
|
657
|
+
for (const exported of this.checker.getExportsOfModule(moduleSymbol)) {
|
|
658
|
+
byName.set(exported.getName(), resolve(exported));
|
|
659
|
+
}
|
|
660
|
+
const wholes = [ts.InternalSymbolName.ExportEquals, ts.InternalSymbolName.Default]
|
|
661
|
+
.map((key) => moduleSymbol.exports?.get(key))
|
|
662
|
+
.filter((own) => own !== undefined)
|
|
663
|
+
.map(resolve);
|
|
664
|
+
exports = { byName, wholes };
|
|
665
|
+
this.moduleExports.set(moduleSymbol, exports);
|
|
666
|
+
}
|
|
667
|
+
return ((exports.byName.get(symbol.getName()) === symbol ? FLAG_PUBLISHED : 0) |
|
|
668
|
+
(exports.wholes.includes(symbol) ? FLAG_MODULE_DEFAULT : 0));
|
|
669
|
+
}
|
|
670
|
+
/** The type of the object a `member` or `call` row's name is read on, if the name is read on one. */
|
|
671
|
+
receiverOf(kind, node) {
|
|
672
|
+
if (kind !== 'member' && kind !== 'call')
|
|
673
|
+
return undefined;
|
|
674
|
+
const access = nameNodeOf(kind, node)?.parent;
|
|
675
|
+
if (!access || !(ts.isPropertyAccessExpression(access) || ts.isElementAccessExpression(access))) {
|
|
676
|
+
return undefined;
|
|
677
|
+
}
|
|
678
|
+
return this.checker.getTypeAtLocation(access.expression);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* The `decl` rows of a `call` or `member` row (spans unset): one per
|
|
682
|
+
* declaration the receiver's union constituents give the member, when they
|
|
683
|
+
* give more than one (carrick#2448). A constituent's declaration is its
|
|
684
|
+
* member's ({@link attributedDeclaration}), or, for a member with none, the
|
|
685
|
+
* constituent type's own ({@link typeDeclaration}). Two instantiations of
|
|
686
|
+
* one generic class, or one class and `undefined`, give one, and no row.
|
|
687
|
+
* A throw writes one row flagged {@link FLAG_CHECKER_THREW}.
|
|
688
|
+
*/
|
|
689
|
+
declRows(kind, node) {
|
|
690
|
+
const found = new Set();
|
|
691
|
+
let name;
|
|
692
|
+
try {
|
|
693
|
+
const symbol = this.symbolOf(kind, node);
|
|
694
|
+
const receiver = this.receiverOf(kind, node);
|
|
695
|
+
if (!symbol || !receiver || !receiver.isUnion())
|
|
696
|
+
return [];
|
|
697
|
+
name = ts.symbolName(symbol);
|
|
698
|
+
for (const constituent of receiver.types) {
|
|
699
|
+
const member = constituent.getProperty(symbol.name);
|
|
700
|
+
if (!member)
|
|
701
|
+
continue;
|
|
702
|
+
const declaration = attributedDeclaration(() => this.program, member.declarations ?? []) ?? this.typeDeclaration(constituent);
|
|
703
|
+
if (declaration)
|
|
704
|
+
found.add(declaration);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
catch {
|
|
708
|
+
return [['decl', 0, 0, null, null, null, null, null, FLAG_CHECKER_THREW]];
|
|
709
|
+
}
|
|
710
|
+
if (found.size < 2)
|
|
711
|
+
return [];
|
|
712
|
+
if (found.size > IMPL_CAP)
|
|
713
|
+
return [['decl', 0, 0, null, null, null, null, null, FLAG_TOO_MANY]];
|
|
714
|
+
const rows = [...found].map((declaration) => {
|
|
715
|
+
const file = declaration.getSourceFile();
|
|
716
|
+
const start = declaration.getStart(file);
|
|
717
|
+
const { declFile, declLine, declPackage } = this.located(file, start);
|
|
718
|
+
const flags = declFile === null ? FLAG_DECLARATION_UNNAMED : 0;
|
|
719
|
+
return { start, row: ['decl', 0, 0, name, declFile, declLine, declPackage, null, flags] };
|
|
720
|
+
});
|
|
721
|
+
rows.sort((a, b) => compareNames(a.row[4], b.row[4]) || a.start - b.start);
|
|
722
|
+
return rows.map(({ row }) => row);
|
|
723
|
+
}
|
|
583
724
|
/** The row's symbol, following aliases to a target that has a declaration. */
|
|
584
725
|
symbolOf(kind, node) {
|
|
585
726
|
let symbol;
|
|
@@ -778,6 +919,7 @@ function nameNodeOf(kind, node) {
|
|
|
778
919
|
case 'ident':
|
|
779
920
|
return node;
|
|
780
921
|
case 'impl':
|
|
922
|
+
case 'decl':
|
|
781
923
|
return undefined;
|
|
782
924
|
case 'jsx':
|
|
783
925
|
// The tag: `<Badge>`, `<ui.Button>`, `<this.Panel>`; a namespaced
|