aontu 0.67.0 → 0.68.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/src/vet.ts CHANGED
@@ -280,14 +280,14 @@ function orderKey(f: VetFinding, index: number): string {
280
280
  export function engineFinding(
281
281
  nil: any, ctx: any, path: string): VetFinding {
282
282
  if (null == nil) {
283
- return {
283
+ return fromRegistry({
284
284
  code: UNSHAPED,
285
285
  class: codeClass(UNSHAPED),
286
286
  severity: 'error',
287
287
  path,
288
288
  message: 'The document does not evaluate.',
289
289
  sites: [],
290
- }
290
+ }, { why: UNSHAPED })
291
291
  }
292
292
 
293
293
  materialise(nil, ctx)
@@ -423,14 +423,62 @@ function coverDataPaths(
423
423
  }
424
424
 
425
425
 
426
+ // A spread or a key can carry a shape-preserving call or a reference,
427
+ // and coverage wants the bag under it; the seen set settles a cycle.
428
+ export function coverThrough(v: any, root: any): any {
429
+ let at = v
430
+ const seen = new Set<any>()
431
+ while (null != at && !seen.has(at)) {
432
+ if (true === at.isMap || true === at.isList) {
433
+ return at
434
+ }
435
+ seen.add(at)
436
+ if ((true === at.isCloseFunc || true === at.isTypeFunc) &&
437
+ Array.isArray(at.peg)) {
438
+ at = at.peg[0]
439
+ continue
440
+ }
441
+ // A relative reference reads from where it was WRITTEN, not where
442
+ // the template lands, so the engine's own resolution is the rule.
443
+ if (true === at.isRef) {
444
+ at = coverRefTarget(root, at.plainRefPath())
445
+ continue
446
+ }
447
+ if (true === at.isRecurse) {
448
+ at = coverRefTarget(root, at.target)
449
+ continue
450
+ }
451
+ return undefined
452
+ }
453
+ return undefined
454
+ }
455
+
456
+
457
+ // A reference descends a list by the segment AS WRITTEN: `$.Defs.0`.
458
+ function coverRefTarget(root: any, segs: string[] | undefined): any {
459
+ if (null == segs) {
460
+ return undefined
461
+ }
462
+ let at = root
463
+ for (const seg of segs) {
464
+ at = true === at?.isMap || true === at?.isList ? at.peg?.[seg] : undefined
465
+ }
466
+ return at
467
+ }
468
+
469
+
426
470
  // Walk one data path down the schema, naming the declaration that
427
471
  // constrains it -- the exact key where the schema has one, else the
428
472
  // covering template. Undefined when the schema declares nothing there.
429
473
  function coverMatch(
430
- anchor: any, segs: string[]): string | undefined {
474
+ anchor: any, segs: string[], root: any): string | undefined {
431
475
  let at: any = anchor
432
476
  let decl = ''
433
477
  for (const seg of segs) {
478
+ at = coverThrough(at, root)
479
+ if (null == at) {
480
+ return undefined
481
+ }
434
482
  const named = true === at.isMap && null != at.peg ? at.peg[seg]
435
483
  : true === at.isList && Array.isArray(at.peg) ? at.peg[Number(seg)]
436
484
  : undefined
@@ -470,7 +518,8 @@ function coverShallowest(paths: string[]): string[] {
470
518
  // The accounting itself: what the schema declared, what the data holds,
471
519
  // and which of each the other met.
472
520
  export function vetCoverage(
473
- anchor: any, dataVal: any, coverageAt?: string): VetCoverage {
521
+ anchor: any, dataVal: any, coverageAt: string | undefined,
522
+ root: any): VetCoverage {
474
523
  const declarations = new Map<string, any>()
475
524
  coverDeclare(anchor, [], declarations)
476
525
 
@@ -499,7 +548,7 @@ export function vetCoverage(
499
548
  continue
500
549
  }
501
550
  const segs = path.replace(/^\$\.?/, '').split('.').filter((x) => '' !== x)
502
- const decl = coverMatch(anchor, segs)
551
+ const decl = coverMatch(anchor, segs, root)
503
552
  if (leaf) {
504
553
  leaves++
505
554
  }
@@ -617,7 +666,7 @@ export function vet(
617
666
  // the same paths minus whatever an include would have added.
618
667
  const measured = 0 === coverCtx.err.length && true !== settledData?.isNil
619
668
  ? settledData : dataVal
620
- coverage = vetCoverage(anchor, measured, options.coverageAt)
669
+ coverage = vetCoverage(anchor, measured, options.coverageAt, schemaVal)
621
670
  }
622
671
 
623
672
  const lintFindings: VetFinding[] = []