From bc422593e8da602cb946c9b877c775314eff7050 Mon Sep 17 00:00:00 2001 From: Will Ockelmann-Wagner Date: Wed, 30 Oct 2024 11:38:55 -0700 Subject: [PATCH 1/3] print diagnostics when a protoplugin fails to emit files. --- packages/protoplugin/src/transpile.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/protoplugin/src/transpile.ts b/packages/protoplugin/src/transpile.ts index cb7e49092..a1e0df4b4 100644 --- a/packages/protoplugin/src/transpile.ts +++ b/packages/protoplugin/src/transpile.ts @@ -158,8 +158,14 @@ export function transpile( throw err; } if (result.emitSkipped) { + const fileNames = files.map((f) => f.name).join("\n"); + const diagnosticMessages = result.diagnostics + .map((d) => d.messageText) + .join("\n"); + + // When compilation fails, this error will be shown in the results of the NPM install error log. throw Error( - "A problem occurred during transpilation and files were not generated. Contact the plugin author for support.", + `A problem occurred during transpilation and files were not generated. Contact the plugin author for support.\n\nGenerating Files:\n\n${fileNames}\n\nDiagnostics:\n\n${diagnosticMessages}` ); } return results; From 9e0abff35b8d0b4d4c0358540b35ddfc810a85d0 Mon Sep 17 00:00:00 2001 From: Timo Stamm Date: Thu, 31 Oct 2024 10:29:55 +0100 Subject: [PATCH 2/3] npx turbo run format --- packages/protoplugin/src/transpile.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/protoplugin/src/transpile.ts b/packages/protoplugin/src/transpile.ts index a1e0df4b4..ab6351fa8 100644 --- a/packages/protoplugin/src/transpile.ts +++ b/packages/protoplugin/src/transpile.ts @@ -165,7 +165,7 @@ export function transpile( // When compilation fails, this error will be shown in the results of the NPM install error log. throw Error( - `A problem occurred during transpilation and files were not generated. Contact the plugin author for support.\n\nGenerating Files:\n\n${fileNames}\n\nDiagnostics:\n\n${diagnosticMessages}` + `A problem occurred during transpilation and files were not generated. Contact the plugin author for support.\n\nGenerating Files:\n\n${fileNames}\n\nDiagnostics:\n\n${diagnosticMessages}`, ); } return results; From 7e1786052e3c40abca431d23ca7f0b498d7c78bf Mon Sep 17 00:00:00 2001 From: Timo Stamm Date: Thu, 31 Oct 2024 10:49:26 +0100 Subject: [PATCH 3/3] Format diagnostics with the compiler's tools; limit to 3 diagnostics; add tests --- ...transpile.test.ts.ts => transpile.test.ts} | 62 +++++++++++++++++++ packages/protoplugin/src/transpile.ts | 34 +++++++--- 2 files changed, 89 insertions(+), 7 deletions(-) rename packages/protoplugin-test/src/{transpile.test.ts.ts => transpile.test.ts} (64%) diff --git a/packages/protoplugin-test/src/transpile.test.ts.ts b/packages/protoplugin-test/src/transpile.test.ts similarity index 64% rename from packages/protoplugin-test/src/transpile.test.ts.ts rename to packages/protoplugin-test/src/transpile.test.ts index b0048d718..0e7bfd7f4 100644 --- a/packages/protoplugin-test/src/transpile.test.ts.ts +++ b/packages/protoplugin-test/src/transpile.test.ts @@ -97,4 +97,66 @@ describe("built-in transpile", () => { ]); }); }); + + describe("failing to emit", () => { + test("raises error with helpful message", async () => { + await expect(async () => + testTranspileToDts([ + `export interface Foo {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + ]), + ).rejects.toThrow( + /^A problem occurred during transpilation and files were not generated\. {2}Contact the plugin author for support\.\n/, + ); + }); + test("raises error with diagnostics", async () => { + await expect(async () => + testTranspileToDts([ + `export interface Foo {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + ]), + ).rejects.toThrow( + /test\.ts\(3,17\): error TS4033: Property 'p' of exported interface has or is using private name 'P'\.$/, + ); + }); + test("raises error with 3 diagnostics, and elides the rest", async () => { + await expect(async () => + testTranspileToDts([ + `export interface Foo1 {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + `export interface Foo2 {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + `export interface Foo3 {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + `export interface Foo4 {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + `export interface Foo5 {`, + ` p: {`, + ` [K in keyof P]: string;`, + ` },`, + `}`, + ]), + ).rejects.toThrow( + /(?:test\.ts\(\d+,\d+\): .+\n){3}2 more diagnostics elided/, + ); + }); + }); }); diff --git a/packages/protoplugin/src/transpile.ts b/packages/protoplugin/src/transpile.ts index ab6351fa8..9b5c936cb 100644 --- a/packages/protoplugin/src/transpile.ts +++ b/packages/protoplugin/src/transpile.ts @@ -158,15 +158,35 @@ export function transpile( throw err; } if (result.emitSkipped) { - const fileNames = files.map((f) => f.name).join("\n"); - const diagnosticMessages = result.diagnostics - .map((d) => d.messageText) - .join("\n"); - - // When compilation fails, this error will be shown in the results of the NPM install error log. + // When compilation fails, this error message is printed to stderr. + const diagnostics = formatDiagnostics(result.diagnostics); throw Error( - `A problem occurred during transpilation and files were not generated. Contact the plugin author for support.\n\nGenerating Files:\n\n${fileNames}\n\nDiagnostics:\n\n${diagnosticMessages}`, + `A problem occurred during transpilation and files were not generated. Contact the plugin author for support.\n\n${diagnostics}`, ); } return results; } + +function formatDiagnostics(diagnostics: readonly ts.Diagnostic[]): string { + const sorted = ts.sortAndDeduplicateDiagnostics(diagnostics); + if (sorted.length == 0) { + return ""; + } + const first = sorted.slice(0, 3); + const formatHost: ts.FormatDiagnosticsHost = { + getCanonicalFileName(fileName: string): string { + return fileName; + }, + getCurrentDirectory(): string { + return "."; + }, + getNewLine(): string { + return "\n"; + }, + }; + let out = ts.formatDiagnostics(first, formatHost).trim(); + if (first.length < sorted.length) { + out += `\n${sorted.length - first.length} more diagnostics elided`; + } + return out; +}