Skip to content

Port formatDiagnostics and formatDiagnosticsWithColorAndContext - #63935

Open
John Favret (johnfav03) wants to merge 7 commits into
microsoft:mainfrom
johnfav03:johnfav03/investigate-4830-format-diagnostics
Open

Port formatDiagnostics and formatDiagnosticsWithColorAndContext#63935
John Favret (johnfav03) wants to merge 7 commits into
microsoft:mainfrom
johnfav03:johnfav03/investigate-4830-format-diagnostics

Conversation

@johnfav03

Copy link
Copy Markdown
Contributor

In the TS API, these are exposed on Program as:

  • formatDiagnostics(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost)
  • formatDiagnosticsWithColorAndContext(diagnostics: readonly Diagnostic[], host: FormatDiagnosticsHost)

Part of #63875 (3D)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5d2afb8f-0680-4d91-9a76-9c08a760ce24
Copilot AI balanced review requested due to automatic review settings August 20, 2026 21:53
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Aug 20, 2026
@typescript-automation typescript-automation Bot added For Uncommitted Bug PR for untriaged, rejected, closed or missing bug labels Aug 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Program diagnostic-formatting APIs for roadmap item #63875 (3D), backed by snapshot-aware server formatting.

Changes:

  • Adds sync/async formatting APIs, protocol methods, and host path handling.
  • Resolves source/config context and tracks diagnostic origins.
  • Adds API tests and updates diagnostic baselines.

Reviewed changes

