Skip to content

Conversation

@dearfl
Copy link

@dearfl dearfl commented Oct 25, 2025

close #794

PS: I know little about LSP or this project

Copy link
Contributor

@kinto0 kinto0 left a comment

Choose a reason for hiding this comment

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

Thanks for contributing! A few tests for this behavior would make us confident it works really well.

Could you add some tests in the lsp_interaction folder where each version for a diagnostics response is correct?

Thanks!!

}
self.connection.publish_diagnostics(diags);
self.connection
.publish_diagnostics(diags, &*self.version_info.lock());
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: by aqcuiring the lock here, we won't be able to make updates to the version info. maybe we should clone it instead?

Copy link
Author

@dearfl dearfl Oct 28, 2025

Choose a reason for hiding this comment

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

cloning the hashtable might be kind of heavy too? I prefer lock. let me know if otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

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

publish_diagnostics_for_uri takes an i32 so maybe we can change the API to only call these functions with that?

Copy link
Author

@dearfl dearfl Oct 28, 2025

Choose a reason for hiding this comment

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

I'm not sure I follow you, publish_diagnostics_for_uri takes an Option<i32> as version, also the change API part.

@dearfl dearfl force-pushed the version-support-publish-diagnostics branch from 7028101 to 77eb1c0 Compare October 28, 2025 07:49
@dearfl
Copy link
Author

dearfl commented Oct 28, 2025

Thanks for contributing! A few tests for this behavior would make us confident it works really well.

Could you add some tests in the lsp_interaction folder where each version for a diagnostics response is correct?

Thanks!!

I added a small test for this, however I can't figure out why it won't work, might need a little help here. : (
It seems Server::did_change happens after Interation::Client::expect_message? I don't know why, is there a way to synchronize? Or maybe I'm using it wrong?

@dearfl dearfl force-pushed the version-support-publish-diagnostics branch 2 times, most recently from 50c3750 to 9313fb2 Compare October 28, 2025 08:26
Copy link
Contributor

@kinto0 kinto0 left a comment

Choose a reason for hiding this comment

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

could you paste the test failure? it should show the messages back/forth.

}
self.connection.publish_diagnostics(diags);
self.connection
.publish_diagnostics(diags, &*self.version_info.lock());
Copy link
Contributor

Choose a reason for hiding this comment

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

publish_diagnostics_for_uri takes an i32 so maybe we can change the API to only call these functions with that?

