@cplieger/deadset-ts 2.2.1 → 3.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.
Files changed (45) hide show
  1. package/README.md +9 -16
  2. package/dist/src/analysis.js +142 -0
  3. package/dist/src/components.js +289 -0
  4. package/dist/src/config.js +6 -0
  5. package/dist/src/discover.js +98 -24
  6. package/dist/src/entry-point-gaps.js +278 -0
  7. package/dist/src/entry-points.js +385 -0
  8. package/dist/src/finding.js +12 -0
  9. package/dist/src/glob.js +65 -0
  10. package/dist/src/graph.js +116 -0
  11. package/dist/src/index.js +1 -2
  12. package/dist/src/manifest.js +120 -0
  13. package/dist/src/print.js +3 -6
  14. package/dist/src/references.js +156 -106
  15. package/dist/src/resolve.js +82 -20
  16. package/dist/src/roots.js +345 -0
  17. package/dist/src/run.js +59 -10
  18. package/dist/src/schema.js +1 -1
  19. package/dist/src/session.js +6 -1
  20. package/dist/src/source-files.js +122 -0
  21. package/dist/src/sweep.js +156 -0
  22. package/dist/src/version.js +1 -1
  23. package/jsr.json +1 -1
  24. package/package.json +3 -3
  25. package/src/analysis.ts +236 -0
  26. package/src/components.ts +372 -0
  27. package/src/config.ts +30 -2
  28. package/src/discover.ts +144 -29
  29. package/src/entry-point-gaps.ts +304 -0
  30. package/src/entry-points.ts +496 -0
  31. package/src/finding.ts +43 -0
  32. package/src/glob.ts +67 -0
  33. package/src/graph.ts +178 -0
  34. package/src/index.ts +1 -20
  35. package/src/manifest.ts +174 -0
  36. package/src/print.ts +5 -6
  37. package/src/references.ts +201 -111
  38. package/src/resolve.ts +117 -24
  39. package/src/roots.ts +467 -0
  40. package/src/run.ts +66 -11
  41. package/src/schema.ts +5 -2
  42. package/src/session.ts +6 -1
  43. package/src/source-files.ts +157 -0
  44. package/src/sweep.ts +230 -0
  45. package/src/version.ts +1 -1
@@ -1,5 +1,6 @@
1
- import { isArrayLiteralExpression, isBinaryExpression, isDeleteExpression, isElementAccessExpression, isForInStatement, isForOfStatement, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, SyntaxKind, } from "@typescript/native/unstable/ast";
1
+ import { isArrayLiteralExpression, isBinaryExpression, isDeleteExpression, isElementAccessExpression, isExportDeclaration, isForInStatement, isForOfStatement, isNamespaceExport, isObjectLiteralExpression, isParenthesizedExpression, isPostfixUnaryExpression, isPrefixUnaryExpression, isPropertyAccessExpression, isPropertyAssignment, isShorthandPropertyAssignment, isSpreadAssignment, isSpreadElement, SyntaxKind, } from "@typescript/native/unstable/ast";
2
2
  import { SymbolFlags } from "@typescript/native/unstable/sync";
3
+ import { globExpression } from "./glob.js";
3
4
  import { nodeKey } from "./inventory.js";
4
5
  import { byPosition, renderPosition } from "./position.js";
5
6
  /**
@@ -125,18 +126,54 @@ function markStores(node, writes) {
125
126
  }
126
127
  }
127
128
  }
129
+ /**
130
+ * The re-exports one node writes, if it is an export declaration. A specifier and a
131
+ * namespace export are declarations whose names are where they are written, so no use is
132
+ * read from them; each references what it carries forward instead. A bare star declares
133
+ * nothing, so the declaration enclosing it, at the top level the file, references the
134
+ * module it names.
135
+ */
136
+ function linksOf(file, node, declarations, enclosing) {
137
+ if (!isExportDeclaration(node)) {
138
+ return [];
139
+ }
140
+ const clause = node.exportClause;
141
+ const specifier = node.moduleSpecifier;
142
+ if (clause === undefined) {
143
+ return specifier === undefined
144
+ ? []
145
+ : [{ node: specifier, at: specifier, from: enclosing, alias: false }];
146
+ }
147
+ if (isNamespaceExport(clause)) {
148
+ const from = declarations.get(nodeKey(file, clause));
149
+ return from === undefined
150
+ ? []
151
+ : [{ node: clause.name, at: specifier ?? clause.name, from, alias: true }];
152
+ }
153
+ const found = [];
154
+ for (const element of clause.elements) {
155
+ const from = declarations.get(nodeKey(file, element));
156
+ if (from !== undefined) {
157
+ found.push({
158
+ node: element.name,
159
+ at: element.propertyName ?? element.name,
160
+ from,
161
+ alias: true,
162
+ });
163
+ }
164
+ }
165
+ return found;
166
+ }
128
167
  /**
129
168
  * Every name node one file holds that is a use rather than a declaration, in source
130
- * order, each with the declaration that encloses it and the use it makes.
131
- *
132
- * One walk answers all three, because the three facts are positional and a second walk
133
- * would have to agree with this one about which nodes are names. A name that is the
134
- * declared name of the declaration it belongs to is left out: it is where that
135
- * declaration is written rather than a use of it, which is what makes a declaration
136
- * referenced only from its own site an unreferenced declaration.
169
+ * order, each with its enclosing declaration and its use, and every re-export the file
170
+ * writes. One walk answers all of it, because a second would have to agree with this one
171
+ * about which nodes are names. A declaration's own declared name is left out, which is
172
+ * what makes a declaration referenced only from its own site an unreferenced one.
137
173
  */