Copilot reviewed 159 out of 159 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tsc/internal/api/format_diagnostics.go Implements server-side formatting and file resolution.
tsc/internal/api/session.go Dispatches formatting requests.
tsc/internal/api/proto.go Defines formatting protocol data.
tsc/internal/api/session_format_diagnostics_test.go Tests server formatting behavior.
tsc/internal/diagnosticwriter/diagnosticwriter.go Refactors shared diagnostic rendering.
packages/typescript/src/api/sync/api.ts Exposes synchronous formatting methods.
packages/typescript/src/api/async/api.ts Exposes asynchronous formatting methods.
packages/typescript/src/api/sync/types.ts Adds the synchronous formatting host type.
packages/typescript/src/api/async/types.ts Adds the asynchronous formatting host type.
packages/typescript/src/api/path.ts Adds host-relative path conversion.
packages/typescript/src/api/proto.generated.ts Adds generated protocol declarations.
packages/typescript/test/sync/api.test.ts Tests the synchronous API.
packages/typescript/test/async/api.test.ts Tests the asynchronous API.
tsc/testdata/submoduleAccepted.txt Updates accepted baseline differences.
tsc/testdata/baselines/reference/compiler/** Updates compiler diagnostic formatting baselines.
tsc/testdata/baselines/reference/config/** Updates configuration diagnostic baselines.
tsc/testdata/baselines/reference/tsc/** Updates command-line compiler baselines.
tsc/testdata/baselines/reference/tscWatch/** Updates watch-mode baselines.
tsc/testdata/baselines/reference/tsbuild/** Updates solution-build baselines.
tsc/testdata/baselines/reference/tsbuildWatch/** Updates watched solution-build baselines.

Comment thread tsc/internal/diagnosticwriter/diagnosticwriter.go Outdated
@johnfav03
John Favret (johnfav03) requested a balanced review from Copilot August 20, 2026 22:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

tsc/internal/api/proto.go:1446

  • These transport-only fields become part of the public Diagnostic API because DiagnosticResponse is re-exported as Diagnostic in packages/typescript/src/api/proto.ts:14. That exposes originSnapshot, originProject, and displayFileName even though origin is intentionally tracked with a private symbol and these values are absent from returned diagnostics; consumers can therefore see and set misleading implementation fields that do not satisfy the formatter's provenance check. Please use a separate formatting-request wire type (or otherwise exclude these fields from the public Diagnostic type).
	// OriginSnapshot and OriginProject identify the program that produced this diagnostic.
	OriginSnapshot SnapshotID `json:"originSnapshot,omitzero"`
	OriginProject  ProjectID  `json:"originProject,omitzero"`
	// DisplayFileName is the host-formatted file name used only for diagnostic output.
	DisplayFileName string `json:"displayFileName,omitempty"`

@andrewbranch

Copy link
Copy Markdown
Member

Hm, I think we can have a slightly simpler way of determining whether a diagnostic is valid to be printed in the context of a file from a given snapshot/project. Instead of associating a specific snapshot/project after the fact, what if we just included the source file's hash on diagnostic responses that include a file? Then, the server could validate during printing that the file it looked up matches the hash.

The one caveat is that I think the methods that return tsconfig source files don't initialize hash for those files; that will need to be added on in the server since diagnostics can be reported on config files.

The other one I'm not sure about is diagnostics that are mapped through declaration maps (i.e. the program loaded a referenced project's .d.ts file, but the diagnostic location was changed to the .ts file via a .d.ts.map). I think that's a thing? Just taking the hash of the declaration file should be fine, we just need to make sure that all works round-trip. Probably a good test to have for this functionality even with the current association approach.

@gabritto

Copy link
Copy Markdown
Member

The details of this were only clear to me recently, so apologies for the late feedback, but today you can get DiagnosticResponses via parseConfigFile, which means we don't necessarily have a snapshot with the file version that produced the diagnostics, and I think we should also have some mechanism to make this case work, too (it's what I need for createProgram, but also users will possibly want this).

@andrewbranch

Copy link
Copy Markdown
Member

Good point, I think my suggestion to use file hashes would handle that case.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Comment thread tsc/internal/api/format_diagnostics.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

api/format_diagnostics.go is surprisingly complex which I think indicates that something is wrong here.

I actually think formatDiagnostic should just be ported to JS, not require a server call at all. It's very few lines of code in total in Strada. And it definitely shouldn't require a full SourceFile to work. Instead of jumping through all these hoops to get back to a SourceFile, we should just be lifting the properties needed for diagnostic formatting onto the API's DiagnosticResponse type at the moment it's created, while we still have a SourceFile on hand in the server. It looks like this is having to do so much work in order to convert pos and end from offsets to line/character pairs. Let's just include the pos/end in both formats on DiagnosticResponse, and then we don't have to make a server round trip just to get the line map.

Comment thread packages/typescript/src/api/async/api.ts Outdated
@github-project-automation github-project-automation Bot moved this from Not started to Waiting on author in PR Backlog Aug 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Comment on lines +176 to +193
if (diagnostic.fileName && diagnostic.code !== fileAppearsToBeBinaryCode) {
output += host.getNewLine();
output += formatCodeSpan(diagnostic, "", getCategoryFormat(diagnostic.category), host);
}

if (diagnostic.relatedInformation?.length) {
output += host.getNewLine();
for (const related of diagnostic.relatedInformation) {
if (related.fileName && related.startPosition) {
output += host.getNewLine();
output += halfIndent + formatLocation(related, host);
output += formatCodeSpan(related, indent, foregroundColorEscapeCyan, host);
}
output += host.getNewLine();
output += indent + flattenDiagnosticMessage(related, host.getNewLine());
}
}
output += host.getNewLine();
Comment thread tsc/internal/api/proto.go
Comment on lines +1510 to +1511
resp.Pos = int(core.UTF16Len(file.Text()[:pos]))
resp.End = int(core.UTF16Len(file.Text()[:end]))
Comment on lines +129 to +133
const lastCharacter = sourceLine.line === endPosition.line
? endPosition.character
: lineContent.length;
context += " ".repeat(startPosition.character);
context += "~".repeat(Math.max(0, lastCharacter - startPosition.character));
host: FormatDiagnosticsHost,
): string {
let output = "";
for (const diagnostic of diagnostics) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Waiting on author

Development

Successfully merging this pull request may close these issues.

4 participants