@cplieger/deadset-ts 4.0.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/bin/component-mapper.js +5 -0
- package/dist/bin/mapper-connection.js +101 -0
- package/dist/bin/node-host.js +24 -2
- package/dist/src/analysis.js +229 -36
- package/dist/src/component-files.js +612 -0
- package/dist/src/component-layer.js +132 -0
- package/dist/src/config.js +9 -2
- package/dist/src/configuration-files.js +186 -0
- package/dist/src/conformance-record.js +2 -2
- package/dist/src/convention-rows.js +383 -0
- package/dist/src/conventions.js +456 -0
- package/dist/src/dependencies.js +30 -3
- package/dist/src/discover.js +10 -3
- package/dist/src/emit-map.js +72 -0
- package/dist/src/entry-point-gaps.js +81 -35
- package/dist/src/entry-points.js +47 -32
- package/dist/src/exempt.js +11 -3
- package/dist/src/findings/completion.js +19 -29
- package/dist/src/findings/emitters.js +22 -1
- package/dist/src/findings/unused-declarations.js +7 -2
- package/dist/src/graph.js +13 -5
- package/dist/src/inventory.js +4 -2
- package/dist/src/kinds.js +2 -2
- package/dist/src/manifest.js +37 -11
- package/dist/src/matrix.js +21 -13
- package/dist/src/partial.js +3 -1
- package/dist/src/pnpm-workspace.js +120 -0
- package/dist/src/position.js +17 -2
- package/dist/src/print.js +2 -0
- package/dist/src/references.js +209 -30
- package/dist/src/report.js +26 -6
- package/dist/src/reporters/annotations.js +10 -3
- package/dist/src/reporters/template.js +3 -0
- package/dist/src/resolve.js +31 -6
- package/dist/src/roots.js +37 -8
- package/dist/src/run.js +13 -3
- package/dist/src/schema.js +2 -0
- package/dist/src/session.js +141 -34
- package/dist/src/setup-failure.js +23 -0
- package/dist/src/source-files.js +4 -61
- package/dist/src/sweep.js +4 -2
- package/dist/src/template-field.js +38 -6
- package/dist/src/test-support.js +59 -0
- package/dist/src/type-errors.js +252 -0
- package/dist/src/type-query-alias.js +92 -0
- package/dist/src/verbs/analyze.js +24 -4
- package/dist/src/verbs/explain.js +4 -1
- package/dist/src/verbs/print-projects.js +17 -56
- package/dist/src/verbs/print-retained.js +7 -2
- package/dist/src/verbs/print-roots.js +7 -2
- package/dist/src/version-range.js +255 -0
- package/dist/src/version.js +1 -1
- package/dist/src/workspace-manifests.js +68 -0
- package/dist/src/workspace-programs.js +342 -0
- package/dist/src/workspace-resolution.js +307 -0
- package/dist/src/workspace-run.js +75 -0
- package/dist/src/workspace.js +358 -0
- package/jsr.json +1 -1
- package/package.json +2 -1
- package/src/analysis.ts +394 -70
- package/src/component-files.ts +718 -0
- package/src/component-layer.ts +160 -0
- package/src/config.ts +11 -2
- package/src/configuration-files.ts +235 -0
- package/src/conformance-record.ts +2 -2
- package/src/convention-rows.ts +440 -0
- package/src/conventions.ts +640 -0
- package/src/dependencies.ts +36 -2
- package/src/discover.ts +10 -6
- package/src/emit-map.ts +93 -0
- package/src/entry-point-gaps.ts +92 -38
- package/src/entry-points.ts +66 -36
- package/src/exempt.ts +21 -3
- package/src/findings/completion.ts +24 -33
- package/src/findings/emitters.ts +32 -1
- package/src/findings/unused-declarations.ts +9 -2
- package/src/graph.ts +15 -4
- package/src/host.ts +23 -0
- package/src/index.ts +1 -1
- package/src/inventory.ts +13 -2
- package/src/kinds.ts +2 -2
- package/src/manifest.ts +47 -14
- package/src/matrix.ts +43 -15
- package/src/partial.ts +6 -1
- package/src/pnpm-workspace.ts +135 -0
- package/src/position.ts +23 -2
- package/src/print.ts +2 -0
- package/src/references.ts +227 -28
- package/src/report.ts +56 -6
- package/src/reporters/annotations.ts +12 -3
- package/src/reporters/template.ts +3 -0
- package/src/resolve.ts +59 -6
- package/src/roots.ts +60 -9
- package/src/run.ts +15 -5
- package/src/schema.ts +2 -0
- package/src/session.ts +218 -37
- package/src/setup-failure.ts +39 -0
- package/src/source-files.ts +4 -66
- package/src/sweep.ts +9 -2
- package/src/template-field.ts +42 -7
- package/src/test-support.ts +77 -0
- package/src/type-errors.ts +340 -0
- package/src/type-query-alias.ts +133 -0
- package/src/verbs/analyze.ts +38 -4
- package/src/verbs/explain.ts +4 -1
- package/src/verbs/print-projects.ts +17 -69
- package/src/verbs/print-retained.ts +7 -2
- package/src/verbs/print-roots.ts +7 -2
- package/src/verbs/verb.ts +6 -3
- package/src/version-range.ts +309 -0
- package/src/version.ts +1 -1
- package/src/workspace-manifests.ts +100 -0
- package/src/workspace-programs.ts +486 -0
- package/src/workspace-resolution.ts +393 -0
- package/src/workspace-run.ts +148 -0
- package/src/workspace.ts +463 -0
package/src/report.ts
CHANGED
|
@@ -13,18 +13,16 @@ import type {
|
|
|
13
13
|
FindingPosition,
|
|
14
14
|
PositionedSymbol,
|
|
15
15
|
} from "./finding.ts";
|
|
16
|
+
import type { AppliedConvention } from "./conventions.ts";
|
|
16
17
|
import type { PassResult } from "./findings-pass.ts";
|
|
17
18
|
import type { StaleSuppression } from "./findings/self-check.ts";
|
|
18
19
|
import type { TestFileRule } from "./references.ts";
|
|
19
20
|
|
|
20
21
|
/** The version of the report schema this analyzer writes a report to. */
|
|
21
|
-
const SCHEMA_VERSION = "
|
|
22
|
+
const SCHEMA_VERSION = "7.0.0";
|
|
22
23
|
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
* implements admits, each an instance of the one it writes.
|
|
26
|
-
*/
|
|
27
|
-
export const SCHEMA_VERSIONS_ACCEPTED: readonly string[] = ["6.0.0", SCHEMA_VERSION];
|
|
24
|
+
/** Every report schema version this analyzer reads: the one the Contract it implements admits. */
|
|
25
|
+
export const SCHEMA_VERSIONS_ACCEPTED: readonly string[] = [SCHEMA_VERSION];
|
|
28
26
|
|
|
29
27
|
/** The name this analyzer writes every document under and mints every identifier with. */
|
|
30
28
|
export const ANALYZER_NAME = "deadset-ts";
|
|
@@ -151,6 +149,22 @@ export interface ReportNotBuilt {
|
|
|
151
149
|
readonly error: string;
|
|
152
150
|
}
|
|
153
151
|
|
|
152
|
+
/** One type error that skipped the function or statement holding it. */
|
|
153
|
+
export interface TypeErrorSkip {
|
|
154
|
+
/** The file holding the error, below the target root. */
|
|
155
|
+
readonly path: string;
|
|
156
|
+
readonly line: number;
|
|
157
|
+
/** The compiler's message, on one line. */
|
|
158
|
+
readonly message: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** One configuration in which the checker left questions unanswered, with what they held. */
|
|
162
|
+
export interface UnansweredCount {
|
|
163
|
+
readonly configuration: string;
|
|
164
|
+
readonly questions: number;
|
|
165
|
+
readonly declarations: number;
|
|
166
|
+
}
|
|
167
|
+
|
|
154
168
|
/** One consumer the run loaded, at the directory a report names it by. */
|
|
155
169
|
interface ReportConsumer {
|
|
156
170
|
readonly id: string;
|
|
@@ -201,6 +215,10 @@ export interface Report {
|
|
|
201
215
|
readonly declared_gaps: readonly WireDeclaredGap[];
|
|
202
216
|
readonly excluded_by_cgo: readonly never[];
|
|
203
217
|
readonly test_file_rules: readonly TestFileRule[];
|
|
218
|
+
readonly type_error_skips: readonly TypeErrorSkip[];
|
|
219
|
+
readonly notes: readonly never[];
|
|
220
|
+
readonly unanswered_questions: readonly UnansweredCount[];
|
|
221
|
+
readonly conventions_applied: readonly AppliedConvention[];
|
|
204
222
|
readonly totals: WireTotals;
|
|
205
223
|
}
|
|
206
224
|
|
|
@@ -217,6 +235,10 @@ export interface ReportInput {
|
|
|
217
235
|
readonly unavailable: readonly UnavailableConsumer[];
|
|
218
236
|
readonly result: PassResult;
|
|
219
237
|
readonly testFileRules: readonly TestFileRule[];
|
|
238
|
+
readonly typeErrorSkips: readonly TypeErrorSkip[];
|
|
239
|
+
readonly unanswered: readonly UnansweredCount[];
|
|
240
|
+
/** The convention rows the run applied, in the report's order. */
|
|
241
|
+
readonly conventionsApplied: readonly AppliedConvention[];
|
|
220
242
|
}
|
|
221
243
|
|
|
222
244
|
/** Two strings ordered bytewise. */
|
|
@@ -462,6 +484,34 @@ export function buildReport(input: ReportInput): Report {
|
|
|
462
484
|
test_file_rules: [...input.testFileRules]
|
|
463
485
|
.sort((a, b) => compare(a.rule, b.rule) || a.matched - b.matched)
|
|
464
486
|
.map((one) => ({ rule: one.rule, matched: one.matched })),
|
|
487
|
+
type_error_skips: [
|
|
488
|
+
...new Map(
|
|
489
|
+
input.typeErrorSkips.map((one) => {
|
|
490
|
+
const skip = { path: one.path, line: one.line, message: one.message };
|
|
491
|
+
return [JSON.stringify(skip), skip] as const;
|
|
492
|
+
}),
|
|
493
|
+
),
|
|
494
|
+
]
|
|
495
|
+
.sort(([a, x], [b, y]) => compare(x.path, y.path) || x.line - y.line || compare(a, b))
|
|
496
|
+
.map(([, skip]) => skip),
|
|
497
|
+
notes: [],
|
|
498
|
+
unanswered_questions: [...input.unanswered]
|
|
499
|
+
.sort(
|
|
500
|
+
(a, b) =>
|
|
501
|
+
compare(a.configuration, b.configuration) ||
|
|
502
|
+
compare(JSON.stringify(a), JSON.stringify(b)),
|
|
503
|
+
)
|
|
504
|
+
.map((one) => ({
|
|
505
|
+
configuration: one.configuration,
|
|
506
|
+
questions: one.questions,
|
|
507
|
+
declarations: one.declarations,
|
|
508
|
+
})),
|
|
509
|
+
conventions_applied: input.conventionsApplied.map((one) => ({
|
|
510
|
+
name: one.name,
|
|
511
|
+
package: one.package,
|
|
512
|
+
version: one.version,
|
|
513
|
+
manifest: one.manifest,
|
|
514
|
+
})),
|
|
465
515
|
totals: totalsOf(findings, input.result),
|
|
466
516
|
};
|
|
467
517
|
}
|
|
@@ -37,11 +37,17 @@ function command(
|
|
|
37
37
|
return `::${level} file=${escapeProperty(at.path)},line=${String(at.line)},col=${String(at.column)},endLine=${String(endLine)},title=${escapeProperty(title)}::${escapeData(message)}`;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** The title and the message prefix of a type-error skip's annotation. */
|
|
41
|
+
const SKIP_TITLE = "type error skipped";
|
|
42
|
+
const SKIP_MESSAGE =
|
|
43
|
+
"the analysis did not evaluate the function or statement holding this type error: ";
|
|
44
|
+
|
|
40
45
|
/**
|
|
41
46
|
* One workflow annotation per finding, then one per stale suppression, each naming its
|
|
42
|
-
* file, line, column and last line, titled by its code and kind
|
|
43
|
-
*
|
|
44
|
-
*
|
|
47
|
+
* file, line, column and last line, titled by its code and kind, then one warning per
|
|
48
|
+
* type-error skip naming its file and line. A finding at or above the failing severity is
|
|
49
|
+
* an error and one below it a warning; a stale suppression is an error, because its kind
|
|
50
|
+
* is fixed on at the failing severity.
|
|
45
51
|
*/
|
|
46
52
|
export function annotations(report: Report, options: RenderOptions): Iterable<string> {
|
|
47
53
|
return coalesced(
|
|
@@ -64,6 +70,9 @@ export function annotations(report: Report, options: RenderOptions): Iterable<st
|
|
|
64
70
|
stale.message,
|
|
65
71
|
)}\n`;
|
|
66
72
|
}
|
|
73
|
+
for (const skip of report.type_error_skips) {
|
|
74
|
+
yield `::warning file=${escapeProperty(skip.path)},line=${String(skip.line)},title=${escapeProperty(SKIP_TITLE)}::${escapeData(SKIP_MESSAGE + skip.message)}\n`;
|
|
75
|
+
}
|
|
67
76
|
})(),
|
|
68
77
|
);
|
|
69
78
|
}
|
|
@@ -925,6 +925,9 @@ class Execution {
|
|
|
925
925
|
if (head === undefined) {
|
|
926
926
|
throw new RenderError("empty command");
|
|
927
927
|
}
|
|
928
|
+
if (head.k === "lit" && head.value === null) {
|
|
929
|
+
throw new RenderError("nil is not a command");
|
|
930
|
+
}
|
|
928
931
|
if (head.k !== "func") {
|
|
929
932
|
if (rest.length > 0 || piped !== undefined) {
|
|
930
933
|
throw new RenderError("cannot give an argument to a non-function");
|
package/src/resolve.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
type TargetKind,
|
|
22
22
|
type TemplateDelimiters,
|
|
23
23
|
} from "./config.ts";
|
|
24
|
+
import { CONVENTION_ROWS } from "./convention-rows.ts";
|
|
24
25
|
import { FIXED_SEVERITY_CODES, LIVE_CODES } from "./kinds.ts";
|
|
25
26
|
import {
|
|
26
27
|
checkDocument,
|
|
@@ -105,6 +106,8 @@ interface Doc {
|
|
|
105
106
|
readonly providers: readonly Provider[] | undefined;
|
|
106
107
|
readonly testFiles: readonly string[] | undefined;
|
|
107
108
|
readonly entryFiles: readonly string[] | undefined;
|
|
109
|
+
readonly componentExtensions: readonly string[] | undefined;
|
|
110
|
+
readonly disabledConventions: readonly string[] | undefined;
|
|
108
111
|
readonly injectionRegistrations: readonly DeclarationEntry[] | undefined;
|
|
109
112
|
readonly lifecycleContracts: readonly LifecycleContract[] | undefined;
|
|
110
113
|
readonly serializers: readonly DeclarationEntry[] | undefined;
|
|
@@ -277,6 +280,44 @@ function readStrings<T extends string>(
|
|
|
277
280
|
return value as readonly T[];
|
|
278
281
|
}
|
|
279
282
|
|
|
283
|
+
/** A component file's extension: a full stop followed by letters and digits. */
|
|
284
|
+
const COMPONENT_EXTENSION = /^\.[A-Za-z0-9]+$/u;
|
|
285
|
+
|
|
286
|
+
function readComponentExtensions(
|
|
287
|
+
ts: Record<string, unknown> | undefined,
|
|
288
|
+
label: string,
|
|
289
|
+
): readonly string[] | undefined {
|
|
290
|
+
const extensions = readStrings(ts, "component_extensions", "ts.component_extensions", label, 0);
|
|
291
|
+
const wrong = extensions?.find((one) => !COMPONENT_EXTENSION.test(one));
|
|
292
|
+
if (wrong !== undefined) {
|
|
293
|
+
throw malformed(
|
|
294
|
+
label,
|
|
295
|
+
"ts.component_extensions",
|
|
296
|
+
`${JSON.stringify(wrong)} is not a full stop followed by letters and digits`,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return extensions;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** The names of the convention rows this analyzer's table carries. */
|
|
303
|
+
const CONVENTION_NAMES: ReadonlySet<string> = new Set(CONVENTION_ROWS.map((row) => row.name));
|
|
304
|
+
|
|
305
|
+
function readDisabledConventions(
|
|
306
|
+
ts: Record<string, unknown> | undefined,
|
|
307
|
+
label: string,
|
|
308
|
+
): readonly string[] | undefined {
|
|
309
|
+
const names = readStrings(ts, "disabled_conventions", "ts.disabled_conventions", label, 0);
|
|
310
|
+
const unknown = names?.find((one) => !CONVENTION_NAMES.has(one));
|
|
311
|
+
if (unknown !== undefined) {
|
|
312
|
+
throw malformed(
|
|
313
|
+
label,
|
|
314
|
+
"ts.disabled_conventions",
|
|
315
|
+
`${JSON.stringify(unknown)} names no convention row this analyzer carries`,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
return names;
|
|
319
|
+
}
|
|
320
|
+
|
|
280
321
|
function requireMember(value: string | undefined, path: string, label: string): string {
|
|
281
322
|
if (value === undefined || value === "") {
|
|
282
323
|
throw malformed(label, path, "is required and names nothing");
|
|
@@ -792,6 +833,8 @@ function readDoc(value: unknown, label: string): Doc {
|
|
|
792
833
|
providers: readProviders(providers, label),
|
|
793
834
|
testFiles: readStrings(ts, "test_files", "ts.test_files", label, 1),
|
|
794
835
|
entryFiles: readStrings(ts, "entry_files", "ts.entry_files", label, 0),
|
|
836
|
+
componentExtensions: readComponentExtensions(ts, label),
|
|
837
|
+
disabledConventions: readDisabledConventions(ts, label),
|
|
795
838
|
injectionRegistrations: readDeclarations(
|
|
796
839
|
ts,
|
|
797
840
|
"injection_registrations",
|
|
@@ -986,13 +1029,13 @@ export function resolve(inputs: Inputs): { config: Config; provenance: Provenanc
|
|
|
986
1029
|
}
|
|
987
1030
|
|
|
988
1031
|
/**
|
|
989
|
-
* The
|
|
990
|
-
*
|
|
991
|
-
*
|
|
992
|
-
*
|
|
1032
|
+
* The configuration the documents resolve to, every document read and refused as
|
|
1033
|
+
* {@link resolve} refuses it, with no target kind required of them: which projects a
|
|
1034
|
+
* run analyzes does not depend on the kind, so a question about the projects asks
|
|
1035
|
+
* none. The kind is empty where no document names one.
|
|
993
1036
|
*/
|
|
994
|
-
export function
|
|
995
|
-
return settleAll(inputs).config
|
|
1037
|
+
export function resolveUnkinded(inputs: Inputs): Config {
|
|
1038
|
+
return settleAll(inputs).config;
|
|
996
1039
|
}
|
|
997
1040
|
|
|
998
1041
|
/**
|
|
@@ -1076,6 +1119,16 @@ function settleAll(inputs: Inputs): { config: Config; provenance: Map<string, Or
|
|
|
1076
1119
|
ts: {
|
|
1077
1120
|
testFiles: at("ts.test_files", defaults.ts.testFiles, (doc) => doc.testFiles),
|
|
1078
1121
|
entryFiles: at("ts.entry_files", defaults.ts.entryFiles, (doc) => doc.entryFiles),
|
|
1122
|
+
componentExtensions: at(
|
|
1123
|
+
"ts.component_extensions",
|
|
1124
|
+
defaults.ts.componentExtensions,
|
|
1125
|
+
(doc) => doc.componentExtensions,
|
|
1126
|
+
),
|
|
1127
|
+
disabledConventions: at(
|
|
1128
|
+
"ts.disabled_conventions",
|
|
1129
|
+
defaults.ts.disabledConventions,
|
|
1130
|
+
(doc) => doc.disabledConventions,
|
|
1131
|
+
),
|
|
1079
1132
|
injectionRegistrations: at(
|
|
1080
1133
|
"ts.injection_registrations",
|
|
1081
1134
|
defaults.ts.injectionRegistrations,
|
package/src/roots.ts
CHANGED
|
@@ -10,29 +10,43 @@
|
|
|
10
10
|
|
|
11
11
|
import type { SourceFile } from "@typescript/native/unstable/ast";
|
|
12
12
|
import { aliasChains } from "./alias-chain.ts";
|
|
13
|
+
import { conventionEntries, type Conventions } from "./conventions.ts";
|
|
13
14
|
import { entryPoints, type EntryRule } from "./entry-points.ts";
|
|
14
15
|
import { globExpression } from "./glob.ts";
|
|
16
|
+
import type { Host } from "./host.ts";
|
|
15
17
|
import { nodeKey, type Inventory, type InventorySymbol } from "./inventory.ts";
|
|
16
18
|
import type { Manifest, ManifestEntry } from "./manifest.ts";
|
|
17
19
|
import { byPosition } from "./position.ts";
|
|
18
20
|
import { UNANSWERED } from "./query.ts";
|
|
19
21
|
import type { ProjectView } from "./session.ts";
|
|
20
22
|
import { sourceFilesOf } from "./source-files.ts";
|
|
23
|
+
import { typeQueryAliases } from "./type-query-alias.ts";
|
|
21
24
|
|
|
22
25
|
/** Why one declaration is a root. */
|
|
23
26
|
export type RootKind =
|
|
24
27
|
/** A file `ts.entry_files` names, and what it exports. */
|
|
25
28
|
| "entry-file"
|
|
29
|
+
/** A file an applied convention row's globs match, and what it exports. */
|
|
30
|
+
| "convention"
|
|
26
31
|
/** A file the manifest names as an importable entry point, and what it exports outside the published API. */
|
|
27
32
|
| "manifest-entry"
|
|
28
33
|
/** A file the manifest names as a command, and what it exports outside the published API. */
|
|
29
34
|
| "manifest-binary"
|
|
35
|
+
/** A file a token of a manifest's script names, and what it exports. */
|
|
36
|
+
| "script"
|
|
37
|
+
/**
|
|
38
|
+
* A global a declaration file declares as an alias of a module's export, and the
|
|
39
|
+
* module declarations around it: a use of the global is a use of the export.
|
|
40
|
+
*/
|
|
41
|
+
| "type-query-alias"
|
|
30
42
|
/** A declaration a consumer of a library target can name. */
|
|
31
43
|
| "published-api"
|
|
32
44
|
/** A declaration an exact reference from the configuration names. */
|
|
33
45
|
| "configured"
|
|
34
46
|
/** A declaration a pattern from the configuration names. */
|
|
35
47
|
| "pattern"
|
|
48
|
+
/** A declaration of a function or statement a type error skipped, and what it may have selected. */
|
|
49
|
+
| "type-error"
|
|
36
50
|
/** A file a tool or the platform enters by its own convention, and what it exports where the tool reads it. */
|
|
37
51
|
| EntryRule;
|
|
38
52
|
|
|
@@ -81,18 +95,34 @@ export interface Roots {
|
|
|
81
95
|
|
|
82
96
|
/** What decides the roots beside the declarations themselves. */
|
|
83
97
|
export interface RootOptions {
|
|
98
|
+
/** The platform the configuration files beside the program are read from. */
|
|
99
|
+
readonly host: Host;
|
|
84
100
|
/** The target's own manifest. */
|
|
85
101
|
readonly manifest: Manifest;
|
|
102
|
+
/**
|
|
103
|
+
* The entry points the other packages of the target's workspace name, each already
|
|
104
|
+
* marked published or not by its own manifest's rule.
|
|
105
|
+
*/
|
|
106
|
+
readonly workspaceEntries?: readonly ManifestEntry[] | undefined;
|
|
86
107
|
/** `roots.patterns` from the resolved configuration. */
|
|
87
108
|
readonly patterns: readonly string[];
|
|
88
109
|
/** `ts.entry_files` from the resolved configuration. */
|
|
89
110
|
readonly entryFiles: readonly string[];
|
|
111
|
+
/** The convention rows the run applied. */
|
|
112
|
+
readonly conventions?: Conventions | undefined;
|
|
90
113
|
/** `ts.test_files` from the resolved configuration. */
|
|
91
114
|
readonly testFiles: readonly string[];
|
|
92
115
|
/** Whether the target is a library, so a consumer outside it reaches its published API. */
|
|
93
116
|
readonly publishedAPI: boolean;
|
|
94
117
|
}
|
|
95
118
|
|
|
119
|
+
/** The kind of root each role of a manifest entry makes. */
|
|
120
|
+
const ENTRY_KINDS = {
|
|
121
|
+
import: "manifest-entry",
|
|
122
|
+
run: "manifest-binary",
|
|
123
|
+
script: "script",
|
|
124
|
+
} as const satisfies Record<ManifestEntry["role"], RootKind>;
|
|
125
|
+
|
|
96
126
|
/** Whether a configured string carries either special character. */
|
|
97
127
|
function isPattern(text: string): boolean {
|
|
98
128
|
return text.includes("*") || text.includes("?");
|
|
@@ -204,19 +234,24 @@ export function roots<Brand>(
|
|
|
204
234
|
};
|
|
205
235
|
|
|
206
236
|
const published: SourceFile[] = [];
|
|
207
|
-
const
|
|
208
|
-
options.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
237
|
+
const entries = [
|
|
238
|
+
...options.manifest.entries.map((entry) => ({
|
|
239
|
+
entry,
|
|
240
|
+
publishes:
|
|
241
|
+
entry.published &&
|
|
242
|
+
(options.manifest.declaresExports ? entry.member.startsWith("exports") : true),
|
|
243
|
+
})),
|
|
244
|
+
...(options.workspaceEntries ?? []).map((entry) => ({ entry, publishes: entry.published })),
|
|
245
|
+
];
|
|
246
|
+
for (const { entry, publishes } of entries) {
|
|
247
|
+
if (options.publishedAPI && publishes) {
|
|
213
248
|
published.push(...files.named(entry.path));
|
|
214
249
|
}
|
|
215
250
|
}
|
|
216
251
|
const publishedNames = new Set(published.map((file) => file.fileName));
|
|
217
|
-
for (const entry of
|
|
252
|
+
for (const { entry } of entries) {
|
|
218
253
|
for (const file of files.named(entry.path)) {
|
|
219
|
-
const kind = entry.role
|
|
254
|
+
const kind = ENTRY_KINDS[entry.role];
|
|
220
255
|
enter(file, kind, entry.member, !publishedNames.has(file.fileName));
|
|
221
256
|
}
|
|
222
257
|
}
|
|
@@ -228,9 +263,25 @@ export function roots<Brand>(
|
|
|
228
263
|
}
|
|
229
264
|
}
|
|
230
265
|
}
|
|
231
|
-
for (const
|
|
266
|
+
for (const { file, row } of options.conventions === undefined
|
|
267
|
+
? []
|
|
268
|
+
: conventionEntries(options.conventions, files)) {
|
|
269
|
+
enter(file, "convention", row, true);
|
|
270
|
+
}
|
|
271
|
+
for (const point of entryPoints(project, files, options.testFiles, options.host, targetRoot)) {
|
|
232
272
|
enter(point.file, point.rule, point.source, point.exports);
|
|
233
273
|
}
|
|
274
|
+
for (const file of files.byPath.values()) {
|
|
275
|
+
for (const alias of typeQueryAliases(file)) {
|
|
276
|
+
const source = alias.type.getText().replace(/\s+/gu, " ");
|
|
277
|
+
for (const node of [alias.declaration, ...alias.containers]) {
|
|
278
|
+
const id = declared.get(nodeKey(file, node));
|
|
279
|
+
if (id !== undefined) {
|
|
280
|
+
add(id, "type-query-alias", source);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
234
285
|
|
|
235
286
|
const { tables: exportsOf, answered } = exportTables(project, held, [
|
|
236
287
|
...entered.filter((entry) => entry.exports).map((entry) => entry.file),
|
package/src/run.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { EMITTERS } from "./findings/emitters.ts";
|
|
|
4
4
|
import type { Host } from "./host.ts";
|
|
5
5
|
import { joinPath, resolvePath } from "./paths.ts";
|
|
6
6
|
import { readScope, ScopeError, scopeForDir, type Scope } from "./scope.ts";
|
|
7
|
-
import {
|
|
7
|
+
import { SetupError, setupLine } from "./setup-failure.ts";
|
|
8
|
+
import { openEngine, type Engine, type EngineOptions } from "./session.ts";
|
|
8
9
|
import { printConfigVerb } from "./verbs/print-config.ts";
|
|
9
10
|
import { printProjectsVerb } from "./verbs/print-projects.ts";
|
|
10
11
|
import { printRetainedVerb } from "./verbs/print-retained.ts";
|
|
@@ -204,7 +205,7 @@ export function run(
|
|
|
204
205
|
out: Writer,
|
|
205
206
|
err: Writer,
|
|
206
207
|
host: Host,
|
|
207
|
-
openClient: (
|
|
208
|
+
openClient: (options: EngineOptions) => Engine = openEngine,
|
|
208
209
|
): number {
|
|
209
210
|
const editing = sourceEditOption(args);
|
|
210
211
|
if (editing !== undefined) {
|
|
@@ -243,7 +244,7 @@ function invoke(
|
|
|
243
244
|
own: VerbOptions,
|
|
244
245
|
args: readonly string[],
|
|
245
246
|
streams: { readonly out: Writer; readonly err: Writer; readonly host: Host },
|
|
246
|
-
openClient: (
|
|
247
|
+
openClient: (options: EngineOptions) => Engine,
|
|
247
248
|
): number {
|
|
248
249
|
let options: Options | undefined;
|
|
249
250
|
const read = (): Options => (options ??= readOptions(args, own));
|
|
@@ -256,8 +257,11 @@ function invoke(
|
|
|
256
257
|
scope: () => scopeOf(streams.host, read()),
|
|
257
258
|
option: (name) => read().named.get(name),
|
|
258
259
|
repeated: (name) => read().repeated.get(name) ?? [],
|
|
259
|
-
openClient: (
|
|
260
|
-
opened = openClient(
|
|
260
|
+
openClient: (config) => {
|
|
261
|
+
opened = openClient({
|
|
262
|
+
collectTiming: false,
|
|
263
|
+
components: { extensions: config.ts.componentExtensions, host: streams.host },
|
|
264
|
+
});
|
|
261
265
|
return opened;
|
|
262
266
|
},
|
|
263
267
|
emitters: EMITTERS,
|
|
@@ -282,6 +286,12 @@ function refuse(error: unknown, err: Writer): number {
|
|
|
282
286
|
err.write(`deadset-ts: ${error.message}\n`);
|
|
283
287
|
return EXIT_FAILURE;
|
|
284
288
|
}
|
|
289
|
+
if (error instanceof SetupError) {
|
|
290
|
+
for (const failure of error.failures) {
|
|
291
|
+
err.write(`${setupLine(failure)}\n`);
|
|
292
|
+
}
|
|
293
|
+
return EXIT_FAILURE;
|
|
294
|
+
}
|
|
285
295
|
if (error instanceof ScopeError) {
|
|
286
296
|
err.write(`deadset-ts: ${error.message}\n`);
|
|
287
297
|
return EXIT_FAILURE;
|
package/src/schema.ts
CHANGED