diagnostics.ts

Diagnostic collection for source analysis.

Provides structured error/warning collection during TypeScript and Svelte analysis, replacing silent catch blocks with actionable diagnostics.

Error Handling Contract

The pipeline accumulates failures into the diagnostics array and keeps going — analysis continues, declarations/members reach the output with partial: true when extraction failed mid-flight, and the caller decides how to react. Producers include type resolution failures, individual member/prop extraction failures, svelte2tsx transform failures, source-map construction failures, import lex / resolver failures, and duplicate declarations.

A small set of conditions still throws from public entry points — these are setup-level, not per-file: missing tsconfig.json (loadTsconfig), Svelte <5 detected (transformSvelteSource), or strict discovery: 'exports' mode with no resolvable exports (discoverSourceFiles). Wrap the top-level analyze / analyzeFromFiles call if you want to handle these.

Usage Pattern

const {modules, diagnostics} = await analyze({sourceFiles, sourceOptions}); if (hasErrors(diagnostics)) { for (const err of errorsOf(diagnostics)) { console.error(formatDiagnostic(err)); } } for (const warning of warningsOf(diagnostics)) { console.warn(formatDiagnostic(warning)); }

Schema-Validated Plain Data

AnalyzeResultJson.diagnostics is Array<Diagnostic> — no wrapper object, no methods, no private fields. Round-trip-safe through JSON.stringify / z.array(Diagnostic).parse and symmetric with AnalyzeResultJson.modules (also Zod-validated). The full envelope is itself a Zod schema (AnalyzeResultJson in analyze-core.ts) with both fields defaulting to [], so the whole {modules, diagnostics} shape round-trips through JSON.stringify(result, compactReplacer) / AnalyzeResultJson.parse even when one or both arrays are empty (the wire form becomes {} and .parse() restores the defaults). Use the free helpers hasErrors, errorsOf, byKind for queries; mutate the array with native Array.push.

File Path Contract

Diagnostic.file is always project-root-relative — no leading slash, no ./ prefix. analyze / analyzeFromFiles normalize paths from all sources (extraction, discovery, dependency resolution) before returning. Consumers that need an absolute path can rejoin with projectRoot.

Declarations
#

23 declarations

view source

byKind
#

diagnostics.ts view source

<K extends DiagnosticKind>(diagnostics: ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | ... 12 more ... | { ...; })[], kind: K): (Extract<...> | ... 12 more ... | Extract<...>)[]

Get diagnostics of a specific kind, narrowed to the matching variant.

diagnostics

type ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

kind

type K

returns

(Extract<{ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; }, { kind: K; }> | ... 12 more ... | Extract<...>)[]

ClassMemberDiagnostic
#

diagnostics.ts view source

