From 7b137bea061178d799d110ebdb501ebc9e4c81c6 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 8 Dec 2021 14:29:28 +0100 Subject: [PATCH] At least *propagate* unhandlable-binder-guard errors --- packages/compiler/src/compiler/codegen.ts | 20 +++++++++++++------- packages/syndicatec/src/cli.ts | 10 ++++++++++ packages/ts-plugin/src/index.ts | 4 ++++ packages/tsc/src/tsc.ts | 4 ++++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/packages/compiler/src/compiler/codegen.ts b/packages/compiler/src/compiler/codegen.ts index 82537fc..fc7f9d1 100644 --- a/packages/compiler/src/compiler/codegen.ts +++ b/packages/compiler/src/compiler/codegen.ts @@ -29,6 +29,8 @@ export function stripShebang(items: Items): Items { export type ModuleType ='es6' | 'require' | 'global'; +export type ErrorSink = (message: string) => void; + export interface CompileOptions { source: string, name?: string, @@ -36,6 +38,7 @@ export interface CompileOptions { module?: ModuleType, global?: string, typescript?: boolean, + emitError: ErrorSink, } export interface CompilerOutput { @@ -49,14 +52,17 @@ export class ExpansionContext { readonly parser: SyndicateParser; readonly moduleType: ModuleType; readonly typescript: boolean; + readonly emitError: (message: string) => void; nextIdNumber = 0; constructor(moduleType: ModuleType, - typescript: boolean) + typescript: boolean, + emitError: ErrorSink) { this.parser = typescript ? new SyndicateTypedParser : new SyndicateParser(); this.moduleType = moduleType; this.typescript = typescript; + this.emitError = emitError; } quasiRandomId(): string { @@ -72,7 +78,7 @@ function stringifyId(i: Identifier): Items { return [ { ... i, type: TokenType.STRING, text: JSON.stringify(i.text) } ]; } -function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) => Items { +function binderTypeGuard(ctx: ExpansionContext, t: TemplateFunction): (binder: Binder, index: number) => Items { return (binder, index) => { if (binder.id.text[0] === '_') { return t`${`/* Ignoring underscore-prefixed binder ${binder.id.text} */`}`; @@ -93,8 +99,8 @@ function binderTypeGuard(t: TemplateFunction): (binder: Binder, index: number) = case 'any': return bind; default: - // TODO: something better than this!! - throw new Error(`Unhandled binding type: ${JSON.stringify(typeText)}`); + ctx.emitError(`Cannot emit guard for binding of type: ${JSON.stringify(typeText)}`); + return bind; /* act as if "any", for now */ } } }; @@ -136,7 +142,7 @@ export function expand(tree: Items, ctx: ExpansionContext): Items { observer: __SYNDICATE__.Turn.ref(__SYNDICATE__.assertionFacetObserver( (${ctx.argDecl(t, '__vs', '__SYNDICATE__.AnyValue')}) => { if (Array.isArray(__vs)) { -${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} +${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')} ${walk(s.body)} } } @@ -202,7 +208,7 @@ ${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} const sa = compilePattern(s.pattern); const guardBody = (body: Statement) => t`if (Array.isArray(__vs)) { -${joinItems(sa.captureBinders.map(binderTypeGuard(t)), '\n')} +${joinItems(sa.captureBinders.map(binderTypeGuard(ctx, t)), '\n')} ${body} }`; @@ -281,7 +287,7 @@ export function compile(options: CompileOptions): CompilerOutput { const macro = new Templates(undefined, { extraDelimiters: ':' }); - const ctx = new ExpansionContext(moduleType, typescript); + const ctx = new ExpansionContext(moduleType, typescript, options.emitError); tree = expand(tree, ctx); diff --git a/packages/syndicatec/src/cli.ts b/packages/syndicatec/src/cli.ts index 9a02bd9..ea17ecc 100644 --- a/packages/syndicatec/src/cli.ts +++ b/packages/syndicatec/src/cli.ts @@ -117,6 +117,8 @@ export function main(argv: string[]) { argv => argv) .argv); + const collectedErrors: Array = []; + const rename = makeRenamer(options.outputDirectory ?? '', options.rootDirectory ?? '.', options.rename); @@ -144,6 +146,10 @@ export function main(argv: string[]) { runtime: options.runtime, module: options.module, typescript: options.typed, + emitError: m => { + console.error(m); + collectedErrors.push(m); + } }); map.sourcesContent = [source]; @@ -161,4 +167,8 @@ export function main(argv: string[]) { fs.writeFileSync(outputFilename, text + sourceMappingComment(dataURL(JSON.stringify(map)))); } } + + if (collectedErrors.length > 0) { + throw new Error(`Compilation failed with ${collectedErrors.length} error(s).`); + } } diff --git a/packages/ts-plugin/src/index.ts b/packages/ts-plugin/src/index.ts index 1e30192..bc35117 100644 --- a/packages/ts-plugin/src/index.ts +++ b/packages/ts-plugin/src/index.ts @@ -164,6 +164,10 @@ const boot: tslib.server.PluginModuleFactory = ({ typescript: ts }) => { source: inputText, name: fileName, typescript: true, + emitError: m => { + console.error(m); + onError?.(m); + }, }); const sf = ts.createSourceFile(fileName, expandedText, languageVersion, true); syndicateInfo.set(fileName, { diff --git a/packages/tsc/src/tsc.ts b/packages/tsc/src/tsc.ts index c93ca4c..729f17b 100644 --- a/packages/tsc/src/tsc.ts +++ b/packages/tsc/src/tsc.ts @@ -150,6 +150,10 @@ function runBuildOnce(options: CommandLineArguments, toWatch = new ToWatch()) { source: inputText, name: fileName, typescript: true, + emitError: m => { + console.error(m); + onError?.(m); + }, }); writeIntermediate(fileName, expandedText); syndicateInfo.set(fileName, {