Skip to content

[ty] Configure check mode for all projects#23121

Merged
BurntSushi merged 1 commit intomainfrom
ag/fix-check-mode
Feb 9, 2026
Merged

[ty] Configure check mode for all projects#23121
BurntSushi merged 1 commit intomainfrom
ag/fix-check-mode

Conversation

@BurntSushi
Copy link
Member

@BurntSushi BurntSushi commented Feb 6, 2026

Previously, we were only setting the check mode on a project if the
diagnostic mode was workspace. While the diagnostic mode defaults to
OpenFilesOnly, the check mode on a ty project defaults to AllFiles
(i.e., workspace).

The result is that projects were always configured in AllFiles check
mode, making it impossible to set the check mode to OpenFilesOnly.
Confusingly, this is distinct from the global settings diagnostic
mode, which could actually be different thant he check mode on the
individual projects!

This did cause one test failure: an end-to-end test checking that
changing the language of a file resulted in the LSP picking up that
change. e.g., Going from Python to non-Python should result in no
diagnostics. This was added in #21867, but I believe the change was
incomplete: when a didOpen notification is received, we were
unconditionally adding the file to the project state without checking
its extension. The test still "worked" precisely because of the
AllFiles vs OpenFilesOnly confusion. That is, the server defaulted
to OpenFilesOnly, but the project defaulted to AllFiles. This in
turn made it so the file was an "open file" and not actually picked up
from a directory scan. That in turn led to should_check_file returning
false, since the AllFiles mode explicitly ignores "open files."

Ref astral-sh/ty#2616

@BurntSushi BurntSushi requested review from dhruvmanila and removed request for Gankra, MichaReiser, carljm, dcreager and sharkdp February 6, 2026 13:26
@ntBre ntBre added the ty Multi-file analysis & type inference label Feb 6, 2026
@BurntSushi BurntSushi added the server Related to the LSP server label Feb 6, 2026
@BurntSushi
Copy link
Member Author

The test failure is real here I think. It was previously not setting the diagnostic mode, which in turn defaulted to Workspace. Now it defaults to OpenFilesOnly and this causes diagnostics to be reported for a file whose type got changed. That's problem number 1. Problem number 2 is that if I set its diagnostic mode explicitly to Workspace, then the test fails, but because it never gets a publishDiagnostic response. So there is actually something different between explicitly setting the diagnostic mode to Workspace and letting it use defaults. That's what I'm investigating now.

Previously, we were only setting the check mode on a project if the
diagnostic mode was `workspace`. While the diagnostic mode defaults to
`OpenFilesOnly`, the _check mode_ on a ty project defaults to `AllFiles`
(i.e., workspace).

The result is that projects were always configured in `AllFiles` check
mode, making it impossible to set the check mode to `OpenFilesOnly`.
Confusingly, this is _distinct_ from the global settings diagnostic
mode, which could actually be different thant he check mode on the
individual projects!

This did cause one test failure: an end-to-end test checking that
changing the language of a file resulted in the LSP picking up that
change. e.g., Going from Python to non-Python should result in no
diagnostics. This was added in #21867, but I believe the change was
incomplete: when a `didOpen` notification is received, we were
unconditionally adding the file to the project state without checking
its extension. The test still "worked" precisely because of the
`AllFiles` vs `OpenFilesOnly` confusion. That is, the server defaulted
to `OpenFilesOnly`, but the project defaulted to `AllFiles`. This in
turn made it so the file was an "open file" and not actually picked up
from a directory scan. That in turn led to `should_check_file` returning
false, since the `AllFiles` mode explicitly ignores "open files."

Ref astral-sh/ty#2616
};
server.send_notification::<DidOpenTextDocument>(params);
let _close_diagnostics = server.await_notification::<PublishDiagnostics>();

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure if it was intentional to have the diagnostics send back twice, but this is no longer the case. It was happening previously because:

  1. Closing the document (above) would result in clearing diagnostics only when DocumentHandle::close returns true. And that would return true because session.global_settings().diagnostic_mode().is_open_files_only() returned true. Because the session global settings used OpenFilesOnly by default.
  2. Re-opening the document (with the language ID changed) caused publish_diagnostics_if_needed inside of the DidOpenTextDocumentHandler handler to run. This would eventually do Project::check_file and that would call should_check_file. And that would return false because the projects have been defaulting to AllFiles as a check mode by default, and the file in question is only in the "open file" set. (Which is perhaps a bug on its own, but I digress.)

The end result is that the test got no diagnostics which was what was expected, but it got for a reason other than respecting the change in language ID. Once I fixed the AllFiles/OpenFilesOnly problem, this test started failing because we would still send back diagnostics for the plain text file.

I ended up fixing this by checking the language ID of the file in the DidOpenTextDocumentHandler handler. If it's Other, then we ignore it, hopefully mirroring what we do in ty_project/src/walk.rs.

Copy link
Member

@dhruvmanila dhruvmanila left a comment

Choose a reason for hiding this comment

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

Uff, this seemed like very confusing to debug, thanks for tracking this down!

Comment on lines -33 to +39
let document = session.open_text_document(
TextDocument::new(uri, text, version).with_language_id(&language_id),
);
let text_doc = TextDocument::new(uri, text, version).with_language_id(&language_id);
if matches!(text_doc.language_id(), Some(LanguageId::Other)) {
return Ok(());
}

let document = session.open_text_document(text_doc);
Copy link
Member

Choose a reason for hiding this comment

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

I think this sounds correct but it would be useful to have a E2E test case for this scenario if it doesn't already exists. What do you think?

Copy link
Member Author

@BurntSushi BurntSushi Feb 9, 2026

Choose a reason for hiding this comment

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

I think this is what the changing_language_of_file_without_extension test covers. That the test was previously passing was a mirage. :-) Once I untangled the AllFiles/OpenFilesOnly stuff, it started failing. Adding this was required to make it pass because otherwise we treat the open file as Python code.

@BurntSushi BurntSushi merged commit 49a25f2 into main Feb 9, 2026
46 checks passed
@BurntSushi BurntSushi deleted the ag/fix-check-mode branch February 9, 2026 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

server Related to the LSP server ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants