Ignore source code actions for a notebook cell (#16154)

## Summary

Related to https://github.com/astral-sh/ruff-vscode/pull/686, this PR
ignores handling source code actions for notebooks which are not
prefixed with `notebook`.

The main motivation is that the native server does not actually handle
it well which results in gibberish code. There's some context about this
in
https://github.com/astral-sh/ruff-vscode/issues/680#issuecomment-2647490812
and the following comments.

closes: https://github.com/astral-sh/ruff-vscode/issues/680

## Test Plan

Running a notebook with the following does nothing except log the
message:
```json
  "notebook.codeActionsOnSave": {
    "source.organizeImports.ruff": "explicit",
  },
```

while, including the `notebook` code actions does make the edit (as
usual):
```json
  "notebook.codeActionsOnSave": {
    "notebook.source.organizeImports.ruff": "explicit"
  },
```
This commit is contained in:
Dhruv Manilawala 2025-02-18 10:28:03 +05:30 committed by GitHub
parent b5cd4f2f70
commit 82eae511ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 3 deletions

View file

@ -48,7 +48,15 @@ impl super::BackgroundDocumentRequestHandler for CodeActions {
if snapshot.client_settings().fix_all() { if snapshot.client_settings().fix_all() {
if supported_code_actions.contains(&SupportedCodeAction::SourceFixAll) { if supported_code_actions.contains(&SupportedCodeAction::SourceFixAll) {
response.push(fix_all(&snapshot).with_failure_code(ErrorCode::InternalError)?); if snapshot.is_notebook_cell() {
// This is ignore here because the client requests this code action for each
// cell in parallel and the server would send a workspace edit with the same
// content which would result in applying the same edit multiple times
// resulting in (possibly) duplicate code.
tracing::debug!("Ignoring `source.fixAll` code action for a notebook cell");
} else {
response.push(fix_all(&snapshot).with_failure_code(ErrorCode::InternalError)?);
}
} else if supported_code_actions.contains(&SupportedCodeAction::NotebookSourceFixAll) { } else if supported_code_actions.contains(&SupportedCodeAction::NotebookSourceFixAll) {
response response
.push(notebook_fix_all(&snapshot).with_failure_code(ErrorCode::InternalError)?); .push(notebook_fix_all(&snapshot).with_failure_code(ErrorCode::InternalError)?);
@ -57,8 +65,19 @@ impl super::BackgroundDocumentRequestHandler for CodeActions {
if snapshot.client_settings().organize_imports() { if snapshot.client_settings().organize_imports() {
if supported_code_actions.contains(&SupportedCodeAction::SourceOrganizeImports) { if supported_code_actions.contains(&SupportedCodeAction::SourceOrganizeImports) {
response if snapshot.is_notebook_cell() {
.push(organize_imports(&snapshot).with_failure_code(ErrorCode::InternalError)?); // This is ignore here because the client requests this code action for each
// cell in parallel and the server would send a workspace edit with the same
// content which would result in applying the same edit multiple times
// resulting in (possibly) duplicate code.
tracing::debug!(
"Ignoring `source.organizeImports` code action for a notebook cell"
);
} else {
response.push(
organize_imports(&snapshot).with_failure_code(ErrorCode::InternalError)?,
);
}
} else if supported_code_actions } else if supported_code_actions
.contains(&SupportedCodeAction::NotebookSourceOrganizeImports) .contains(&SupportedCodeAction::NotebookSourceOrganizeImports)
{ {

View file

@ -50,6 +50,21 @@ impl super::BackgroundDocumentRequestHandler for CodeActionResolve {
.with_failure_code(ErrorCode::InvalidParams); .with_failure_code(ErrorCode::InvalidParams);
}; };
match action_kind {
SupportedCodeAction::SourceFixAll | SupportedCodeAction::SourceOrganizeImports
if snapshot.is_notebook_cell() =>
{
// This should never occur because we ignore generating these code actions for a
// notebook cell in the `textDocument/codeAction` request handler.
return Err(anyhow::anyhow!(
"Code action resolver cannot resolve {:?} for a notebook cell",
action_kind.to_kind().as_str()
))
.with_failure_code(ErrorCode::InvalidParams);
}
_ => {}
}
action.edit = match action_kind { action.edit = match action_kind {
SupportedCodeAction::SourceFixAll | SupportedCodeAction::NotebookSourceFixAll => Some( SupportedCodeAction::SourceFixAll | SupportedCodeAction::NotebookSourceFixAll => Some(
resolve_edit_for_fix_all( resolve_edit_for_fix_all(

View file

@ -184,4 +184,15 @@ impl DocumentSnapshot {
pub(crate) fn encoding(&self) -> PositionEncoding { pub(crate) fn encoding(&self) -> PositionEncoding {
self.position_encoding self.position_encoding
} }
/// Returns `true` if this snapshot represents a notebook cell.
pub(crate) const fn is_notebook_cell(&self) -> bool {
matches!(
&self.document_ref,
index::DocumentQuery::Notebook {
cell_url: Some(_),
..
}
)
}
} }