Skip to content

Remove GetOptionsDiagnostics, expose global diags in LSP#2322

Closed
jakebailey wants to merge 15 commits intomainfrom
jabaile/remove-options-diags
Closed

Remove GetOptionsDiagnostics, expose global diags in LSP#2322
jakebailey wants to merge 15 commits intomainfrom
jabaile/remove-options-diags

Conversation

@jakebailey
Copy link
Copy Markdown
Member

@jakebailey jakebailey commented Dec 10, 2025

"Options diagnostics" were just config file diagnostics + global diagnostics.

This was odd, because we then took that in places and combined it with... config file diags and global diags. And then not deduping it, sometimes.

This PR just removes GetOptionsDiagnostics altogether, instead leaving behind just GetConfigFileParsingDiagnostics and GetGlobalDiagnostics.

The language server still does not ever call GetGlobalDiagnostics. I am not sure where such a thing would go, since global diagnostics are generated as a side effect of doing checking (e.g., when we figure out that AsyncIterable was never declared or something).

The language server now keeps track of global diagnostics on the fly as it creates and destroys checkers. The diags are eventually bubbled out as diags on the tsconfig.

There's a baseline change, but I think it's correct and positive.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR removes the GetOptionsDiagnostics method, which redundantly combined config file diagnostics and global diagnostics. The code now directly uses GetConfigFileParsingDiagnostics and GetGlobalDiagnostics instead, eliminating unnecessary duplication and improving diagnostic handling clarity.

Key changes:

  • Removed GetOptionsDiagnostics method and its helper from the Program struct
  • Updated diagnostic collection logic to call GetConfigFileParsingDiagnostics and GetGlobalDiagnostics directly
  • Added a safety check in GetGlobalDiagnostics to handle editor scenarios

Reviewed changes

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

File Description
testdata/baselines/reference/tsbuildWatch/configFileErrors/reports-syntax-errors-in-config-file.js Updated test baseline to reflect removal of semanticDiagnosticsPerFile field and changes to diagnostic caching behavior
testdata/baselines/reference/tsbuild/configFileErrors/reports-syntax-errors-in-config-file.js Updated test baseline with same changes as watch variant
internal/execute/incremental/program.go Removed GetOptionsDiagnostics method wrapper and its usage in error state checking
internal/compiler/program.go Removed GetOptionsDiagnostics and helper methods, added type assertion safety check, updated GetDiagnosticsOfAnyProgram to call diagnostics methods directly

@jakebailey jakebailey changed the title Remove GetOptionsDiagnostics Remove GetOptionsDiagnostics, GetGlobalDiagnostics Dec 10, 2025
@jakebailey jakebailey marked this pull request as draft December 10, 2025 19:35
@jakebailey jakebailey changed the title Remove GetOptionsDiagnostics, GetGlobalDiagnostics Remove GetOptionsDiagnostics Dec 10, 2025
@andrewbranch
Copy link
Copy Markdown
Member

global diagnostics are generated as a side effect of doing checking (e.g., when we figure out that AsyncIterable was never declared or something).

Isn't it the case that some diagnostics are generated during checker initialization due to symbol table merging? Or are those only ever duplicate declaration diagnostics, which always have a location?

It seems like maybe a distinction we should have instead of whatever mess we inherited from Strada is diagnostics that got generated during initialization, because those (whether they have a location or not) will always reliably be there regardless of what files have been checked in what order.

@jakebailey
Copy link
Copy Markdown
Member Author

Yes, there are diagnostics that are generated without a location, so can't be exposed any other way.

@andrewbranch
Copy link
Copy Markdown
Member

I know that some diagnostics are generated without a location; I'm asking whether "has a location" is orthogonal to "is dependent on what files have been checked in what order" (I think it is, at least in part)

@jakebailey
Copy link
Copy Markdown
Member Author

Ah. I think we still can report global diagnostics on things like "Iterable is missing", which only happens when you finally ask for it somewhere. Would need to recheck.

@andrewbranch
Copy link
Copy Markdown
Member

I think this change is fine as-is; I was just suggesting that it could be useful to have one bucket of diagnostics specifically from checker initialization because that would be known to be populated the exact same way no matter how many files you have or haven't checked. If that happened to include any global (location-less) diagnostics, we could reliably report them in the LSP without jumping through extra hoops. But I recognize that it wouldn't contain all the global diagnostics (and maybe in practice it wouldn't include any). The broader question of global diagnostics in the LSP will have to be figured out later—as you said, it's not new in this PR. I think Sheetal meant that it's new in Corsa, which is true I guess. I would approve this if you're ready to undraft it.

@jakebailey jakebailey marked this pull request as ready for review March 28, 2026 02:45
@jakebailey jakebailey requested a review from Copilot March 28, 2026 02:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 11 out of 11 changed files in this pull request and generated 2 comments.

Comment on lines +191 to +196
p.globalDiagCheckerCount[index] = len(globals)
before := len(p.globalDiagAccumulated)
p.globalDiagAccumulated = compiler.SortAndDeduplicateDiagnostics(append(p.globalDiagAccumulated, globals...))
if len(p.globalDiagAccumulated) != before {
p.globalDiagChanged = true
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Okay, this is my new fresh idea. The language server keeps track of global diagnostics, merging them into a big list that's kept even if checkers go away. Those get exposed as diags on the tsconfig, and it's all checked periodically.

@jakebailey jakebailey changed the title Remove GetOptionsDiagnostics Remove GetOptionsDiagnostics, expose global diags in LSP Mar 28, 2026
GetChecker(ctx context.Context) (*checker.Checker, func())
GetCheckerForFile(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func())
GetCheckerForFileExclusive(ctx context.Context, file *ast.SourceFile) (*checker.Checker, func())
GetGlobalDiagnostics() []*ast.Diagnostic
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There's technically not a great reason to bother putting this in here. In a future PR, I'm going to have to redo the way the pool works again anyway, but I can undo this specific bit and shove it back into Program as a special case.

@jakebailey
Copy link
Copy Markdown
Member Author

Probably should just take #3285

@jakebailey jakebailey marked this pull request as draft March 30, 2026 22:36
@jakebailey jakebailey closed this Mar 31, 2026
@jakebailey jakebailey deleted the jabaile/remove-options-diags branch April 8, 2026 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants