mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
Auto merge of #17395 - davidbarsky:david/remove-unindexed-project-notification, r=Veykril
chore: remove `UnindexinedProject` notification This PR is split out from https://github.com/rust-lang/rust-analyzer/pull/17246/ (and contains its changes, which is a little annoying from a review perspective...). I'd like to land this change a week or so after #17246 lands in order to give any users of the unindexed project notification time to adopt migrate.
This commit is contained in:
commit
eb5da56d83
15 changed files with 14 additions and 366 deletions
|
@ -679,9 +679,6 @@ config_data! {
|
||||||
/// Whether to show `can't find Cargo.toml` error message.
|
/// Whether to show `can't find Cargo.toml` error message.
|
||||||
notifications_cargoTomlNotFound: bool = true,
|
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.
|
/// How many worker threads in the main loop. The default `null` means to pick automatically.
|
||||||
numThreads: Option<NumThreads> = None,
|
numThreads: Option<NumThreads> = None,
|
||||||
|
|
||||||
|
@ -1236,7 +1233,6 @@ pub enum FilesWatcher {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NotificationsConfig {
|
pub struct NotificationsConfig {
|
||||||
pub cargo_toml_not_found: bool,
|
pub cargo_toml_not_found: bool,
|
||||||
pub unindexed_project: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -1800,7 +1796,6 @@ impl Config {
|
||||||
pub fn notifications(&self) -> NotificationsConfig {
|
pub fn notifications(&self) -> NotificationsConfig {
|
||||||
NotificationsConfig {
|
NotificationsConfig {
|
||||||
cargo_toml_not_found: self.notifications_cargoTomlNotFound().to_owned(),
|
cargo_toml_not_found: self.notifications_cargoTomlNotFound().to_owned(),
|
||||||
unindexed_project: self.notifications_unindexedProject().to_owned(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,7 @@ pub(crate) fn handle_did_open_text_document(
|
||||||
|
|
||||||
tracing::info!("New file content set {:?}", params.text_document.text);
|
tracing::info!("New file content set {:?}", params.text_document.text);
|
||||||
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
||||||
if state.config.discover_workspace_config().is_some()
|
if state.config.discover_workspace_config().is_some() {
|
||||||
|| state.config.notifications().unindexed_project
|
|
||||||
{
|
|
||||||
tracing::debug!("queuing task");
|
tracing::debug!("queuing task");
|
||||||
let _ = state
|
let _ = state
|
||||||
.deferred_task_queue
|
.deferred_task_queue
|
||||||
|
|
|
@ -834,16 +834,3 @@ pub struct CompletionImport {
|
||||||
pub struct ClientCommandOptions {
|
pub struct ClientCommandOptions {
|
||||||
pub commands: Vec<String>,
|
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>,
|
|
||||||
}
|
|
||||||
|
|
|
@ -90,7 +90,6 @@ pub(crate) enum QueuedTask {
|
||||||
pub(crate) enum Task {
|
pub(crate) enum Task {
|
||||||
Response(lsp_server::Response),
|
Response(lsp_server::Response),
|
||||||
DiscoverLinkedProjects(DiscoverProjectParam),
|
DiscoverLinkedProjects(DiscoverProjectParam),
|
||||||
ClientNotification(lsp_ext::UnindexedProjectParams),
|
|
||||||
Retry(lsp_server::Request),
|
Retry(lsp_server::Request),
|
||||||
Diagnostics(DiagnosticsGeneration, Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
|
Diagnostics(DiagnosticsGeneration, Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
|
||||||
DiscoverTest(lsp_ext::DiscoverTestResults),
|
DiscoverTest(lsp_ext::DiscoverTestResults),
|
||||||
|
@ -642,9 +641,6 @@ impl GlobalState {
|
||||||
fn handle_task(&mut self, prime_caches_progress: &mut Vec<PrimeCachesProgress>, task: Task) {
|
fn handle_task(&mut self, prime_caches_progress: &mut Vec<PrimeCachesProgress>, task: Task) {
|
||||||
match task {
|
match task {
|
||||||
Task::Response(response) => self.respond(response),
|
Task::Response(response) => self.respond(response),
|
||||||
Task::ClientNotification(params) => {
|
|
||||||
self.send_notification::<lsp_ext::UnindexedProject>(params)
|
|
||||||
}
|
|
||||||
// Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
|
// Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
|
||||||
Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
|
Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
|
||||||
Task::Retry(_) => (),
|
Task::Retry(_) => (),
|
||||||
|
@ -825,12 +821,7 @@ impl GlobalState {
|
||||||
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
|
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
|
||||||
let arg = DiscoverProjectParam::Path(path);
|
let arg = DiscoverProjectParam::Path(path);
|
||||||
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
|
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
|
||||||
} else if snap.config.notifications().unindexed_project {
|
}
|
||||||
let params = lsp_ext::UnindexedProjectParams {
|
|
||||||
text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
|
|
||||||
};
|
|
||||||
sender.send(Task::ClientNotification(params)).unwrap();
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!(?uri, "is indexed");
|
tracing::debug!(?uri, "is indexed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ use lsp_types::{
|
||||||
InlayHint, InlayHintLabel, InlayHintParams, PartialResultParams, Position, Range,
|
InlayHint, InlayHintLabel, InlayHintParams, PartialResultParams, Position, Range,
|
||||||
RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams,
|
RenameFilesParams, TextDocumentItem, TextDocumentPositionParams, WorkDoneProgressParams,
|
||||||
};
|
};
|
||||||
use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams, UnindexedProject};
|
use rust_analyzer::lsp::ext::{OnEnter, Runnables, RunnablesParams};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use stdx::format_to_acc;
|
use stdx::format_to_acc;
|
||||||
|
|
||||||
|
@ -811,66 +811,6 @@ fn main() {{}}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_opening_a_file_outside_of_indexed_workspace() {
|
|
||||||
if skip_slow_tests() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tmp_dir = TestDir::new();
|
|
||||||
let path = tmp_dir.path();
|
|
||||||
|
|
||||||
let project = json!({
|
|
||||||
"roots": [path],
|
|
||||||
"crates": [ {
|
|
||||||
"root_module": path.join("src/crate_one/lib.rs"),
|
|
||||||
"deps": [],
|
|
||||||
"edition": "2015",
|
|
||||||
"cfg": [ "cfg_atom_1", "feature=\"cfg_1\""],
|
|
||||||
} ]
|
|
||||||
});
|
|
||||||
|
|
||||||
let code = format!(
|
|
||||||
r#"
|
|
||||||
//- /rust-project.json
|
|
||||||
{project}
|
|
||||||
|
|
||||||
//- /src/crate_one/lib.rs
|
|
||||||
mod bar;
|
|
||||||
|
|
||||||
fn main() {{}}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
|
|
||||||
let server = Project::with_fixture(&code)
|
|
||||||
.tmp_dir(tmp_dir)
|
|
||||||
.with_config(serde_json::json!({
|
|
||||||
"notifications": {
|
|
||||||
"unindexedProject": true
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
.server()
|
|
||||||
.wait_until_workspace_is_loaded();
|
|
||||||
|
|
||||||
let uri = server.doc_id("src/crate_two/lib.rs").uri;
|
|
||||||
server.notification::<DidOpenTextDocument>(DidOpenTextDocumentParams {
|
|
||||||
text_document: TextDocumentItem {
|
|
||||||
uri: uri.clone(),
|
|
||||||
language_id: "rust".to_owned(),
|
|
||||||
version: 0,
|
|
||||||
text: "/// Docs\nfn foo() {}".to_owned(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
let expected = json!({
|
|
||||||
"textDocuments": [
|
|
||||||
{
|
|
||||||
"uri": uri
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
server.expect_notification::<UnindexedProject>(expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn diagnostics_dont_block_typing() {
|
fn diagnostics_dont_block_typing() {
|
||||||
if skip_slow_tests() {
|
if skip_slow_tests() {
|
||||||
|
|
|
@ -256,40 +256,6 @@ impl Server {
|
||||||
self.send_notification(r)
|
self.send_notification(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn expect_notification<N>(&self, expected: Value)
|
|
||||||
where
|
|
||||||
N: lsp_types::notification::Notification,
|
|
||||||
N::Params: Serialize,
|
|
||||||
{
|
|
||||||
while let Some(Message::Notification(actual)) =
|
|
||||||
recv_timeout(&self.client.receiver).unwrap_or_else(|_| panic!("timed out"))
|
|
||||||
{
|
|
||||||
if actual.method == N::METHOD {
|
|
||||||
let actual = actual
|
|
||||||
.clone()
|
|
||||||
.extract::<Value>(N::METHOD)
|
|
||||||
.expect("was not able to extract notification");
|
|
||||||
|
|
||||||
tracing::debug!(?actual, "got notification");
|
|
||||||
if let Some((expected_part, actual_part)) = find_mismatch(&expected, &actual) {
|
|
||||||
panic!(
|
|
||||||
"JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
|
|
||||||
to_string_pretty(&expected).unwrap(),
|
|
||||||
to_string_pretty(&actual).unwrap(),
|
|
||||||
to_string_pretty(expected_part).unwrap(),
|
|
||||||
to_string_pretty(actual_part).unwrap(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
tracing::debug!("successfully matched notification");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic!("never got expected notification");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value)
|
pub(crate) fn request<R>(&self, params: R::Params, expected_resp: Value)
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!---
|
<!---
|
||||||
lsp/ext.rs hash: 278250dba58cd879
|
lsp/ext.rs hash: f41950db4c7b3a5a
|
||||||
|
|
||||||
If you need to change the above hash to make the test pass, please check if you
|
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:
|
need to adjust this doc as well and ping this issue:
|
||||||
|
@ -616,25 +616,6 @@ 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.
|
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
|
## Server Status
|
||||||
|
|
||||||
**Experimental Client Capability:** `{ "serverStatusNotification": boolean }`
|
**Experimental Client Capability:** `{ "serverStatusNotification": boolean }`
|
||||||
|
|
|
@ -830,11 +830,6 @@ Sets the LRU capacity of the specified queries.
|
||||||
--
|
--
|
||||||
Whether to show `can't find Cargo.toml` error message.
|
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`)::
|
[[rust-analyzer.numThreads]]rust-analyzer.numThreads (default: `null`)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
|
|
@ -2267,16 +2267,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"title": "notifications",
|
|
||||||
"properties": {
|
|
||||||
"rust-analyzer.notifications.unindexedProject": {
|
|
||||||
"markdownDescription": "Whether to send an UnindexedProject notification to the client.",
|
|
||||||
"default": false,
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"title": "general",
|
"title": "general",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
|
@ -42,16 +42,7 @@ export async function createClient(
|
||||||
const resp = await next(params, token);
|
const resp = await next(params, token);
|
||||||
if (resp && Array.isArray(resp)) {
|
if (resp && Array.isArray(resp)) {
|
||||||
return resp.map((val) => {
|
return resp.map((val) => {
|
||||||
return prepareVSCodeConfig(val, (key, cfg) => {
|
return prepareVSCodeConfig(val);
|
||||||
// we only want to set discovered workspaces on the right key
|
|
||||||
// and if a workspace has been discovered.
|
|
||||||
if (
|
|
||||||
key === "linkedProjects" &&
|
|
||||||
config.discoveredWorkspaces.length > 0
|
|
||||||
) {
|
|
||||||
cfg[key] = config.discoveredWorkspaces;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return resp;
|
return resp;
|
||||||
|
|
|
@ -2,9 +2,9 @@ import * as Is from "vscode-languageclient/lib/common/utils/is";
|
||||||
import * as os from "os";
|
import * as os from "os";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import { type Env, log, unwrapUndefinable, expectNotUndefined } from "./util";
|
import { expectNotUndefined, log, unwrapUndefinable } from "./util";
|
||||||
import type { JsonProject } from "./rust_project";
|
import type { Env } from "./util";
|
||||||
import type { Disposable } from "./ctx";
|
import type { Disposable } from "vscode";
|
||||||
|
|
||||||
export type RunnableEnvCfgItem = {
|
export type RunnableEnvCfgItem = {
|
||||||
mask?: string;
|
mask?: string;
|
||||||
|
@ -31,7 +31,6 @@ export class Config {
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor(disposables: Disposable[]) {
|
constructor(disposables: Disposable[]) {
|
||||||
this.discoveredWorkspaces = [];
|
|
||||||
vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, disposables);
|
vscode.workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, disposables);
|
||||||
this.refreshLogging();
|
this.refreshLogging();
|
||||||
this.configureLanguage();
|
this.configureLanguage();
|
||||||
|
@ -52,8 +51,6 @@ export class Config {
|
||||||
log.info("Using configuration", Object.fromEntries(cfg));
|
log.info("Using configuration", Object.fromEntries(cfg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public discoveredWorkspaces: JsonProject[];
|
|
||||||
|
|
||||||
private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) {
|
private async onDidChangeConfiguration(event: vscode.ConfigurationChangeEvent) {
|
||||||
this.refreshLogging();
|
this.refreshLogging();
|
||||||
|
|
||||||
|
@ -342,18 +339,7 @@ export class Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the optional `cb?` parameter is meant to be used to add additional
|
export function prepareVSCodeConfig<T>(resp: T): T {
|
||||||
// key/value pairs to the VS Code configuration. This needed for, e.g.,
|
|
||||||
// including a `rust-project.json` into the `linkedProjects` key as part
|
|
||||||
// of the configuration/InitializationParams _without_ causing VS Code
|
|
||||||
// configuration to be written out to workspace-level settings. This is
|
|
||||||
// undesirable behavior because rust-project.json files can be tens of
|
|
||||||
// thousands of lines of JSON, most of which is not meant for humans
|
|
||||||
// to interact with.
|
|
||||||
export function prepareVSCodeConfig<T>(
|
|
||||||
resp: T,
|
|
||||||
cb?: (key: Extract<keyof T, string>, res: { [key: string]: any }) => void,
|
|
||||||
): T {
|
|
||||||
if (Is.string(resp)) {
|
if (Is.string(resp)) {
|
||||||
return substituteVSCodeVariableInString(resp) as T;
|
return substituteVSCodeVariableInString(resp) as T;
|
||||||
} else if (resp && Is.array<any>(resp)) {
|
} else if (resp && Is.array<any>(resp)) {
|
||||||
|
@ -365,9 +351,6 @@ export function prepareVSCodeConfig<T>(
|
||||||
for (const key in resp) {
|
for (const key in resp) {
|
||||||
const val = resp[key];
|
const val = resp[key];
|
||||||
res[key] = prepareVSCodeConfig(val);
|
res[key] = prepareVSCodeConfig(val);
|
||||||
if (cb) {
|
|
||||||
cb(key, res);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res as T;
|
return res as T;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as vscode from "vscode";
|
import * as vscode from "vscode";
|
||||||
import * as lc from "vscode-languageclient/node";
|
import type * as lc from "vscode-languageclient/node";
|
||||||
import * as ra from "./lsp_ext";
|
import * as ra from "./lsp_ext";
|
||||||
|
|
||||||
import { Config, prepareVSCodeConfig } from "./config";
|
import { Config, prepareVSCodeConfig } from "./config";
|
||||||
|
@ -22,11 +22,10 @@ import {
|
||||||
import { execRevealDependency } from "./commands";
|
import { execRevealDependency } from "./commands";
|
||||||
import { PersistentState } from "./persistent_state";
|
import { PersistentState } from "./persistent_state";
|
||||||
import { bootstrap } from "./bootstrap";
|
import { bootstrap } from "./bootstrap";
|
||||||
import type { RustAnalyzerExtensionApi } from "./main";
|
|
||||||
import type { JsonProject } from "./rust_project";
|
|
||||||
import { prepareTestExplorer } from "./test_explorer";
|
import { prepareTestExplorer } from "./test_explorer";
|
||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
import { text } from "node:stream/consumers";
|
import { text } from "node:stream/consumers";
|
||||||
|
import type { RustAnalyzerExtensionApi } from "./main";
|
||||||
|
|
||||||
// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
|
// We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
|
||||||
// only those are in use. We use "Empty" to represent these scenarios
|
// only those are in use. We use "Empty" to represent these scenarios
|
||||||
|
@ -71,7 +70,7 @@ export type CtxInit = Ctx & {
|
||||||
|
|
||||||
export class Ctx implements RustAnalyzerExtensionApi {
|
export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
readonly statusBar: vscode.StatusBarItem;
|
readonly statusBar: vscode.StatusBarItem;
|
||||||
config: Config;
|
readonly config: Config;
|
||||||
readonly workspace: Workspace;
|
readonly workspace: Workspace;
|
||||||
readonly version: string;
|
readonly version: string;
|
||||||
|
|
||||||
|
@ -212,15 +211,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
};
|
};
|
||||||
|
|
||||||
let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
|
let rawInitializationOptions = vscode.workspace.getConfiguration("rust-analyzer");
|
||||||
if (this.config.discoverProjectRunner) {
|
|
||||||
const command = `${this.config.discoverProjectRunner}.discoverWorkspaceCommand`;
|
|
||||||
log.info(`running command: ${command}`);
|
|
||||||
const uris = vscode.workspace.textDocuments
|
|
||||||
.filter(isRustDocument)
|
|
||||||
.map((document) => document.uri);
|
|
||||||
const projects: JsonProject[] = await vscode.commands.executeCommand(command, uris);
|
|
||||||
this.setWorkspaces(projects);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.workspace.kind === "Detached Files") {
|
if (this.workspace.kind === "Detached Files") {
|
||||||
rawInitializationOptions = {
|
rawInitializationOptions = {
|
||||||
|
@ -229,16 +219,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const initializationOptions = prepareVSCodeConfig(
|
const initializationOptions = prepareVSCodeConfig(rawInitializationOptions);
|
||||||
rawInitializationOptions,
|
|
||||||
(key, obj) => {
|
|
||||||
// we only want to set discovered workspaces on the right key
|
|
||||||
// and if a workspace has been discovered.
|
|
||||||
if (key === "linkedProjects" && this.config.discoveredWorkspaces.length > 0) {
|
|
||||||
obj["linkedProjects"] = this.config.discoveredWorkspaces;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
this._client = await createClient(
|
this._client = await createClient(
|
||||||
this.traceOutputChannel,
|
this.traceOutputChannel,
|
||||||
|
@ -258,23 +239,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
this.outputChannel!.show();
|
this.outputChannel!.show();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
this.pushClientCleanup(
|
|
||||||
this._client.onNotification(ra.unindexedProject, async (params) => {
|
|
||||||
if (this.config.discoverProjectRunner) {
|
|
||||||
const command = `${this.config.discoverProjectRunner}.discoverWorkspaceCommand`;
|
|
||||||
log.info(`running command: ${command}`);
|
|
||||||
const uris = params.textDocuments.map((doc) =>
|
|
||||||
vscode.Uri.parse(doc.uri, true),
|
|
||||||
);
|
|
||||||
const projects: JsonProject[] = await vscode.commands.executeCommand(
|
|
||||||
command,
|
|
||||||
uris,
|
|
||||||
);
|
|
||||||
this.setWorkspaces(projects);
|
|
||||||
await this.notifyRustAnalyzer();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return this._client;
|
return this._client;
|
||||||
}
|
}
|
||||||
|
@ -400,19 +364,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
return this.extCtx.subscriptions;
|
return this.extCtx.subscriptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
setWorkspaces(workspaces: JsonProject[]) {
|
|
||||||
this.config.discoveredWorkspaces = workspaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
async notifyRustAnalyzer(): Promise<void> {
|
|
||||||
// this is a workaround to avoid needing writing the `rust-project.json` into
|
|
||||||
// a workspace-level VS Code-specific settings folder. We'd like to keep the
|
|
||||||
// `rust-project.json` entirely in-memory.
|
|
||||||
await this.client?.sendNotification(lc.DidChangeConfigurationNotification.type, {
|
|
||||||
settings: "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateCommands(forceDisable?: "disable") {
|
private updateCommands(forceDisable?: "disable") {
|
||||||
this.commandDisposables.forEach((disposable) => disposable.dispose());
|
this.commandDisposables.forEach((disposable) => disposable.dispose());
|
||||||
this.commandDisposables = [];
|
this.commandDisposables = [];
|
||||||
|
|
|
@ -303,9 +303,3 @@ export type RecursiveMemoryLayoutNode = {
|
||||||
export type RecursiveMemoryLayout = {
|
export type RecursiveMemoryLayout = {
|
||||||
nodes: RecursiveMemoryLayoutNode[];
|
nodes: RecursiveMemoryLayoutNode[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unindexedProject = new lc.NotificationType<UnindexedProjectParams>(
|
|
||||||
"rust-analyzer/unindexedProject",
|
|
||||||
);
|
|
||||||
|
|
||||||
export type UnindexedProjectParams = { textDocuments: lc.TextDocumentIdentifier[] };
|
|
||||||
|
|
|
@ -6,16 +6,12 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx";
|
||||||
import * as diagnostics from "./diagnostics";
|
import * as diagnostics from "./diagnostics";
|
||||||
import { activateTaskProvider } from "./tasks";
|
import { activateTaskProvider } from "./tasks";
|
||||||
import { setContextValue } from "./util";
|
import { setContextValue } from "./util";
|
||||||
import type { JsonProject } from "./rust_project";
|
|
||||||
|
|
||||||
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
||||||
|
|
||||||
// This API is not stable and may break in between minor releases.
|
|
||||||
export interface RustAnalyzerExtensionApi {
|
export interface RustAnalyzerExtensionApi {
|
||||||
|
// FIXME: this should be non-optional
|
||||||
readonly client?: lc.LanguageClient;
|
readonly client?: lc.LanguageClient;
|
||||||
|
|
||||||
setWorkspaces(workspaces: JsonProject[]): void;
|
|
||||||
notifyRustAnalyzer(): Promise<void>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deactivate() {
|
export async function deactivate() {
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
export interface JsonProject {
|
|
||||||
/// Path to the sysroot directory.
|
|
||||||
///
|
|
||||||
/// The sysroot is where rustc looks for the
|
|
||||||
/// crates that are built-in to rust, such as
|
|
||||||
/// std.
|
|
||||||
///
|
|
||||||
/// https://doc.rust-lang.org/rustc/command-line-arguments.html#--sysroot-override-the-system-root
|
|
||||||
///
|
|
||||||
/// To see the current value of sysroot, you
|
|
||||||
/// can query rustc:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// $ rustc --print sysroot
|
|
||||||
/// /Users/yourname/.rustup/toolchains/stable-x86_64-apple-darwin
|
|
||||||
/// ```
|
|
||||||
sysroot?: string;
|
|
||||||
/// Path to the directory with *source code* of
|
|
||||||
/// sysroot crates.
|
|
||||||
///
|
|
||||||
/// By default, this is `lib/rustlib/src/rust/library`
|
|
||||||
/// relative to the sysroot.
|
|
||||||
///
|
|
||||||
/// It should point to the directory where std,
|
|
||||||
/// core, and friends can be found:
|
|
||||||
///
|
|
||||||
/// https://github.com/rust-lang/rust/tree/master/library.
|
|
||||||
///
|
|
||||||
/// If provided, rust-analyzer automatically adds
|
|
||||||
/// dependencies on sysroot crates. Conversely,
|
|
||||||
/// if you omit this path, you can specify sysroot
|
|
||||||
/// dependencies yourself and, for example, have
|
|
||||||
/// several different "sysroots" in one graph of
|
|
||||||
/// crates.
|
|
||||||
sysroot_src?: string;
|
|
||||||
/// The set of crates comprising the current
|
|
||||||
/// project. Must include all transitive
|
|
||||||
/// dependencies as well as sysroot crate (libstd,
|
|
||||||
/// libcore and such).
|
|
||||||
crates: Crate[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Crate {
|
|
||||||
/// Optional crate name used for display purposes,
|
|
||||||
/// without affecting semantics. See the `deps`
|
|
||||||
/// key for semantically-significant crate names.
|
|
||||||
display_name?: string;
|
|
||||||
/// Path to the root module of the crate.
|
|
||||||
root_module: string;
|
|
||||||
/// Edition of the crate.
|
|
||||||
edition: "2015" | "2018" | "2021";
|
|
||||||
/// Dependencies
|
|
||||||
deps: Dep[];
|
|
||||||
/// Should this crate be treated as a member of
|
|
||||||
/// current "workspace".
|
|
||||||
///
|
|
||||||
/// By default, inferred from the `root_module`
|
|
||||||
/// (members are the crates which reside inside
|
|
||||||
/// the directory opened in the editor).
|
|
||||||
///
|
|
||||||
/// Set this to `false` for things like standard
|
|
||||||
/// library and 3rd party crates to enable
|
|
||||||
/// performance optimizations (rust-analyzer
|
|
||||||
/// assumes that non-member crates don't change).
|
|
||||||
is_workspace_member?: boolean;
|
|
||||||
/// Optionally specify the (super)set of `.rs`
|
|
||||||
/// files comprising this crate.
|
|
||||||
///
|
|
||||||
/// By default, rust-analyzer assumes that only
|
|
||||||
/// files under `root_module.parent` can belong
|
|
||||||
/// to a crate. `include_dirs` are included
|
|
||||||
/// recursively, unless a subdirectory is in
|
|
||||||
/// `exclude_dirs`.
|
|
||||||
///
|
|
||||||
/// Different crates can share the same `source`.
|
|
||||||
///
|
|
||||||
/// If two crates share an `.rs` file in common,
|
|
||||||
/// they *must* have the same `source`.
|
|
||||||
/// rust-analyzer assumes that files from one
|
|
||||||
/// source can't refer to files in another source.
|
|
||||||
source?: {
|
|
||||||
include_dirs: string[];
|
|
||||||
exclude_dirs: string[];
|
|
||||||
};
|
|
||||||
/// The set of cfgs activated for a given crate, like
|
|
||||||
/// `["unix", "feature=\"foo\"", "feature=\"bar\""]`.
|
|
||||||
cfg: string[];
|
|
||||||
/// Target triple for this Crate.
|
|
||||||
///
|
|
||||||
/// Used when running `rustc --print cfg`
|
|
||||||
/// to get target-specific cfgs.
|
|
||||||
target?: string;
|
|
||||||
/// Environment variables, used for
|
|
||||||
/// the `env!` macro
|
|
||||||
env: { [key: string]: string };
|
|
||||||
|
|
||||||
/// Whether the crate is a proc-macro crate.
|
|
||||||
is_proc_macro: boolean;
|
|
||||||
/// For proc-macro crates, path to compiled
|
|
||||||
/// proc-macro (.so file).
|
|
||||||
proc_macro_dylib_path?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Dep {
|
|
||||||
/// Index of a crate in the `crates` array.
|
|
||||||
crate: number;
|
|
||||||
/// Name as should appear in the (implicit)
|
|
||||||
/// `extern crate name` declaration.
|
|
||||||
name: string;
|
|
||||||
}
|
|
Loading…
Reference in a new issue