ZodObject<{ className: ZodString; memberName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Class member analysis failed.

Diagnostic
#

diagnostics.ts view source

ZodDiscriminatedUnion<[ZodObject<{ symbolName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>, ... 12 more ..., ZodObject<...>], "kind">

Discriminated union of all diagnostic variants.

DiagnosticKind
#

diagnostics.ts view source

ZodEnum<{ type_extraction_failed: "type_extraction_failed"; signature_analysis_failed: "signature_analysis_failed"; class_member_failed: "class_member_failed"; svelte_prop_failed: "svelte_prop_failed"; ... 9 more ...; resolver_failed: "resolver_failed"; }>

Discriminant for Diagnostic variant types.

DiagnosticSeverity
#

diagnostics.ts view source

ZodEnum<{ error: "error"; warning: "warning"; }>

Diagnostic severity levels.

- 'error' — analysis failed, declaration may be incomplete or missing data - 'warning' — partial success, something seems off but analysis continued

DuplicateCommentDiagnostic
#

diagnostics.ts view source

ZodObject<{ commentType: ZodEnum<{ module_comment: "module_comment"; doc_comment: "doc_comment"; }>; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<...>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Duplicate comment sources detected (e.g., both HTML and JSDoc @module, or both HTML @component and JSDoc for component docComment).

DuplicateDeclarationDiagnostic
#

diagnostics.ts view source

ZodObject<{ declarationName: ZodString; modules: ZodArray<ZodString>; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<...>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

A declaration name appears in more than one module.

Library docs assume a flat namespace — two modules exporting the same name collide when consumers import {name}. Emitted at warning severity so the analysis result remains usable; consumers who want it fatal can promote via onDuplicates: 'throw' or by inspecting the diagnostic. The default slot (name === 'default') is excluded — every module owns its own.

errorsOf
#

diagnostics.ts view source

(diagnostics: ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]): ({ ...; } | ... 12 more ... | { ...; })[]

Get all error-severity diagnostics.

diagnostics

type ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

returns

({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

formatDiagnostic
#

diagnostics.ts view source

(diagnostic: { symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; }): string

Format a diagnostic for display.

Assumes diagnostic.file is project-root-relative (the contract enforced by analyze / analyzeFromFiles). The displayed path is prefixed with ./.

diagnostic

the diagnostic to format

type { symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; }

returns

string

formatted string like './file.ts:10:5: error: message'

examples

for (const d of errorsOf(diagnostics)) { console.error(formatDiagnostic(d)); }

hasErrors
#

diagnostics.ts view source

(diagnostics: ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]): boolean

Check if any error-severity diagnostics were collected.

diagnostics

type ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

returns

boolean

hasWarnings
#

diagnostics.ts view source

(diagnostics: ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]): boolean

Check if any warning-severity diagnostics were collected.

diagnostics

type ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

returns

boolean

ImportParseDiagnostic
#

diagnostics.ts view source

ZodObject<{ file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Import parsing failed during dependency resolution.

MisplacedTagDiagnostic
#

diagnostics.ts view source

ZodObject<{ tagName: ZodEnum<{ default: "default"; mutates: "mutates"; throws: "throws"; since: "since"; example: "example"; deprecated: "deprecated"; see: "see"; nodocs: "nodocs"; }>; functionName: ZodString; ... 5 more ...; kind: ZodLiteral<...>; }, $strict>

Symbol-scope JSDoc tag (@example, @deprecated, @since, @see, @throws, @mutates, @default, @nodocs) found on a non-primary overload signature.

Symbol-scope tags describe the function as a whole, not individual signatures. The primary signature's JSDoc feeds the parent declaration's symbol-level extraction; tags on non-primary overload signatures are silently dropped from output. This diagnostic surfaces them so authors can move them to the primary signature.

@default and @nodocs are included here even though overloads never carry a defaultValue or per-overload exclusion: their presence on a non-primary signature is always a misplacement.

ModuleSkippedDiagnostic
#

diagnostics.ts view source

ZodObject<{ reason: ZodEnum<{ not_in_program: "not_in_program"; no_analyzer: "no_analyzer"; requires_program: "requires_program"; }>; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<...>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Module was skipped during the analysis pass.

Always warning severity — the rest of the analysis still runs and the module's absence in modules reflects the skip. Reasons:

- not_in_program — the file wasn't in the ts.Program (race between session ingest and query, or virtual file missing for a .svelte) - no_analyzer — file extension didn't match any analyzer - requires_program — Svelte file reached the non-Svelte dispatcher (caller should use the session API instead of analyzeModule directly)

Discovery-time file-read failures are a separate kind: module_unreadable.

ModuleUnreadableDiagnostic
#

diagnostics.ts view source

ZodObject<{ file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

File discovered via package.json exports exists but couldn't be read.

Always error severity — discovery-time, emitted by discoverFromExports when readFile fails (permission denied, FS error). Distinct from module_skipped so severity is a stable per-kind property and downstream consumers can route discovery failures separately from analysis-pass skips.

ResolverFailedDiagnostic
#

diagnostics.ts view source

ZodObject<{ specifier: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Import resolver threw while resolving a specifier.

Distinguishes a buggy resolver from a legitimately unresolvable specifier: resolvers that return null for unknown specifiers stay silent (the normal "external package" case); resolvers that *throw* surface here so consumers can fix the resolver. Recoverable — the session treats the throw as null and continues, so analysis still runs but with a missing dependency edge.

Emitted at ingest time by the session's resolve phase.

SignatureAnalysisDiagnostic
#

diagnostics.ts view source

ZodObject<{ functionName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Function/method signature analysis failed.

SourceMapFailedDiagnostic
#

diagnostics.ts view source

ZodObject<{ file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Source map parsing failed for a Svelte virtual file.

Analysis continues using virtual-file positions, so downstream line/column fields on other diagnostics may point into the svelte2tsx-generated TS rather than the original .svelte source. Rare; usually signals a malformed or incompatible svelte2tsx output.

Emitted at ingest time by transformSvelteSource (in svelte.ts); flows through setFile/setFiles ingest diagnostics rather than the analysis pass.

SveltePropDiagnostic
#

diagnostics.ts view source

ZodObject<{ componentName: ZodString; propName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Svelte prop type resolution failed.

TransformFailedDiagnostic
#

diagnostics.ts view source

ZodObject<{ file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

svelte2tsx transform threw for a .svelte file.

Unrecoverable at ingest — the file's owned-entry stays in the session (virtual: undefined, unfilteredDeps: [], transformFailed: true) so query() can synthesize a placeholder ModuleJson (partial: true, empty declarations). The originating error message lives in message; this diagnostic is the authoritative cause-of-failure signal.

TypeExtractionDiagnostic
#

diagnostics.ts view source

ZodObject<{ symbolName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

Type extraction failed (e.g., complex or recursive types).

UnknownParamDiagnostic
#

diagnostics.ts view source

ZodObject<{ paramName: ZodString; functionName: ZodString; file: ZodString; line: ZodOptional<ZodNumber>; column: ZodOptional<ZodNumber>; message: ZodString; severity: ZodEnum<...>; kind: ZodLiteral<...>; }, $strict>

@param tag references a name that doesn't match any actual parameter.

Usually a typo (@param argz for parameter args) or stale doc after a rename. The description is dropped; analysis continues.

warningsOf
#

diagnostics.ts view source

(diagnostics: ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]): ({ ...; } | ... 12 more ... | { ...; })[]

Get all warning-severity diagnostics.

diagnostics

type ({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

returns

({ symbolName: string; file: string; message: string; severity: "error" | "warning"; kind: "type_extraction_failed"; line?: number | undefined; column?: number | undefined; } | { functionName: string; ... 5 more ...; column?: number | undefined; } | ... 11 more ... | { ...; })[]

Imported by
#