Skip to content

Commit

Permalink
Add a UnindexedProject notification and a corresponding setting.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbarsky committed Nov 9, 2023
1 parent 2625495 commit 51d2ed8
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 4 deletions.
9 changes: 8 additions & 1 deletion crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ config_data! {
/// Whether to show `can't find Cargo.toml` error message.
notifications_cargoTomlNotFound: bool = "true",

/// Whether to send an UnindexedProject notification to the client.
notifications_unindexedProject: bool = "false",

/// How many worker threads in the main loop. The default `null` means to pick automatically.
numThreads: Option<usize> = "null",

Expand Down Expand Up @@ -717,6 +720,7 @@ pub enum FilesWatcher {
#[derive(Debug, Clone)]
pub struct NotificationsConfig {
pub cargo_toml_not_found: bool,
pub unindexed_project: bool,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -1188,7 +1192,10 @@ impl Config {
}

pub fn notifications(&self) -> NotificationsConfig {
NotificationsConfig { cargo_toml_not_found: self.data.notifications_cargoTomlNotFound }
NotificationsConfig {
cargo_toml_not_found: self.data.notifications_cargoTomlNotFound,
unindexed_project: self.data.notifications_unindexedProject,
}
}

pub fn cargo_autoreload(&self) -> bool {
Expand Down
33 changes: 31 additions & 2 deletions crates/rust-analyzer/src/handlers/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use vfs::{AbsPathBuf, ChangeKind, VfsPath};
use crate::{
config::Config,
global_state::GlobalState,
lsp::{from_proto, utils::apply_document_changes},
lsp::{ext, from_proto, utils::apply_document_changes},
lsp_ext::RunFlycheckParams,
mem_docs::DocumentData,
reload,
Expand Down Expand Up @@ -55,6 +55,7 @@ pub(crate) fn handle_did_open_text_document(
params: DidOpenTextDocumentParams,
) -> anyhow::Result<()> {
let _p = profile::span("handle_did_open_text_document");
tracing::error!("handle_did_open_text_document");

if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
let already_exists = state
Expand All @@ -64,7 +65,14 @@ pub(crate) fn handle_did_open_text_document(
if already_exists {
tracing::error!("duplicate DidOpenTextDocument: {}", path);
}
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
{
let vfs = &mut state.vfs.write().0;
vfs.set_file_contents(path.clone(), Some(params.text_document.text.into_bytes()));
}

if state.config.notifications().unindexed_project {
run_unindexed_project(state, params.text_document.uri)
}
}
Ok(())
}
Expand Down Expand Up @@ -341,3 +349,24 @@ pub(crate) fn handle_run_flycheck(
}
Ok(())
}

pub(crate) fn run_unindexed_project(state: &mut GlobalState, uri: lsp_types::Url) {
let _p = profile::span("run_unindexed_project");

if state.is_quiescent() && state.process_changes() {
let id = from_proto::file_id(&state.snapshot(), &uri).expect("Unable to get file ID");
if let Ok(crates) = state.snapshot().analysis.crates_for(id) {
if crates.is_empty() {
tracing::debug!(?uri, "rust-analyzer does not track this file");
let text_documents = vec![lsp_types::TextDocumentIdentifier { uri: uri }];
state.send_notification::<ext::UnindexedProject>(ext::UnindexedProjectParams {
text_documents,
});
} else {
tracing::debug!(?uri, "file is indexed by rust-analyzer")
}
} else {
tracing::warn!("was unable to get analysis for crate")
}
}
}
13 changes: 13 additions & 0 deletions crates/rust-analyzer/src/lsp/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,3 +696,16 @@ pub struct CompletionImport {
pub struct ClientCommandOptions {
pub commands: Vec<String>,
}

pub enum UnindexedProject {}

impl Notification for UnindexedProject {
type Params = UnindexedProjectParams;
const METHOD: &'static str = "rust-analyzer/unindexedProject";
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct UnindexedProjectParams {
pub text_documents: Vec<TextDocumentIdentifier>,
}
21 changes: 20 additions & 1 deletion docs/dev/lsp-extensions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!---
lsp/ext.rs hash: 121482ee911854da
lsp/ext.rs hash: 21cb0f2f547891a2
If you need to change the above hash to make the test pass, please check if you
need to adjust this doc as well and ping this issue:
Expand Down Expand Up @@ -444,6 +444,25 @@ Reloads project information (that is, re-executes `cargo metadata`).

Rebuilds build scripts and proc-macros, and runs the build scripts to reseed the build data.

## Unindexed Project

**Experimental Client Capability:** `{ "unindexedProject": boolean }`

**Method:** `rust-analyzer/unindexedProject`

**Notification:**

```typescript
interface UnindexedProjectParams {
/// A list of documents that rust-analyzer has determined are not indexed.
textDocuments: lc.TextDocumentIdentifier[]
}
```

This notification is sent from the server to the client. The client is expected
to determine the appropriate owners of `textDocuments` and update `linkedProjects`
if an owner can be determined successfully.

## Server Status

**Experimental Client Capability:** `{ "serverStatusNotification": boolean }`
Expand Down
5 changes: 5 additions & 0 deletions docs/user/generated_config.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,11 @@ Sets the LRU capacity of the specified queries.
--
Whether to show `can't find Cargo.toml` error message.
--
[[rust-analyzer.notifications.unindexedProject]]rust-analyzer.notifications.unindexedProject (default: `false`)::
+
--
Whether to send an UnindexedProject notification to the client.
--
[[rust-analyzer.numThreads]]rust-analyzer.numThreads (default: `null`)::
+
--
Expand Down
5 changes: 5 additions & 0 deletions editors/code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,11 @@
"default": true,
"type": "boolean"
},
"rust-analyzer.notifications.unindexedProject": {
"markdownDescription": "Whether to send an UnindexedProject notification to the client.",
"default": false,
"type": "boolean"
},
"rust-analyzer.numThreads": {
"markdownDescription": "How many worker threads in the main loop. The default `null` means to pick automatically.",
"default": null,
Expand Down
13 changes: 13 additions & 0 deletions editors/code/src/ctx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ export class Ctx implements RustAnalyzerExtensionApi {
this.outputChannel!.show();
}),
);
this.pushClientCleanup(
this._client.onNotification(ra.unindexedProject, async (params) => {
const command = `${this.config.discoverProjectRunner}.discoverWorkspaceCommand`;
log.info(`running command: ${command}`);
let uris = params.textDocuments.map((doc) => vscode.Uri.parse(doc.uri, true));

Check failure on line 240 in editors/code/src/ctx.ts

View workflow job for this annotation

GitHub Actions / TypeScript (ubuntu-latest)

'uris' is never reassigned. Use 'const' instead

Check failure on line 240 in editors/code/src/ctx.ts

View workflow job for this annotation

GitHub Actions / TypeScript (windows-latest)

'uris' is never reassigned. Use 'const' instead
const projects: JsonProject[] = await vscode.commands.executeCommand(
command,
uris,
);
this.setWorkspaces(projects);
await this.notifyRustAnalyzer();
}),
);
}
return this._client;
}
Expand Down
6 changes: 6 additions & 0 deletions editors/code/src/lsp_ext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,3 +220,9 @@ export type RecursiveMemoryLayoutNode = {
export type RecursiveMemoryLayout = {
nodes: RecursiveMemoryLayoutNode[];
};

export const unindexedProject = new lc.NotificationType<UnindexedProjectParams>(
"rust-analyzer/unindexedProject",
);

export type UnindexedProjectParams = { textDocuments: lc.TextDocumentIdentifier[] };

0 comments on commit 51d2ed8

Please sign in to comment.