Skip to content

Commit fc8cfb2

Browse files
committed
Auto merge of #14689 - Veykril:patch-vscode-paths, r=Veykril
fix: Force InitializeParams windows path drives to uppercase Should fix #14683 cc `@jyn514`
2 parents 83cc5ef + 140e1d7 commit fc8cfb2

File tree

3 files changed

+70
-15
lines changed

3 files changed

+70
-15
lines changed

crates/base-db/src/lib.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,21 @@ pub trait SourceDatabase: FileLoader + std::fmt::Debug {
7171
fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
7272

7373
/// The crate graph.
74-
#[salsa::input]
7574
fn crate_graph(&self) -> Arc<CrateGraph>;
75+
fn proc_macros(&self) -> Arc<ProcMacros>;
7676

77-
/// The crate graph.
7877
#[salsa::input]
79-
fn proc_macros(&self) -> Arc<ProcMacros>;
78+
fn ws_crate_graph(&self, ws: WorkspaceId) -> Arc<CrateGraph>;
79+
80+
#[salsa::input]
81+
fn ws_proc_macros(&self, ws: WorkspaceId) -> Arc<ProcMacros>;
8082
}
8183

84+
// we want to split the crate graph into per_ws_crate_graph, but still somehow share crates that
85+
// are the same with ids and the like such that we can dedupe work?
86+
87+
pub struct WorkspaceId(u32);
88+
8289
fn parse_query(db: &dyn SourceDatabase, file_id: FileId) -> Parse<ast::SourceFile> {
8390
let _p = profile::span("parse_query").detail(|| format!("{file_id:?}"));
8491
let text = db.file_text(file_id);

crates/hir-ty/src/mir/eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! This module provides a MIR interpreter, which is used in const eval.
22
3-
use std::{borrow::Cow, collections::HashMap, iter, ops::Range, sync::Arc};
3+
use std::{borrow::Cow, iter, ops::Range, sync::Arc};
44

55
use base_db::CrateId;
66
use chalk_ir::{

crates/rust-analyzer/src/bin/main.rs

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
mod logger;
88
mod rustc_wrapper;
99

10-
use std::{env, fs, path::Path, process};
10+
use std::{
11+
env, fs,
12+
path::{Path, PathBuf},
13+
process,
14+
};
1115

1216
use lsp_server::Connection;
1317
use rust_analyzer::{cli::flags, config::Config, from_json, Result};
@@ -149,12 +153,18 @@ fn run_server() -> Result<()> {
149153

150154
let (initialize_id, initialize_params) = connection.initialize_start()?;
151155
tracing::info!("InitializeParams: {}", initialize_params);
152-
let initialize_params =
153-
from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;
154-
155-
let root_path = match initialize_params
156-
.root_uri
156+
let lsp_types::InitializeParams {
157+
root_uri,
158+
capabilities,
159+
workspace_folders,
160+
initialization_options,
161+
client_info,
162+
..
163+
} = from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;
164+
165+
let root_path = match root_uri
157166
.and_then(|it| it.to_file_path().ok())
167+
.map(patch_path_prefix)
158168
.and_then(|it| AbsPathBuf::try_from(it).ok())
159169
{
160170
Some(it) => it,
@@ -164,19 +174,19 @@ fn run_server() -> Result<()> {
164174
}
165175
};
166176

167-
let workspace_roots = initialize_params
168-
.workspace_folders
177+
let workspace_roots = workspace_folders
169178
.map(|workspaces| {
170179
workspaces
171180
.into_iter()
172181
.filter_map(|it| it.uri.to_file_path().ok())
182+
.map(patch_path_prefix)
173183
.filter_map(|it| AbsPathBuf::try_from(it).ok())
174184
.collect::<Vec<_>>()
175185
})
176186
.filter(|workspaces| !workspaces.is_empty())
177187
.unwrap_or_else(|| vec![root_path.clone()]);
178-
let mut config = Config::new(root_path, initialize_params.capabilities, workspace_roots);
179-
if let Some(json) = initialize_params.initialization_options {
188+
let mut config = Config::new(root_path, capabilities, workspace_roots);
189+
if let Some(json) = initialization_options {
180190
if let Err(e) = config.update(json) {
181191
use lsp_types::{
182192
notification::{Notification, ShowMessage},
@@ -205,7 +215,7 @@ fn run_server() -> Result<()> {
205215

206216
connection.initialize_finish(initialize_id, initialize_result)?;
207217

208-
if let Some(client_info) = initialize_params.client_info {
218+
if let Some(client_info) = client_info {
209219
tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
210220
}
211221

@@ -219,3 +229,41 @@ fn run_server() -> Result<()> {
219229
tracing::info!("server did shut down");
220230
Ok(())
221231
}
232+
233+
fn patch_path_prefix(path: PathBuf) -> PathBuf {
234+
use std::path::{Component, Prefix};
235+
if cfg!(windows) || cfg!(test) {
236+
// VSCode might report paths with the file drive in lowercase, but this can mess
237+
// with env vars set by tools and build scripts executed by r-a such that it invalidates
238+
// cargo's compilations unnecessarily. https://github.com/rust-lang/rust-analyzer/issues/14683
239+
// So we just uppercase the drive letter here unconditionally.
240+
// (doing it conditionally is a pain because std::path::Prefix always reports uppercase letters on windows)
241+
let mut comps = path.components();
242+
match comps.next() {
243+
Some(Component::Prefix(prefix)) => {
244+
let prefix = match prefix.kind() {
245+
Prefix::Disk(d) => {
246+
format!("{}:", d.to_ascii_uppercase() as char)
247+
}
248+
Prefix::VerbatimDisk(d) => {
249+
format!(r"\\?\{}:\", d.to_ascii_uppercase() as char)
250+
}
251+
_ => return path,
252+
};
253+
let mut path = PathBuf::new();
254+
path.push(prefix);
255+
path.extend(comps);
256+
path
257+
}
258+
_ => path,
259+
}
260+
} else {
261+
path
262+
}
263+
}
264+
265+
#[test]
266+
fn patch_path_prefix_works() {
267+
assert_eq!(patch_path_prefix(r"c:\foo\bar".into()), PathBuf::from(r"C:\foo\bar"));
268+
assert_eq!(patch_path_prefix(r"\\?\c:\foo\bar".into()), PathBuf::from(r"\\?\C:\foo\bar"));
269+
}

0 commit comments

Comments
 (0)