Skip to content

Commit 51d2ed8

Browse files
committed
Add a UnindexedProject notification and a corresponding setting.
1 parent 2625495 commit 51d2ed8

File tree

8 files changed

+101
-4
lines changed

8 files changed

+101
-4
lines changed

crates/rust-analyzer/src/config.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ config_data! {
457457
/// Whether to show `can't find Cargo.toml` error message.
458458
notifications_cargoTomlNotFound: bool = "true",
459459

460+
/// Whether to send an UnindexedProject notification to the client.
461+
notifications_unindexedProject: bool = "false",
462+
460463
/// How many worker threads in the main loop. The default `null` means to pick automatically.
461464
numThreads: Option<usize> = "null",
462465

@@ -717,6 +720,7 @@ pub enum FilesWatcher {
717720
#[derive(Debug, Clone)]
718721
pub struct NotificationsConfig {
719722
pub cargo_toml_not_found: bool,
723+
pub unindexed_project: bool,
720724
}
721725

722726
#[derive(Debug, Clone)]
@@ -1188,7 +1192,10 @@ impl Config {
11881192
}
11891193

11901194
pub fn notifications(&self) -> NotificationsConfig {
1191-
NotificationsConfig { cargo_toml_not_found: self.data.notifications_cargoTomlNotFound }
1195+
NotificationsConfig {
1196+
cargo_toml_not_found: self.data.notifications_cargoTomlNotFound,
1197+
unindexed_project: self.data.notifications_unindexedProject,
1198+
}
11921199
}
11931200

11941201
pub fn cargo_autoreload(&self) -> bool {

crates/rust-analyzer/src/handlers/notification.rs

+31-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use vfs::{AbsPathBuf, ChangeKind, VfsPath};
1515
use crate::{
1616
config::Config,
1717
global_state::GlobalState,
18-
lsp::{from_proto, utils::apply_document_changes},
18+
lsp::{ext, from_proto, utils::apply_document_changes},
1919
lsp_ext::RunFlycheckParams,
2020
mem_docs::DocumentData,
2121
reload,
@@ -55,6 +55,7 @@ pub(crate) fn handle_did_open_text_document(
5555
params: DidOpenTextDocumentParams,
5656
) -> anyhow::Result<()> {
5757
let _p = profile::span("handle_did_open_text_document");
58+
tracing::error!("handle_did_open_text_document");
5859

5960
if let Ok(path) = from_proto::vfs_path(&params.text_document.uri) {
6061
let already_exists = state
@@ -64,7 +65,14 @@ pub(crate) fn handle_did_open_text_document(
6465
if already_exists {
6566
tracing::error!("duplicate DidOpenTextDocument: {}", path);
6667
}
67-
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
68+
{
69+
let vfs = &mut state.vfs.write().0;
70+
vfs.set_file_contents(path.clone(), Some(params.text_document.text.into_bytes()));
71+
}
72+
73+
if state.config.notifications().unindexed_project {
74+
run_unindexed_project(state, params.text_document.uri)
75+
}
6876
}
6977
Ok(())
7078
}
@@ -341,3 +349,24 @@ pub(crate) fn handle_run_flycheck(
341349
}
342350
Ok(())
343351
}
352+
353+
pub(crate) fn run_unindexed_project(state: &mut GlobalState, uri: lsp_types::Url) {
354+
let _p = profile::span("run_unindexed_project");
355+
356+
if state.is_quiescent() && state.process_changes() {
357+
let id = from_proto::file_id(&state.snapshot(), &uri).expect("Unable to get file ID");
358+
if let Ok(crates) = state.snapshot().analysis.crates_for(id) {
359+
if crates.is_empty() {
360+
tracing::debug!(?uri, "rust-analyzer does not track this file");
361+
let text_documents = vec![lsp_types::TextDocumentIdentifier { uri: uri }];
362+
state.send_notification::<ext::UnindexedProject>(ext::UnindexedProjectParams {
363+
text_documents,
364+
});
365+
} else {
366+
tracing::debug!(?uri, "file is indexed by rust-analyzer")
367+
}
368+
} else {
369+
tracing::warn!("was unable to get analysis for crate")
370+
}
371+
}
372+
}

crates/rust-analyzer/src/lsp/ext.rs

+13
Original file line numberDiff line numberDiff line change
@@ -696,3 +696,16 @@ pub struct CompletionImport {
696696
pub struct ClientCommandOptions {
697697
pub commands: Vec<String>,
698698
}
699+
700+
pub enum UnindexedProject {}
701+
702+
impl Notification for UnindexedProject {
703+
type Params = UnindexedProjectParams;
704+
const METHOD: &'static str = "rust-analyzer/unindexedProject";
705+
}
706+
707+
#[derive(Deserialize, Serialize, Debug)]
708+
#[serde(rename_all = "camelCase")]
709+
pub struct UnindexedProjectParams {
710+
pub text_documents: Vec<TextDocumentIdentifier>,
711+
}

docs/dev/lsp-extensions.md

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!---
2-
lsp/ext.rs hash: 121482ee911854da
2+
lsp/ext.rs hash: 21cb0f2f547891a2
33
44
If you need to change the above hash to make the test pass, please check if you
55
need to adjust this doc as well and ping this issue:
@@ -444,6 +444,25 @@ Reloads project information (that is, re-executes `cargo metadata`).
444444

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

447+
## Unindexed Project
448+
449+
**Experimental Client Capability:** `{ "unindexedProject": boolean }`
450+
451+
**Method:** `rust-analyzer/unindexedProject`
452+
453+
**Notification:**
454+
455+
```typescript
456+
interface UnindexedProjectParams {
457+
/// A list of documents that rust-analyzer has determined are not indexed.
458+
textDocuments: lc.TextDocumentIdentifier[]
459+
}
460+
```
461+
462+
This notification is sent from the server to the client. The client is expected
463+
to determine the appropriate owners of `textDocuments` and update `linkedProjects`
464+
if an owner can be determined successfully.
465+
447466
## Server Status
448467

449468
**Experimental Client Capability:** `{ "serverStatusNotification": boolean }`

docs/user/generated_config.adoc

+5
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,11 @@ Sets the LRU capacity of the specified queries.
714714
--
715715
Whether to show `can't find Cargo.toml` error message.
716716
--
717+
[[rust-analyzer.notifications.unindexedProject]]rust-analyzer.notifications.unindexedProject (default: `false`)::
718+
+
719+
--
720+
Whether to send an UnindexedProject notification to the client.
721+
--
717722
[[rust-analyzer.numThreads]]rust-analyzer.numThreads (default: `null`)::
718723
+
719724
--

editors/code/package.json

+5
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,11 @@
14361436
"default": true,
14371437
"type": "boolean"
14381438
},
1439+
"rust-analyzer.notifications.unindexedProject": {
1440+
"markdownDescription": "Whether to send an UnindexedProject notification to the client.",
1441+
"default": false,
1442+
"type": "boolean"
1443+
},
14391444
"rust-analyzer.numThreads": {
14401445
"markdownDescription": "How many worker threads in the main loop. The default `null` means to pick automatically.",
14411446
"default": null,

editors/code/src/ctx.ts

+13
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,19 @@ export class Ctx implements RustAnalyzerExtensionApi {
233233
this.outputChannel!.show();
234234
}),
235235
);
236+
this.pushClientCleanup(
237+
this._client.onNotification(ra.unindexedProject, async (params) => {
238+
const command = `${this.config.discoverProjectRunner}.discoverWorkspaceCommand`;
239+
log.info(`running command: ${command}`);
240+
let uris = params.textDocuments.map((doc) => vscode.Uri.parse(doc.uri, true));
241+
const projects: JsonProject[] = await vscode.commands.executeCommand(
242+
command,
243+
uris,
244+
);
245+
this.setWorkspaces(projects);
246+
await this.notifyRustAnalyzer();
247+
}),
248+
);
236249
}
237250
return this._client;
238251
}

editors/code/src/lsp_ext.ts

+6
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,9 @@ export type RecursiveMemoryLayoutNode = {
220220
export type RecursiveMemoryLayout = {
221221
nodes: RecursiveMemoryLayoutNode[];
222222
};
223+
224+
export const unindexedProject = new lc.NotificationType<UnindexedProjectParams>(
225+
"rust-analyzer/unindexedProject",
226+
);
227+
228+
export type UnindexedProjectParams = { textDocuments: lc.TextDocumentIdentifier[] };

0 commit comments

Comments
 (0)