.client
.expect_message(lsp_server::Message::Notification(
lsp_server::Notification {
method: "textDocument/publishDiagnostics".to_owned(),
Copy link
Contributor

Choose a reason for hiding this comment

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

if we send a server.diagnostic request we should receive a document diagnostic response (maybe we also get a publishDiagnostic)

));

interaction.server.did_change("text_document.py", "# test");
interaction.server.diagnostic("text_document.py");
Copy link
Contributor

Choose a reason for hiding this comment

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

we likely can skip these diagnostic requests since the server always publishes diagnostics regardless of the client asking for them

@dearfl
Copy link
Author

dearfl commented Oct 28, 2025

could you paste the test failure? it should show the messages back/forth.

running 1 test
client--->server {"id":1,"method":"initialize","params":{"capabilities":{"textDocument":{"publishDiagnostics":{"codeDescriptionSupport":true,"dataSupport":true,"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"workspace":{"configuration":true}},"clientInfo":{"name":"debug"},"processId":64851,"rootPath":"/","trace":"verbose"}}
client<---server {"id":1,"result":{"capabilities":{"codeActionProvider":{"codeActionKinds":["quickfix"]},"completionProvider":{"triggerCharacters":["."]},"definitionProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"hoverProvider":true,"inlayHintProvider":true,"positionEncoding":"utf-16","signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":2,"typeDefinitionProvider":true,"workspace":{"fileOperations":{"willRename":{"filters":[{"pattern":{"glob":"**/*.{py,pyi}","matches":"file"},"scheme":"file"}]}},"workspaceFolders":{"changeNotifications":true,"supported":true}},"workspaceSymbolProvider":true},"serverInfo":{"name":"pyrefly-lsp","version":"pyrefly-lsp-test-version"}}}
client--->server {"method":"initialized","params":{}}
Reading messages
DEBUG Running with 3 threads (5 MiB stack size)
client<---server {"id":1,"method":"workspace/configuration","params":{"items":[{"section":"python"}]}}
client--->server {"id":1}
client--->server {"method":"textDocument/didOpen","params":{"textDocument":{"languageId":"python","text":"# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nprint(\"Did you catch the change?\")\n","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}}
client--->server {"id":2,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
DEBUG Running epoch 1 of run 0
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
Handling non-canceled request textDocument/diagnostic (2)
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}
client--->server {"method":"textDocument/didChange","params":{"contentChanges":[{"text":"# test"}],"textDocument":{"languageId":"python","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}}
client--->server {"id":3,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
DEBUG Running epoch 1 of run 1
DEBUG Committing transaction
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}

thread 'test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics' panicked at pyrefly/lib/test/lsp/lsp_interaction/object_model.rs:531:17:
assertion failed: `(left == right)`: Response mismatch

Diff < left / right > :
<{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}
>{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}


note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Connection closed.
DEBUG Running epoch 1 of run 2
test test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics ... FAILED

failures:

failures:
    test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2554 filtered out; finished in 0.21s

error: test failed, to rerun pass `-p pyrefly --lib`

@kinto0
Copy link
Contributor

kinto0 commented Oct 29, 2025

could you paste the test failure? it should show the messages back/forth.

running 1 test
client--->server {"id":1,"method":"initialize","params":{"capabilities":{"textDocument":{"publishDiagnostics":{"codeDescriptionSupport":true,"dataSupport":true,"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"workspace":{"configuration":true}},"clientInfo":{"name":"debug"},"processId":64851,"rootPath":"/","trace":"verbose"}}
client<---server {"id":1,"result":{"capabilities":{"codeActionProvider":{"codeActionKinds":["quickfix"]},"completionProvider":{"triggerCharacters":["."]},"definitionProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"hoverProvider":true,"inlayHintProvider":true,"positionEncoding":"utf-16","signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":2,"typeDefinitionProvider":true,"workspace":{"fileOperations":{"willRename":{"filters":[{"pattern":{"glob":"**/*.{py,pyi}","matches":"file"},"scheme":"file"}]}},"workspaceFolders":{"changeNotifications":true,"supported":true}},"workspaceSymbolProvider":true},"serverInfo":{"name":"pyrefly-lsp","version":"pyrefly-lsp-test-version"}}}
client--->server {"method":"initialized","params":{}}
Reading messages
DEBUG Running with 3 threads (5 MiB stack size)
client<---server {"id":1,"method":"workspace/configuration","params":{"items":[{"section":"python"}]}}
client--->server {"id":1}
client--->server {"method":"textDocument/didOpen","params":{"textDocument":{"languageId":"python","text":"# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nprint(\"Did you catch the change?\")\n","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}}
client--->server {"id":2,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
DEBUG Running epoch 1 of run 0
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
Handling non-canceled request textDocument/diagnostic (2)
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}
client--->server {"method":"textDocument/didChange","params":{"contentChanges":[{"text":"# test"}],"textDocument":{"languageId":"python","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}}
client--->server {"id":3,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
DEBUG Running epoch 1 of run 1
DEBUG Committing transaction
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}

thread 'test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics' panicked at pyrefly/lib/test/lsp/lsp_interaction/object_model.rs:531:17:
assertion failed: `(left == right)`: Response mismatch

Diff < left / right > :
<{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}
>{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}


note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Connection closed.
DEBUG Running epoch 1 of run 2
test test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics ... FAILED

failures:

failures:
    test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2554 filtered out; finished in 0.21s

error: test failed, to rerun pass `-p pyrefly --lib`

hmm that test looks like the behavior you want. like the other comments say, you're looking for the publishDiagnostic notification, not the textDocument/diagnostic response. the first one happens because of the type error then the next one happens because of the didChange. you can remove the document diagnostic requests and make a similar method to expect_publish_diagnostics_error_count but with a version attached. this'll let you test the behavior correctly!

@dearfl dearfl force-pushed the version-support-publish-diagnostics branch from f982a09 to 32c4548 Compare October 30, 2025 17:00
@dearfl
Copy link
Author

dearfl commented Oct 30, 2025

could you paste the test failure? it should show the messages back/forth.

running 1 test
client--->server {"id":1,"method":"initialize","params":{"capabilities":{"textDocument":{"publishDiagnostics":{"codeDescriptionSupport":true,"dataSupport":true,"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"workspace":{"configuration":true}},"clientInfo":{"name":"debug"},"processId":64851,"rootPath":"/","trace":"verbose"}}
client<---server {"id":1,"result":{"capabilities":{"codeActionProvider":{"codeActionKinds":["quickfix"]},"completionProvider":{"triggerCharacters":["."]},"definitionProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"hoverProvider":true,"inlayHintProvider":true,"positionEncoding":"utf-16","signatureHelpProvider":{"triggerCharacters":["(",","]},"textDocumentSync":2,"typeDefinitionProvider":true,"workspace":{"fileOperations":{"willRename":{"filters":[{"pattern":{"glob":"**/*.{py,pyi}","matches":"file"},"scheme":"file"}]}},"workspaceFolders":{"changeNotifications":true,"supported":true}},"workspaceSymbolProvider":true},"serverInfo":{"name":"pyrefly-lsp","version":"pyrefly-lsp-test-version"}}}
client--->server {"method":"initialized","params":{}}
Reading messages
DEBUG Running with 3 threads (5 MiB stack size)
client<---server {"id":1,"method":"workspace/configuration","params":{"items":[{"section":"python"}]}}
client--->server {"id":1}
client--->server {"method":"textDocument/didOpen","params":{"textDocument":{"languageId":"python","text":"# Copyright (c) Meta Platforms, Inc. and affiliates.\n#\n# This source code is licensed under the MIT license found in the\n# LICENSE file in the root directory of this source tree.\n\nprint(\"Did you catch the change?\")\n","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}}
client--->server {"id":2,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
DEBUG Running epoch 1 of run 0
 WARN While finding Python interpreter: Python environment (version, platform, or site-package-path) has value unset, but no Python interpreter could be found to query for values. Falling back to Pyrefly defaults for missing values.
Handling non-canceled request textDocument/diagnostic (2)
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}
client--->server {"method":"textDocument/didChange","params":{"contentChanges":[{"text":"# test"}],"textDocument":{"languageId":"python","uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}}
client--->server {"id":3,"method":"textDocument/diagnostic","params":{"textDocument":{"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py"}}}
DEBUG Running epoch 1 of run 1
DEBUG Committing transaction
client<---server {"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}

thread 'test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics' panicked at pyrefly/lib/test/lsp/lsp_interaction/object_model.rs:531:17:
assertion failed: `(left == right)`: Response mismatch

Diff < left / right > :
<{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":2}}
>{"method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///tmp/pyrefly_lsp_testiT0Ha4/text_document.py","version":1}}


note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Connection closed.
DEBUG Running epoch 1 of run 2
test test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics ... FAILED

failures:

failures:
    test::lsp::lsp_interaction::diagnostic::test_version_support_publish_diagnostics

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 2554 filtered out; finished in 0.21s

error: test failed, to rerun pass `-p pyrefly --lib`

hmm that test looks like the behavior you want. like the other comments say, you're looking for the publishDiagnostic notification, not the textDocument/diagnostic response. the first one happens because of the type error then the next one happens because of the didChange. you can remove the document diagnostic requests and make a similar method to expect_publish_diagnostics_error_count but with a version attached. this'll let you test the behavior correctly!

Now the test always fails with Timeout error, idk why.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Version Support to textDocument/publishDiagnostics

3 participants