perf(typert): skip re-verified diagnostics and share analyzer caches in the tsdown plugin

This commit is contained in:
imccyu
2026-08-26 12:35:04 +08:00
parent 75428c7f47
commit 54ef0f315a
2 changed files with 31 additions and 4 deletions
@@ -22,6 +22,11 @@ interface TypertPlugin {
const DECORATOR_SYNTAX = /^\s*@[A-Za-z_$][\w$]*/m
// This plugin consumes tsc-emitted `lib/types` output, so every project it
// would re-diagnose has already passed the workspace tsc build in the same
// orchestration; the generator skips its per-package diagnostic pass here.
const TSC_VERIFIED_INPUT = { checkDiagnostics: false } as const
/** Generation scope selected by a tsdown build phase. */
export interface TypertPluginOptions {
/** Package mode emits only the package being bundled; workspace mode emits every explicit contributor once. */
@@ -78,7 +83,7 @@ export function typertPlugin(pluginOptions: TypertPluginOptions = {}): TypertPlu
if (manifest.name === undefined || !hasTypertExport(manifest.exports)) return
let artifacts = artifactsByRoot.get(root)
if (artifacts === undefined) {
const generator = new WorkspaceTypertGenerator(root)
const generator = new WorkspaceTypertGenerator(root, TSC_VERIFIED_INPUT)
artifacts = pluginOptions.faces === undefined
? generator.generate()
: generator.generate(undefined, pluginOptions.faces)
@@ -89,7 +94,7 @@ export function typertPlugin(pluginOptions: TypertPluginOptions = {}): TypertPlu
}
function emitWorkspace(root: string, faces: readonly TypertFace[] | undefined): void {
const generator = new WorkspaceTypertGenerator(root)
const generator = new WorkspaceTypertGenerator(root, TSC_VERIFIED_INPUT)
const packages = generator.discover(faces)
.filter(candidate => hasTypertExport(readManifest(join(root, candidate.root)).exports))
.map(candidate => candidate.package)
+24 -2
View File
@@ -5,7 +5,7 @@
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { TypertAnalysisError, WorkspaceAnalyzer } from './analyzer.ts'
import { TypertAnalysisError, WorkspaceAnalyzer, WorkspaceCaches } from './analyzer.ts'
import type { DiscoveredTypertPackage } from './analyzer.ts'
import { FaceModelEmitter } from './emitter.ts'
import type { ModelEmitResult } from './emitter.ts'
@@ -16,13 +16,32 @@ export interface WorkspaceEmitResult extends ModelEmitResult {
readonly packageRoot: string
}
/** Behavior switches for one {@link WorkspaceTypertGenerator}. */
export interface WorkspaceTypertGeneratorOptions {
/**
* Run the per-package syntactic/semantic diagnostic pass before analysis
* (default true). Pass false only when the same orchestration already
* verified the workspace with tsc; the Typert-specific analysis checks
* (annotation coverage, private cross-package references, unretainable
* merges) run regardless.
*/
readonly checkDiagnostics?: boolean
}
/** Discover, analyze, and emit package reflection from independent faces. */
export class WorkspaceTypertGenerator {
/** Parsed-config and program-host state shared by every analyzer this generator creates. */
private readonly caches = new WorkspaceCaches()
/**
* Bind generation to one workspace root.
* @param root - directory containing face aggregate tsconfigs.
* @param options - behavior switches applied to every pass of this generator.
*/
constructor(private readonly root: string) {}
constructor(
private readonly root: string,
private readonly options: WorkspaceTypertGeneratorOptions = {},
) {}
/**
* Find public package faces that contribute Cordis services/events or
@@ -33,6 +52,7 @@ export class WorkspaceTypertGenerator {
discover(faces?: readonly TypertFace[]): DiscoveredTypertPackage[] {
return new WorkspaceAnalyzer({
root: this.root,
caches: this.caches,
...(faces === undefined ? {} : { faces }),
}).discoverPackages()
}
@@ -48,7 +68,9 @@ export class WorkspaceTypertGenerator {
const workspace = new WorkspaceAnalyzer({
root: this.root,
packages: selected,
caches: this.caches,
...(faces === undefined ? {} : { faces }),
...(this.options.checkDiagnostics === undefined ? {} : { checkDiagnostics: this.options.checkDiagnostics }),
}).analyze()
const artifacts: WorkspaceEmitResult[] = []
for (const face of workspace.faces) {