-
Notifications
You must be signed in to change notification settings - Fork 334
Export diagnostic-collecting API for downstream emitter composition #9416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
|
|
||
| if (root) { | ||
| root = options["update-code-model"](root, sdkContext); | ||
| const updatedRoot = options["update-code-model"](root, sdkContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot could we remove this callback from the options, and put that as a parameter of this method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! The update-code-model callback is now a parameter of createCodeModel() instead of being in options. This makes the API more explicit and allows downstream emitters to pass their own callback without modifying options. The option still exists for backward compatibility with $onEmit(). (commit feb41b6)
…odel parameter Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
| reportDiagnostic<C extends keyof DiagnosticMessagesMap, M extends keyof DiagnosticMessagesMap[C]>( | ||
| diag: DiagnosticReport<DiagnosticMessagesMap, C, M>, | ||
| ): void { | ||
| libReportDiagnostic(this.program, diag); | ||
| if (this.collectedDiagnostics) { | ||
| // In collecting mode, store the diagnostic instead of reporting it | ||
| this.collectedDiagnostics.push(createDiagnostic(diag)); | ||
| } else { | ||
| // In normal mode, report the diagnostic directly | ||
| libReportDiagnostic(this.program, diag); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should remove this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Removed the reportDiagnostic method (along with warn and error) from Logger class. Functions now create diagnostics using createDiagnostic() and add them directly to sdkContext.__diagnostics array, which is returned by createModel(). This follows the [Result, readonly Diagnostic[]] pattern throughout the codebase. (commit 750acf0)
ArcturusZhang
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot we need to remove the method reportDiagnostic in Logger.
for those places that were previously calling this function, we need to change that method to use the same pattern to return [Result, readonly Diagnostic[]] instead.
I understand you want to remove |
…tern - Removed reportDiagnostic, warn, and error methods from Logger class - Added __diagnostics array to CSharpEmitterContext for collecting diagnostics - Updated all code to use createDiagnostic and push to sdkContext.__diagnostics - Updated createModel to return diagnostics from __diagnostics instead of logger - Updated all tests to report returned diagnostics to program for assertions - Simplified Logger to only handle tracing, removed diagnostic collection mode Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
|
@copilot I saw you added a diagnostic field in the context, but this is not quite following the best practice. at the beginning, and use its apis to wrap normal results without diagnostics, or add diagnostics into the result. |
- Replaced __diagnostics array with DiagnosticCollector from TypeSpec - Updated createModel to use diagnostics.wrap() for returning tuple - Functions now access diagnostics via sdkContext.__diagnostics.add() - Updated tests to set up diagnostic collector when needed - Follows the pattern from TCGC: createDiagnosticCollector at top level Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
Refactored to use |
Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
|
@copilot I think you misunderstood the pattern. If a method would be called here and it returns a diagnostic and something else, and we need this "something", we should do it in this way: This pattern is kind of contagious, if one method is returning the diagnostics, its caller must also return the diagnostics in its signature. |
…lection pattern Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
Co-authored-by: ArcturusZhang <10554446+ArcturusZhang@users.noreply.github.com>
You're correct - I've now refactored to follow the proper pattern. Each function that returns diagnostics creates its own |
The emitter was directly reporting diagnostics to the program, preventing downstream emitters from collecting and handling diagnostics according to TypeSpec best practices (
[Result, readonly Diagnostic[]]pattern).Changes
createModel()- Now returns[CodeModel, readonly Diagnostic[]]usingcreateDiagnosticCollector()anddiagnostics.wrap()createCodeModel()- New exported function wrapping emission logic, returns[void, readonly Diagnostic[]]updateCodeModelparameter - Refactored from options to explicit parameter ofcreateCodeModel()for better API discoverabilityreportDiagnostic(),warn(), anderror()methods; Logger now only handles tracingcreateDiagnosticCollector(). Internal helper functions acceptDiagnosticCollectoras a parameter. Callers usediagnostics.pipe()to unwrap tuple-returning functions._validateDotNetSdk()- Now returns[boolean, readonly Diagnostic[]]with its own diagnostic collector$onEmit()- Refactored to callcreateCodeModel()and report collected diagnosticsAll code that previously called
logger.reportDiagnostic()now usescreateDiagnostic()and adds diagnostics viaDiagnosticCollectorparameters. This implements the[Result, readonly Diagnostic[]]pattern consistently throughout the codebase, following the "contagious" pattern where functions that call diagnostic-returning functions must also return diagnostics.The implementation follows TypeSpec best practices exactly as demonstrated in TCGC:
[Result, readonly Diagnostic[]]create their own collector at the beginningDiagnosticCollectoras a parameter and add diagnostics to itdiagnostics.pipe(func())to unwrap results and aggregate diagnosticsdiagnostics.wrap(result)at the endOver 40 functions were updated across 8 files to properly handle diagnostic collection: type-converter.ts, service-authentication.ts, client-converter.ts, operation-converter.ts, namespace-converter.ts, emitter.ts, code-model-writer.ts, and example-converter.ts.
Usage
Each function creates its own diagnostic collector and returns tuples following the TypeSpec pattern, enabling proper diagnostic composition for downstream emitters.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.