138
174
  function sitesOf(file, declarations, fileId) {
139
175
  const found = [];
176
+ const links = [];
140
177
  const writes = new Set();
141
178
  const declared = new Set();
142
179
  const shorthands = new Map();
@@ -172,6 +209,7 @@ function sitesOf(file, declarations, fileId) {
172
209
  }
173
210
  markNames(node);
174
211
  markStores(node, writes);
212
+ links.push(...linksOf(file, node, declarations, enclosing));
175
213
  const held = declarations.get(nodeKey(file, node));
176
214
  const outer = enclosing;
177
215
  if (held !== undefined) {
@@ -181,63 +219,7 @@ function sitesOf(file, declarations, fileId) {
181
219
  enclosing = outer;
182
220
  };
183
221
  file.forEachChild(visit);
184
- return found;
185
- }
186
- /**
187
- * One literal run of a pattern, with every character the expression syntax claims
188
- * escaped.
189
- *
190
- * The set is the syntax characters and the solidus, and it is closed: an escape of any
191
- * other character is refused outright by the expression syntax under the unicode flag,
192
- * so escaping a hyphen, which needs none outside a character class, would refuse every
193
- * pattern that names a hyphenated path.
194
- */
195
- function quoted(text) {
196
- return text.replaceAll(/[.*+?^${}()|[\]\\/]/gu, (character) => `\\${character}`);
197
- }
198
- /**
199
- * The expression one glob pattern denotes. `**` spans path separators while `*` and `?`
200
- * do not, a brace list is an alternation of its members, and every other character
201
- * stands for itself.
202
- */
203
- function expressionOf(pattern) {
204
- let source = "^";
205
- let at = 0;
206
- while (at < pattern.length) {
207
- const rest = pattern.slice(at);
208
- if (rest.startsWith("**/")) {
209
- source += "(?:[^/]*/)*";
210
- at += 3;
211
- continue;
212
- }
213
- if (rest.startsWith("**")) {
214
- source += ".*";
215
- at += 2;
216
- continue;
217
- }
218
- const character = pattern[at] ?? "";
219
- at += 1;
220
- if (character === "*") {
221
- source += "[^/]*";
222
- continue;
223
- }
224
- if (character === "?") {
225
- source += "[^/]";
226
- continue;
227
- }
228
- if (character === "{") {
229
- const close = pattern.indexOf("}", at);
230
- if (close < 0) {
231
- source += "\\{";
232
- continue;
233
- }
234
- source += `(?:${pattern.slice(at, close).split(",").map(quoted).join("|")})`;
235
- at = close + 1;
236
- continue;
237
- }
238
- source += quoted(character);
239
- }
240
- return new RegExp(`${source}$`, "u");
222
+ return { uses: found, links };
241
223
  }
242
224
  /**
243
225
  * The name one test-file rule takes. A rule's name is a word list the report's own
@@ -270,10 +252,12 @@ function compare(a, b) {
270
252
  export function references(project, held, targetRoot, options) {
271
253
  const cap = options.batchCap ?? DEFAULT_BATCH_CAP;
272
254
  const declarations = held.declarations;
273
- const patterns = options.testFiles.map(expressionOf);
255
+ const patterns = options.testFiles.map(globExpression);
274
256
  const matched = options.testFiles.map(() => 0);
275
257
  const found = [];
258
+ const tests = [];
276
259
  const reached = new Map();
260
+ const steps = new Map();
277
261
  let batched = 0;
278
262
  let fileBatches = 0;
279
263
  let residueFallbacks = 0;
@@ -283,23 +267,51 @@ export function references(project, held, targetRoot, options) {
283
267
  const ownFiles = new Set(files.map((file) => file.fileName));
284
268
  /** The identifier of the declaration one node of this program is, where it is one. */
285
269
  const declaredAt = (node) => declarations.get(nodeKey(node.getSourceFile(), node));
270
+ /**
271
+ * The declarations of the inventory one symbol is.
272
+ *
273
+ * A declaration handle carries the file it is in, so the question is answered before
274
+ * the handle is resolved: a declaration outside the project's own files belongs to
275
+ * another program and is never read, which is what keeps the pass from fetching a
276
+ * library file to discover that the inventory does not hold what is in it.
277
+ */
278
+ const declarationsOf = (symbol) => {
279
+ const ids = [];
280
+ for (const handle of symbol.declarations) {
281
+ if (!ownFiles.has(handle.path)) {
282
+ continue;
283
+ }
284
+ const node = project.declarationAt(handle)?.node;
285
+ const id = node === undefined ? undefined : declaredAt(node);
286
+ if (id !== undefined && !ids.includes(id)) {
287
+ ids.push(id);
288
+ }
289
+ }
290
+ return ids;
291
+ };
292
+ /**
293
+ * What one alias names, one link along, asked once per alias whatever the number of
294
+ * chains it is a link of. Only a symbol the binder flagged an alias is asked, which is
295
+ * the condition the step asserts on: a default export of an expression is written in
296
+ * an alias form and names nothing declared elsewhere, so its chain ends at itself.
297
+ */
298
+ const stepOf = (symbol) => {
299
+ if ((symbol.flags & SymbolFlags.Alias) === 0) {
300
+ return undefined;
301
+ }
302
+ if (steps.has(symbol.id)) {
303
+ return steps.get(symbol.id);
304
+ }
305
+ const next = project.aliasStepOf(symbol);
306
+ aliasSteps += 1;
307
+ steps.set(symbol.id, next);
308
+ return next;
309
+ };
286
310
  /**
287
311
  * The declarations one symbol names: the declaration it is, and every link of the
288
312
  * alias chain it stands at the head of. A re-export something imports is used and so
289
313
  * is the declaration behind it, so both are named; a link this project does not
290
314
  * declare is stepped over rather than recorded.
291
- *
292
- * A symbol is asked to step only where the binder flagged it an alias, which is the
293
- * same condition the step itself asserts on. The declaration's syntax is not that
294
- * condition and does not stand in for it: a default export of an expression is
295
- * written as one of the alias forms and names nothing declared elsewhere, so it is
296
- * recorded as the declaration it is and the chain ends there.
297
- *
298
- * A declaration handle carries the file it is in, so the question the walk asks of a
299
- * declaration is answered before it is resolved: a declaration outside the project's
300
- * own files belongs to another program and is never read, which is what keeps the
301
- * pass from fetching a library file to discover that the inventory does not hold what
302
- * is in it.
303
315
  */
304
316
  const targetsOf = (symbol) => {
305
317
  const cached = reached.get(symbol.id);
@@ -312,34 +324,47 @@ export function references(project, held, targetRoot, options) {
312
324
  let stepped = false;
313
325
  while (at !== undefined && !walked.has(at.id)) {
314
326
  walked.add(at.id);
315
- const alias = (at.flags & SymbolFlags.Alias) !== 0;
316
- for (const handle of at.declarations) {
317
- if (!ownFiles.has(handle.path)) {
318
- continue;
319
- }
320
- const node = project.declarationAt(handle)?.node;
321
- const id = node === undefined ? undefined : declaredAt(node);
322
- if (id !== undefined && !targets.some((target) => target.id === id)) {
327
+ for (const id of declarationsOf(at)) {
328
+ if (!targets.some((target) => target.id === id)) {
323
329
  targets.push({ id, stepped });
324
330
  }
325
331
  }
326
- if (!alias) {
327
- break;
328
- }
329
- at = project.aliasStepOf(at);
330
- aliasSteps += 1;
332
+ at = stepOf(at);
331
333
  stepped = true;
332
334
  }
333
335
  reached.set(symbol.id, targets);
334
336
  return targets;
335
337
  };
338
+ /**
339
+ * The declarations one re-export carries forward: for an alias, the first link along
340
+ * its chain that the inventory declares, stepping over the links it does not, such as
341
+ * an import the re-export is written against; for a bare star, the module it names.
342
+ * Each later link is a declaration of its own that references the next, so one link
343
+ * per re-export is what lets a chain be followed one declaration at a time.
344
+ */
345
+ const carriedBy = (link, symbol) => {
346
+ if (!link.alias) {
347
+ return declarationsOf(symbol);
348
+ }
349
+ const walked = new Set([symbol.id]);
350
+ let at = stepOf(symbol);
351
+ while (at !== undefined && !walked.has(at.id)) {
352
+ walked.add(at.id);
353
+ const ids = declarationsOf(at);
354
+ if (ids.length > 0) {
355
+ return ids;
356
+ }
357
+ at = stepOf(at);
358
+ }
359
+ return [];
360
+ };
336
361
  /** The symbol one site resolves to, asking only the accessor the site's form names. */
337
362
  const symbolFor = (site, answered) => {
338
363
  if (site.shorthand !== undefined) {
339
364
  shorthandLookups += 1;
340
365
  return project.shorthandValueAt(project.handle(site.shorthand));
341
366
  }
342
- const batched = answered.get(site.node.pos);
367
+ const batched = answered.get(site.node);
343
368
  if (batched !== undefined) {
344
369
  return batched;
345
370
  }
@@ -348,35 +373,59 @@ export function references(project, held, targetRoot, options) {
348
373
  };
349
374
  for (const file of files) {
350
375
  const path = renderPosition(file, targetRoot, 0).path;
351
- let test = false;
352
- patterns.forEach((pattern, index) => {
353
- if (pattern.test(path)) {
376
+ const hits = patterns.map((pattern) => pattern.test(path));
377
+ hits.forEach((hit, index) => {
378
+ if (hit) {
354
379
  matched[index] = (matched[index] ?? 0) + 1;
355
- test = true;
356
380
  }
357
381
  });
358
- const sites = sitesOf(file, declarations, declaredAt(file) ?? "");
359
- // One batch per capped run of the file's name nodes. A shorthand is left out of
360
- // the batch: its name resolves to the property the literal declares, so the batch's
361
- // answer for it would name something this project's inventory never holds.
362
- const batching = sites.filter((site) => site.shorthand === undefined);
382
+ const test = hits.includes(true);
383
+ if (test) {
384
+ tests.push(path);
385
+ }
386
+ const { uses, links } = sitesOf(file, declarations, declaredAt(file) ?? "");
387
+ // One batch per capped run of the file's name nodes, the re-exports' nodes after
388
+ // the uses. A shorthand is left out of the batch: its name resolves to the property
389
+ // the literal declares, so the batch's answer for it would name something this
390
+ // project's inventory never holds.
391
+ const batching = [
392
+ ...uses.filter((site) => site.shorthand === undefined).map((site) => site.node),
393
+ ...links.map((link) => link.node),
394
+ ];
363
395
  const answered = new Map();
364
396
  batched += batching.length;
365
397
  for (let from = 0; from < batching.length; from += cap) {
366
398
  const run = batching.slice(from, from + cap);
367
- const answers = project.symbolsAt(run.map((site) => project.handle(site.node)));
399
+ const answers = project.symbolsAt(run.map((node) => project.handle(node)));
368
400
  fileBatches += 1;
369
- run.forEach((site, index) => {
401
+ run.forEach((node, index) => {
370
402
  const symbol = answers[index];
371
403
  if (symbol !== undefined) {
372
- answered.set(site.node.pos, symbol);
404
+ answered.set(node, symbol);
373
405
  }
374
406
  });
375
407
  }
376
- for (const site of sites) {
408
+ for (const link of links) {
409
+ const symbol = answered.get(link.node);
410
+ if (symbol === undefined) {
411
+ continue;
412
+ }
413
+ const position = renderPosition(file, targetRoot, link.at.getStart());
414
+ for (const id of carriedBy(link, symbol)) {
415
+ found.push({
416
+ from: link.from,
417
+ to: id,
418
+ position,
419
+ use: "read",
420
+ resolution: link.alias ? "alias" : "batch",
421
+ test,
422
+ });
423
+ }
424
+ }
425
+ for (const site of uses) {
377
426
  const direct = site.shorthand !== undefined
378
427
  ? "shorthand"
379
- : answered.has(site.node.pos)
428
+ : answered.has(site.node)
380
429
  ? "batch"
381
430
  : "resolved-symbol";
382
431
  const symbol = symbolFor(site, answered);
@@ -406,6 +455,7 @@ export function references(project, held, targetRoot, options) {
406
455
  testFileRules: options.testFiles
407
456
  .map((_pattern, index) => ({ rule: patternRule(index), matched: matched[index] ?? 0 }))
408
457
  .sort((a, b) => compare(a.rule, b.rule)),
458
+ testFilePaths: tests.sort(compare),
409
459
  cost: { batched, fileBatches, residueFallbacks, shorthandLookups, aliasSteps },
410
460
  };
411
461
  }
@@ -8,6 +8,20 @@ const FAMILY_KEY_LENGTH = 4;
8
8
  const SEVERITY_KEY = /^DS[0-9]{2}([0-9]{2})?$/u;
9
9
  const EXEMPTION_CLASS = /^[a-z][a-z0-9-]*$/u;
10
10
  const CONTRACT_VERSION_PATTERN = /^[0-9]+\.[0-9]+\.[0-9]+$/u;
11
+ /** The members only a platform build configuration carries. */
12
+ const PLATFORM_MEMBERS = ["os", "arch", "tags"];
13
+ /** The member only a project build configuration carries. */
14
+ const PROJECT_MEMBER = "project";
15
+ /**
16
+ * One segment of a project path: not empty, not `.` or `..`, and holding no
17
+ * solidus, backslash or line break.
18
+ */
19
+ const PROJECT_SEGMENT = String.raw `(?:[^/\\.\r\n][^/\\\r\n]*|\.[^/\\.\r\n][^/\\\r\n]*|\.\.[^/\\\r\n]+)`;
20
+ /**
21
+ * A project path: segments joined by a solidus, so the path is relative, below
22
+ * the root it is read against, and spelled one way on every machine.
23
+ */
24
+ const PROJECT_PATH = new RegExp(`^${PROJECT_SEGMENT}(?:/${PROJECT_SEGMENT})*$`, "u");
11
25
  const TARGET_KINDS = ["application", "library"];
12
26
  const CONFIDENCES = ["certain", "probable", "possible"];
13
27
  const GENERATED_FILES = ["exclude", "include"];
@@ -135,10 +149,52 @@ function requireMember(value, path, label) {
135
149
  }
136
150
  return value;
137
151
  }
152
+ /** One build configuration entry as a platform: an identifier, an operating system and an architecture. */
153
+ function readPlatform(entry, at, label) {
154
+ return {
155
+ shape: "platform",
156
+ id: requireMember(readString(entry, "id", `${at}.id`, label), `${at}.id`, label),
157
+ os: requireMember(readString(entry, "os", `${at}.os`, label), `${at}.os`, label),
158
+ arch: requireMember(readString(entry, "arch", `${at}.arch`, label), `${at}.arch`, label),
159
+ tags: readStrings(entry, "tags", `${at}.tags`, label, 0) ?? [],
160
+ };
161
+ }
162
+ /** One build configuration entry as a project: an identifier and a configuration file below the target root. */
163
+ function readProject(entry, at, label) {
164
+ const id = requireMember(readString(entry, "id", `${at}.id`, label), `${at}.id`, label);
165
+ const path = `${at}.${PROJECT_MEMBER}`;
166
+ const project = requireMember(readString(entry, PROJECT_MEMBER, path, label), path, label);
167
+ if (!PROJECT_PATH.test(project)) {
168
+ throw malformed(label, path, `${JSON.stringify(project)} is not a path below the target root: segments joined by /, ` +
169
+ "none empty, . or .., and no backslash or line break");
170
+ }
171
+ return { shape: "project", id, project };
172
+ }
138
173
  /**
139
- * The build matrix: every entry names an identifier, an operating system and an
140
- * architecture.
174
+ * One build configuration entry, read as the one shape its members name: a member
175
+ * only a platform carries makes it a platform, the member only a project carries
176
+ * makes it a project, and an entry naming members of both, or of neither, is
177
+ * refused at the entry, because the two shapes are exclusive.
141
178
  */
179
+ function readConfiguration(entry, at, label) {
180
+ if (!isRecord(entry)) {
181
+ throw malformed(label, at, "is not an object");
182
+ }
183
+ const platform = PLATFORM_MEMBERS.filter((name) => Object.hasOwn(entry, name));
184
+ const project = Object.hasOwn(entry, PROJECT_MEMBER);
185
+ if (platform.length > 0 && project) {
186
+ throw malformed(label, at, `carries ${spell(platform)} of a platform and ${JSON.stringify(PROJECT_MEMBER)} of a ` +
187
+ "project, and an entry is one shape or the other");
188
+ }
189
+ if (project) {
190
+ return readProject(entry, at, label);
191
+ }
192
+ if (platform.length === 0) {
193
+ throw malformed(label, at, `names neither a platform's "os" and "arch" nor a project's ${JSON.stringify(PROJECT_MEMBER)}`);
194
+ }
195
+ return readPlatform(entry, at, label);
196
+ }
197
+ /** The build matrix, one entry in one shape at a time. */
142
198
  function readConfigurations(analysis, label) {
143
199
  const value = member(analysis, "configurations");
144
200
  if (value === undefined) {
@@ -147,18 +203,7 @@ function readConfigurations(analysis, label) {
147
203
  if (!Array.isArray(value)) {
148
204
  throw malformed(label, "analysis.configurations", "is not an array");
149
205
  }
150
- return value.map((entry, index) => {
151
- const at = `analysis.configurations[${String(index)}]`;
152
- if (!isRecord(entry)) {
153
- throw malformed(label, at, "is not an object");
154
- }
155
- return {
156
- id: requireMember(readString(entry, "id", `${at}.id`, label), `${at}.id`, label),
157
- os: requireMember(readString(entry, "os", `${at}.os`, label), `${at}.os`, label),
158
- arch: requireMember(readString(entry, "arch", `${at}.arch`, label), `${at}.arch`, label),
159
- tags: readStrings(entry, "tags", `${at}.tags`, label, 0) ?? [],
160
- };
161
- });
206
+ return value.map((entry, index) => readConfiguration(entry, `analysis.configurations[${String(index)}]`, label));
162
207
  }
163
208
  /**
164
209
  * The action delimiter pair: once a document names the object both members are
@@ -439,6 +484,29 @@ function checkLabels(provenance) {
439
484
  * the usage exit code.
440
485
  */
441
486
  export function resolve(inputs) {
487
+ const { config, provenance } = settleAll(inputs);
488
+ if (config.targetKind === "") {
489
+ throw new ConfigError("missing-target-kind", "target.kind", "target.kind is not set, it has no default and is never inferred: searched " +
490
+ `${describeSource("the repository configuration", inputs.repository, inputs.repositoryLabel)} and ` +
491
+ describeSource("the central configuration", inputs.central, inputs.centralLabel));
492
+ }
493
+ checkLabels(provenance);
494
+ return { config, provenance };
495
+ }
496
+ /**
497
+ * The build matrix the configuration documents resolve to, every document read and
498
+ * refused as {@link resolve} refuses it, and nothing else required of them: which
499
+ * projects a run analyzes depends on the matrix alone, so a question about the
500
+ * projects asks no target kind.
501
+ */
502
+ export function resolveMatrix(inputs) {
503
+ return settleAll(inputs).config.analysis.configurations;
504
+ }
505
+ /**
506
+ * Every setting the documents supply, each from the highest-ranked source carrying
507
+ * it, with the origin of each. The target kind is empty where no source names one.
508
+ */
509
+ function settleAll(inputs) {
442
510
  const sources = readSources(inputs);
443
511
  const defaults = defaultConfig();
444
512
  const provenance = new Map();
@@ -472,11 +540,5 @@ export function resolve(inputs) {
472
540
  entryFiles: at("ts.entry_files", defaults.ts.entryFiles, (doc) => doc.entryFiles),
473
541
  },
474
542
  };
475
- if (config.targetKind === "") {
476
- throw new ConfigError("missing-target-kind", "target.kind", "target.kind is not set, it has no default and is never inferred: searched " +
477
- `${describeSource("the repository configuration", inputs.repository, inputs.repositoryLabel)} and ` +
478
- describeSource("the central configuration", inputs.central, inputs.centralLabel));
479
- }
480
- checkLabels(provenance);
481
543
  return { config, provenance };
482
544
  }