Skip to content

Commit 3fc7101

Browse files
committed
Fix config guard lock for ratoml tests
1 parent afdf4c8 commit 3fc7101

File tree

6 files changed

+59
-63
lines changed

6 files changed

+59
-63
lines changed

src/tools/rust-analyzer/crates/load-cargo/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ impl ProjectFolders {
156156
pub fn new(
157157
workspaces: &[ProjectWorkspace],
158158
global_excludes: &[AbsPathBuf],
159-
user_config_dir_path: Option<&'static AbsPath>,
159+
user_config_dir_path: Option<&AbsPath>,
160160
) -> ProjectFolders {
161161
let mut res = ProjectFolders::default();
162162
let mut fsc = FileSetConfig::builder();
@@ -302,7 +302,7 @@ impl ProjectFolders {
302302
p
303303
};
304304

305-
let file_set_roots: Vec<VfsPath> = vec![VfsPath::from(ratoml_path.to_owned())];
305+
let file_set_roots = vec![VfsPath::from(ratoml_path.to_owned())];
306306
let entry = vfs::loader::Entry::Files(vec![ratoml_path.to_owned()]);
307307

308308
res.watch.push(res.load.len());

src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,7 @@
33
//! Of particular interest is the `feature_flags` hash map: while other fields
44
//! configure the server itself, feature flags are passed into analysis, and
55
//! tweak things like automatic insertion of `()` in completions.
6-
use std::{
7-
env, fmt, iter,
8-
ops::Not,
9-
sync::{LazyLock, OnceLock},
10-
};
6+
use std::{env, fmt, iter, ops::Not, sync::OnceLock};
117

128
use cfg::{CfgAtom, CfgDiff};
139
use hir::Symbol;
@@ -805,16 +801,13 @@ impl std::ops::Deref for Config {
805801

806802
impl Config {
807803
/// Path to the user configuration dir. This can be seen as a generic way to define what would be `$XDG_CONFIG_HOME/rust-analyzer` in Linux.
808-
pub fn user_config_dir_path() -> Option<&'static AbsPath> {
809-
static USER_CONFIG_PATH: LazyLock<Option<AbsPathBuf>> = LazyLock::new(|| {
810-
let user_config_path = if let Some(path) = env::var_os("__TEST_RA_USER_CONFIG_DIR") {
811-
std::path::PathBuf::from(path)
812-
} else {
813-
dirs::config_dir()?.join("rust-analyzer")
814-
};
815-
Some(AbsPathBuf::assert_utf8(user_config_path))
816-
});
817-
USER_CONFIG_PATH.as_deref()
804+
pub fn user_config_dir_path() -> Option<AbsPathBuf> {
805+
let user_config_path = if let Some(path) = env::var_os("__TEST_RA_USER_CONFIG_DIR") {
806+
std::path::PathBuf::from(path)
807+
} else {
808+
dirs::config_dir()?.join("rust-analyzer")
809+
};
810+
Some(AbsPathBuf::assert_utf8(user_config_path))
818811
}
819812

820813
pub fn same_source_root_parent_map(
@@ -1254,7 +1247,7 @@ pub struct NotificationsConfig {
12541247
pub cargo_toml_not_found: bool,
12551248
}
12561249

1257-
#[derive(Deserialize, Serialize, Debug, Clone)]
1250+
#[derive(Debug, Clone)]
12581251
pub enum RustfmtConfig {
12591252
Rustfmt { extra_args: Vec<String>, enable_range_formatting: bool },
12601253
CustomCommand { command: String, args: Vec<String> },

src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,13 +392,13 @@ impl GlobalState {
392392
|| !self.config.same_source_root_parent_map(&self.local_roots_parent_map)
393393
{
394394
let config_change = {
395-
let user_config_path = {
396-
let mut p = Config::user_config_dir_path().unwrap().to_path_buf();
395+
let user_config_path = (|| {
396+
let mut p = Config::user_config_dir_path()?;
397397
p.push("rust-analyzer.toml");
398-
p
399-
};
398+
Some(p)
399+
})();
400400

401-
let user_config_abs_path = Some(user_config_path.as_path());
401+
let user_config_abs_path = user_config_path.as_deref();
402402

403403
let mut change = ConfigChange::default();
404404
let db = self.analysis_host.raw_database();

src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ impl GlobalState {
590590
}
591591

592592
watchers.extend(
593-
iter::once(Config::user_config_dir_path())
593+
iter::once(Config::user_config_dir_path().as_deref())
594594
.chain(self.workspaces.iter().map(|ws| ws.manifest().map(ManifestPath::as_ref)))
595595
.flatten()
596596
.map(|glob_pattern| lsp_types::FileSystemWatcher {
@@ -616,7 +616,7 @@ impl GlobalState {
616616
let project_folders = ProjectFolders::new(
617617
&self.workspaces,
618618
&files_config.exclude,
619-
Config::user_config_dir_path().to_owned(),
619+
Config::user_config_dir_path().as_deref(),
620620
);
621621

622622
if (self.proc_macro_clients.is_empty() || !same_workspaces)

src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/ratoml.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,6 @@ impl RatomlTest {
3030
fixtures: Vec<&str>,
3131
roots: Vec<&str>,
3232
client_config: Option<serde_json::Value>,
33-
) -> Self {
34-
RatomlTest::new_with_lock(fixtures, roots, client_config, false)
35-
}
36-
37-
fn new_locked(
38-
fixtures: Vec<&str>,
39-
roots: Vec<&str>,
40-
client_config: Option<serde_json::Value>,
41-
) -> Self {
42-
RatomlTest::new_with_lock(fixtures, roots, client_config, true)
43-
}
44-
45-
fn new_with_lock(
46-
fixtures: Vec<&str>,
47-
roots: Vec<&str>,
48-
client_config: Option<serde_json::Value>,
49-
prelock: bool,
5033
) -> Self {
5134
let tmp_dir = TestDir::new();
5235
let tmp_path = tmp_dir.path().to_owned();
@@ -63,7 +46,7 @@ impl RatomlTest {
6346
project = project.with_config(client_config);
6447
}
6548

66-
let server = project.server_with_lock(prelock).wait_until_workspace_is_loaded();
49+
let server = project.server_with_lock(true).wait_until_workspace_is_loaded();
6750

6851
let mut case = Self { urls: vec![], server, tmp_path };
6952
let urls = fixtures.iter().map(|fixture| case.fixture_path(fixture)).collect::<Vec<_>>();
@@ -89,7 +72,7 @@ impl RatomlTest {
8972
let mut spl = spl.into_iter();
9073
if let Some(first) = spl.next() {
9174
if first == "$$CONFIG_DIR$$" {
92-
path = Config::user_config_dir_path().unwrap().to_path_buf().into();
75+
path = Config::user_config_dir_path().unwrap().into();
9376
} else {
9477
path = path.join(first);
9578
}
@@ -307,7 +290,7 @@ fn ratoml_user_config_detected() {
307290
return;
308291
}
309292

310-
let server = RatomlTest::new_locked(
293+
let server = RatomlTest::new(
311294
vec![
312295
r#"
313296
//- /$$CONFIG_DIR$$/rust-analyzer.toml
@@ -343,7 +326,7 @@ fn ratoml_create_user_config() {
343326
return;
344327
}
345328

346-
let mut server = RatomlTest::new_locked(
329+
let mut server = RatomlTest::new(
347330
vec![
348331
r#"
349332
//- /p1/Cargo.toml
@@ -382,7 +365,7 @@ fn ratoml_modify_user_config() {
382365
return;
383366
}
384367

385-
let mut server = RatomlTest::new_locked(
368+
let mut server = RatomlTest::new(
386369
vec![
387370
r#"
388371
//- /p1/Cargo.toml
@@ -423,7 +406,7 @@ fn ratoml_delete_user_config() {
423406
return;
424407
}
425408

426-
let mut server = RatomlTest::new_locked(
409+
let mut server = RatomlTest::new(
427410
vec![
428411
r#"
429412
//- /p1/Cargo.toml

src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
cell::{Cell, RefCell},
33
env, fs,
4-
sync::Once,
4+
sync::{Once, OnceLock},
55
time::Duration,
66
};
77

@@ -140,13 +140,36 @@ impl Project<'_> {
140140
/// if there is a path to config dir in the test fixture. However, in certain cases we create a
141141
/// file in the config dir after server is run, something where our naive approach comes short.
142142
/// Using a `prelock` allows us to force a lock when we know we need it.
143-
pub(crate) fn server_with_lock(self, prelock: bool) -> Server {
144-
static CONFIG_DIR_LOCK: Mutex<()> = Mutex::new(());
145-
146-
let mut config_dir_guard = if prelock {
147-
let v = Some(CONFIG_DIR_LOCK.lock());
148-
env::set_var("__TEST_RA_USER_CONFIG_DIR", TestDir::new().path());
149-
v
143+
pub(crate) fn server_with_lock(self, config_lock: bool) -> Server {
144+
static CONFIG_DIR_LOCK: OnceLock<(Utf8PathBuf, Mutex<()>)> = OnceLock::new();
145+
146+
let config_dir_guard = if config_lock {
147+
Some({
148+
let (path, mutex) = CONFIG_DIR_LOCK.get_or_init(|| {
149+
let value = TestDir::new().keep().path().to_owned();
150+
env::set_var("__TEST_RA_USER_CONFIG_DIR", &value);
151+
(value, Mutex::new(()))
152+
});
153+
#[allow(dyn_drop)]
154+
(mutex.lock(), {
155+
Box::new({
156+
struct Dropper(Utf8PathBuf);
157+
impl Drop for Dropper {
158+
fn drop(&mut self) {
159+
for entry in fs::read_dir(&self.0).unwrap() {
160+
let path = entry.unwrap().path();
161+
if path.is_file() {
162+
fs::remove_file(path).unwrap();
163+
} else if path.is_dir() {
164+
fs::remove_dir_all(path).unwrap();
165+
}
166+
}
167+
}
168+
}
169+
Dropper(path.clone())
170+
}) as Box<dyn Drop>
171+
})
172+
})
150173
} else {
151174
None
152175
};
@@ -185,11 +208,6 @@ impl Project<'_> {
185208

186209
for entry in fixture {
187210
if let Some(pth) = entry.path.strip_prefix("/$$CONFIG_DIR$$") {
188-
if config_dir_guard.is_none() {
189-
config_dir_guard = Some(CONFIG_DIR_LOCK.lock());
190-
env::set_var("__TEST_RA_USER_CONFIG_DIR", TestDir::new().path());
191-
}
192-
193211
let path = Config::user_config_dir_path().unwrap().join(&pth['/'.len_utf8()..]);
194212
fs::create_dir_all(path.parent().unwrap()).unwrap();
195213
fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
@@ -293,12 +311,14 @@ pub(crate) struct Server {
293311
client: Connection,
294312
/// XXX: remove the tempdir last
295313
dir: TestDir,
296-
_config_dir_guard: Option<MutexGuard<'static, ()>>,
314+
#[allow(dyn_drop)]
315+
_config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>,
297316
}
298317

299318
impl Server {
319+
#[allow(dyn_drop)]
300320
fn new(
301-
config_dir_guard: Option<MutexGuard<'static, ()>>,
321+
config_dir_guard: Option<(MutexGuard<'static, ()>, Box<dyn Drop>)>,
302322
dir: TestDir,
303323
config: Config,
304324
) -> Server {

0 commit comments

Comments
 (0)