diff options
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 42 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/main.rs | 41 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/load_cargo.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 25 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 31 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/support.rs | 31 |
6 files changed, 110 insertions, 65 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 9b30bef8d..a99612690 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -14,7 +14,7 @@ use std::{ | |||
14 | use anyhow::{bail, Context, Result}; | 14 | use anyhow::{bail, Context, Result}; |
15 | use ra_cfg::CfgOptions; | 15 | use ra_cfg::CfgOptions; |
16 | use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId}; | 16 | use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId}; |
17 | use rustc_hash::FxHashMap; | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
18 | use serde_json::from_reader; | 18 | use serde_json::from_reader; |
19 | 19 | ||
20 | pub use crate::{ | 20 | pub use crate::{ |
@@ -57,25 +57,25 @@ impl PackageRoot { | |||
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 60 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] |
61 | pub enum ProjectRoot { | 61 | pub enum ProjectManifest { |
62 | ProjectJson(PathBuf), | 62 | ProjectJson(PathBuf), |
63 | CargoToml(PathBuf), | 63 | CargoToml(PathBuf), |
64 | } | 64 | } |
65 | 65 | ||
66 | impl ProjectRoot { | 66 | impl ProjectManifest { |
67 | pub fn from_manifest_file(path: PathBuf) -> Result<ProjectRoot> { | 67 | pub fn from_manifest_file(path: PathBuf) -> Result<ProjectManifest> { |
68 | if path.ends_with("rust-project.json") { | 68 | if path.ends_with("rust-project.json") { |
69 | return Ok(ProjectRoot::ProjectJson(path)); | 69 | return Ok(ProjectManifest::ProjectJson(path)); |
70 | } | 70 | } |
71 | if path.ends_with("Cargo.toml") { | 71 | if path.ends_with("Cargo.toml") { |
72 | return Ok(ProjectRoot::CargoToml(path)); | 72 | return Ok(ProjectManifest::CargoToml(path)); |
73 | } | 73 | } |
74 | bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()) | 74 | bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display()) |
75 | } | 75 | } |
76 | 76 | ||
77 | pub fn discover_single(path: &Path) -> Result<ProjectRoot> { | 77 | pub fn discover_single(path: &Path) -> Result<ProjectManifest> { |
78 | let mut candidates = ProjectRoot::discover(path)?; | 78 | let mut candidates = ProjectManifest::discover(path)?; |
79 | let res = match candidates.pop() { | 79 | let res = match candidates.pop() { |
80 | None => bail!("no projects"), | 80 | None => bail!("no projects"), |
81 | Some(it) => it, | 81 | Some(it) => it, |
@@ -87,12 +87,12 @@ impl ProjectRoot { | |||
87 | Ok(res) | 87 | Ok(res) |
88 | } | 88 | } |
89 | 89 | ||
90 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> { | 90 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectManifest>> { |
91 | if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") { | 91 | if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") { |
92 | return Ok(vec![ProjectRoot::ProjectJson(project_json)]); | 92 | return Ok(vec![ProjectManifest::ProjectJson(project_json)]); |
93 | } | 93 | } |
94 | return find_cargo_toml(path) | 94 | return find_cargo_toml(path) |
95 | .map(|paths| paths.into_iter().map(ProjectRoot::CargoToml).collect()); | 95 | .map(|paths| paths.into_iter().map(ProjectManifest::CargoToml).collect()); |
96 | 96 | ||
97 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { | 97 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { |
98 | match find_in_parent_dirs(path, "Cargo.toml") { | 98 | match find_in_parent_dirs(path, "Cargo.toml") { |
@@ -128,16 +128,28 @@ impl ProjectRoot { | |||
128 | .collect() | 128 | .collect() |
129 | } | 129 | } |
130 | } | 130 | } |
131 | |||
132 | pub fn discover_all(paths: &[impl AsRef<Path>]) -> Vec<ProjectManifest> { | ||
133 | let mut res = paths | ||
134 | .iter() | ||
135 | .filter_map(|it| ProjectManifest::discover(it.as_ref()).ok()) | ||
136 | .flatten() | ||
137 | .collect::<FxHashSet<_>>() | ||
138 | .into_iter() | ||
139 | .collect::<Vec<_>>(); | ||
140 | res.sort(); | ||
141 | res | ||
142 | } | ||
131 | } | 143 | } |
132 | 144 | ||
133 | impl ProjectWorkspace { | 145 | impl ProjectWorkspace { |
134 | pub fn load( | 146 | pub fn load( |
135 | root: ProjectRoot, | 147 | root: ProjectManifest, |
136 | cargo_features: &CargoConfig, | 148 | cargo_features: &CargoConfig, |
137 | with_sysroot: bool, | 149 | with_sysroot: bool, |
138 | ) -> Result<ProjectWorkspace> { | 150 | ) -> Result<ProjectWorkspace> { |
139 | let res = match root { | 151 | let res = match root { |
140 | ProjectRoot::ProjectJson(project_json) => { | 152 | ProjectManifest::ProjectJson(project_json) => { |
141 | let file = File::open(&project_json).with_context(|| { | 153 | let file = File::open(&project_json).with_context(|| { |
142 | format!("Failed to open json file {}", project_json.display()) | 154 | format!("Failed to open json file {}", project_json.display()) |
143 | })?; | 155 | })?; |
@@ -148,7 +160,7 @@ impl ProjectWorkspace { | |||
148 | })?, | 160 | })?, |
149 | } | 161 | } |
150 | } | 162 | } |
151 | ProjectRoot::CargoToml(cargo_toml) => { | 163 | ProjectManifest::CargoToml(cargo_toml) => { |
152 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) | 164 | let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features) |
153 | .with_context(|| { | 165 | .with_context(|| { |
154 | format!( | 166 | format!( |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index e82fd57de..8d071ab1c 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -4,9 +4,14 @@ | |||
4 | mod args; | 4 | mod args; |
5 | 5 | ||
6 | use lsp_server::Connection; | 6 | use lsp_server::Connection; |
7 | use rust_analyzer::{cli, config::Config, from_json, Result}; | 7 | use rust_analyzer::{ |
8 | cli, | ||
9 | config::{Config, LinkedProject}, | ||
10 | from_json, Result, | ||
11 | }; | ||
8 | 12 | ||
9 | use crate::args::HelpPrinted; | 13 | use crate::args::HelpPrinted; |
14 | use ra_project_model::ProjectManifest; | ||
10 | 15 | ||
11 | fn main() -> Result<()> { | 16 | fn main() -> Result<()> { |
12 | setup_logging()?; | 17 | setup_logging()?; |
@@ -97,17 +102,6 @@ fn run_server() -> Result<()> { | |||
97 | log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); | 102 | log::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default()); |
98 | } | 103 | } |
99 | 104 | ||
100 | let cwd = std::env::current_dir()?; | ||
101 | let root = initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); | ||
102 | |||
103 | let workspace_roots = initialize_params | ||
104 | .workspace_folders | ||
105 | .map(|workspaces| { | ||
106 | workspaces.into_iter().filter_map(|it| it.uri.to_file_path().ok()).collect::<Vec<_>>() | ||
107 | }) | ||
108 | .filter(|workspaces| !workspaces.is_empty()) | ||
109 | .unwrap_or_else(|| vec![root]); | ||
110 | |||
111 | let config = { | 105 | let config = { |
112 | let mut config = Config::default(); | 106 | let mut config = Config::default(); |
113 | if let Some(value) = &initialize_params.initialization_options { | 107 | if let Some(value) = &initialize_params.initialization_options { |
@@ -115,10 +109,31 @@ fn run_server() -> Result<()> { | |||
115 | } | 109 | } |
116 | config.update_caps(&initialize_params.capabilities); | 110 | config.update_caps(&initialize_params.capabilities); |
117 | 111 | ||
112 | if config.linked_projects.is_empty() { | ||
113 | let cwd = std::env::current_dir()?; | ||
114 | let root = | ||
115 | initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd); | ||
116 | let workspace_roots = initialize_params | ||
117 | .workspace_folders | ||
118 | .map(|workspaces| { | ||
119 | workspaces | ||
120 | .into_iter() | ||
121 | .filter_map(|it| it.uri.to_file_path().ok()) | ||
122 | .collect::<Vec<_>>() | ||
123 | }) | ||
124 | .filter(|workspaces| !workspaces.is_empty()) | ||
125 | .unwrap_or_else(|| vec![root]); | ||
126 | |||
127 | config.linked_projects = ProjectManifest::discover_all(&workspace_roots) | ||
128 | .into_iter() | ||
129 | .map(LinkedProject::from) | ||
130 | .collect(); | ||
131 | } | ||
132 | |||
118 | config | 133 | config |
119 | }; | 134 | }; |
120 | 135 | ||
121 | rust_analyzer::main_loop(workspace_roots, config, connection)?; | 136 | rust_analyzer::main_loop(config, connection)?; |
122 | 137 | ||
123 | log::info!("shutting down IO..."); | 138 | log::info!("shutting down IO..."); |
124 | io_threads.join()?; | 139 | io_threads.join()?; |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 8eaf75ff6..c7e86fe0c 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -8,7 +8,8 @@ use crossbeam_channel::{unbounded, Receiver}; | |||
8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; | 8 | use ra_db::{ExternSourceId, FileId, SourceRootId}; |
9 | use ra_ide::{AnalysisChange, AnalysisHost}; | 9 | use ra_ide::{AnalysisChange, AnalysisHost}; |
10 | use ra_project_model::{ | 10 | use ra_project_model::{ |
11 | get_rustc_cfg_options, CargoConfig, PackageRoot, ProcMacroClient, ProjectRoot, ProjectWorkspace, | 11 | get_rustc_cfg_options, CargoConfig, PackageRoot, ProcMacroClient, ProjectManifest, |
12 | ProjectWorkspace, | ||
12 | }; | 13 | }; |
13 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; | 14 | use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; |
14 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -28,7 +29,7 @@ pub fn load_cargo( | |||
28 | with_proc_macro: bool, | 29 | with_proc_macro: bool, |
29 | ) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { | 30 | ) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> { |
30 | let root = std::env::current_dir()?.join(root); | 31 | let root = std::env::current_dir()?.join(root); |
31 | let root = ProjectRoot::discover_single(&root)?; | 32 | let root = ProjectManifest::discover_single(&root)?; |
32 | let ws = ProjectWorkspace::load( | 33 | let ws = ProjectWorkspace::load( |
33 | root, | 34 | root, |
34 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, | 35 | &CargoConfig { load_out_dirs_from_check, ..Default::default() }, |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 9c6e369d2..761bc9c2d 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -12,14 +12,13 @@ use std::{ffi::OsString, path::PathBuf}; | |||
12 | use lsp_types::ClientCapabilities; | 12 | use lsp_types::ClientCapabilities; |
13 | use ra_flycheck::FlycheckConfig; | 13 | use ra_flycheck::FlycheckConfig; |
14 | use ra_ide::{AssistConfig, CompletionConfig, InlayHintsConfig}; | 14 | use ra_ide::{AssistConfig, CompletionConfig, InlayHintsConfig}; |
15 | use ra_project_model::CargoConfig; | 15 | use ra_project_model::{CargoConfig, JsonProject, ProjectManifest}; |
16 | use serde::Deserialize; | 16 | use serde::Deserialize; |
17 | 17 | ||
18 | #[derive(Debug, Clone)] | 18 | #[derive(Debug, Clone)] |
19 | pub struct Config { | 19 | pub struct Config { |
20 | pub client_caps: ClientCapsConfig, | 20 | pub client_caps: ClientCapsConfig, |
21 | 21 | ||
22 | pub with_sysroot: bool, | ||
23 | pub publish_diagnostics: bool, | 22 | pub publish_diagnostics: bool, |
24 | pub lru_capacity: Option<usize>, | 23 | pub lru_capacity: Option<usize>, |
25 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, | 24 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, |
@@ -35,6 +34,27 @@ pub struct Config { | |||
35 | pub assist: AssistConfig, | 34 | pub assist: AssistConfig, |
36 | pub call_info_full: bool, | 35 | pub call_info_full: bool, |
37 | pub lens: LensConfig, | 36 | pub lens: LensConfig, |
37 | |||
38 | pub with_sysroot: bool, | ||
39 | pub linked_projects: Vec<LinkedProject>, | ||
40 | } | ||
41 | |||
42 | #[derive(Debug, Clone)] | ||
43 | pub enum LinkedProject { | ||
44 | ProjectManifest(ProjectManifest), | ||
45 | JsonProject(JsonProject), | ||
46 | } | ||
47 | |||
48 | impl From<ProjectManifest> for LinkedProject { | ||
49 | fn from(v: ProjectManifest) -> Self { | ||
50 | LinkedProject::ProjectManifest(v) | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl From<JsonProject> for LinkedProject { | ||
55 | fn from(v: JsonProject) -> Self { | ||
56 | LinkedProject::JsonProject(v) | ||
57 | } | ||
38 | } | 58 | } |
39 | 59 | ||
40 | #[derive(Clone, Debug, PartialEq, Eq)] | 60 | #[derive(Clone, Debug, PartialEq, Eq)] |
@@ -141,6 +161,7 @@ impl Default for Config { | |||
141 | assist: AssistConfig::default(), | 161 | assist: AssistConfig::default(), |
142 | call_info_full: true, | 162 | call_info_full: true, |
143 | lens: LensConfig::default(), | 163 | lens: LensConfig::default(), |
164 | linked_projects: Vec::new(), | ||
144 | } | 165 | } |
145 | } | 166 | } |
146 | } | 167 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 35f2d7001..d901f21d7 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -12,13 +12,11 @@ use std::{ | |||
12 | fmt, | 12 | fmt, |
13 | ops::Range, | 13 | ops::Range, |
14 | panic, | 14 | panic, |
15 | path::PathBuf, | ||
16 | sync::Arc, | 15 | sync::Arc, |
17 | time::{Duration, Instant}, | 16 | time::{Duration, Instant}, |
18 | }; | 17 | }; |
19 | 18 | ||
20 | use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; | 19 | use crossbeam_channel::{never, select, unbounded, RecvError, Sender}; |
21 | use itertools::Itertools; | ||
22 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; | 20 | use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; |
23 | use lsp_types::{ | 21 | use lsp_types::{ |
24 | DidChangeTextDocumentParams, NumberOrString, TextDocumentContentChangeEvent, WorkDoneProgress, | 22 | DidChangeTextDocumentParams, NumberOrString, TextDocumentContentChangeEvent, WorkDoneProgress, |
@@ -36,7 +34,7 @@ use serde::{de::DeserializeOwned, Serialize}; | |||
36 | use threadpool::ThreadPool; | 34 | use threadpool::ThreadPool; |
37 | 35 | ||
38 | use crate::{ | 36 | use crate::{ |
39 | config::{Config, FilesWatcher}, | 37 | config::{Config, FilesWatcher, LinkedProject}, |
40 | diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask}, | 38 | diagnostics::{to_proto::url_from_path_with_drive_lowercasing, DiagnosticTask}, |
41 | from_proto, | 39 | from_proto, |
42 | global_state::{GlobalState, GlobalStateSnapshot}, | 40 | global_state::{GlobalState, GlobalStateSnapshot}, |
@@ -70,7 +68,7 @@ impl fmt::Display for LspError { | |||
70 | 68 | ||
71 | impl Error for LspError {} | 69 | impl Error for LspError {} |
72 | 70 | ||
73 | pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) -> Result<()> { | 71 | pub fn main_loop(config: Config, connection: Connection) -> Result<()> { |
74 | log::info!("initial config: {:#?}", config); | 72 | log::info!("initial config: {:#?}", config); |
75 | 73 | ||
76 | // Windows scheduler implements priority boosts: if thread waits for an | 74 | // Windows scheduler implements priority boosts: if thread waits for an |
@@ -95,29 +93,24 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) | |||
95 | let mut loop_state = LoopState::default(); | 93 | let mut loop_state = LoopState::default(); |
96 | let mut global_state = { | 94 | let mut global_state = { |
97 | let workspaces = { | 95 | let workspaces = { |
98 | // FIXME: support dynamic workspace loading. | 96 | if config.linked_projects.is_empty() && config.notifications.cargo_toml_not_found { |
99 | let project_roots: FxHashSet<_> = ws_roots | ||
100 | .iter() | ||
101 | .filter_map(|it| ra_project_model::ProjectRoot::discover(it).ok()) | ||
102 | .flatten() | ||
103 | .collect(); | ||
104 | |||
105 | if project_roots.is_empty() && config.notifications.cargo_toml_not_found { | ||
106 | show_message( | 97 | show_message( |
107 | lsp_types::MessageType::Error, | 98 | lsp_types::MessageType::Error, |
108 | format!( | 99 | "rust-analyzer failed to discover workspace".to_string(), |
109 | "rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: {}", | ||
110 | ws_roots.iter().format_with(", ", |it, f| f(&it.display())) | ||
111 | ), | ||
112 | &connection.sender, | 100 | &connection.sender, |
113 | ); | 101 | ); |
114 | }; | 102 | }; |
115 | 103 | ||
116 | project_roots | 104 | config |
117 | .into_iter() | 105 | .linked_projects |
106 | .iter() | ||
107 | .filter_map(|project| match project { | ||
108 | LinkedProject::ProjectManifest(it) => Some(it), | ||
109 | LinkedProject::JsonProject(_) => None, | ||
110 | }) | ||
118 | .filter_map(|root| { | 111 | .filter_map(|root| { |
119 | ra_project_model::ProjectWorkspace::load( | 112 | ra_project_model::ProjectWorkspace::load( |
120 | root, | 113 | root.clone(), |
121 | &config.cargo, | 114 | &config.cargo, |
122 | config.with_sysroot, | 115 | config.with_sysroot, |
123 | ) | 116 | ) |
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs index 66a6f4d54..30d03b622 100644 --- a/crates/rust-analyzer/tests/heavy_tests/support.rs +++ b/crates/rust-analyzer/tests/heavy_tests/support.rs | |||
@@ -19,8 +19,9 @@ use serde_json::{to_string_pretty, Value}; | |||
19 | use tempfile::TempDir; | 19 | use tempfile::TempDir; |
20 | use test_utils::{find_mismatch, parse_fixture}; | 20 | use test_utils::{find_mismatch, parse_fixture}; |
21 | 21 | ||
22 | use ra_project_model::ProjectManifest; | ||
22 | use rust_analyzer::{ | 23 | use rust_analyzer::{ |
23 | config::{ClientCapsConfig, Config}, | 24 | config::{ClientCapsConfig, Config, LinkedProject}, |
24 | main_loop, | 25 | main_loop, |
25 | }; | 26 | }; |
26 | 27 | ||
@@ -42,7 +43,7 @@ impl<'a> Project<'a> { | |||
42 | self | 43 | self |
43 | } | 44 | } |
44 | 45 | ||
45 | pub fn root(mut self, path: &str) -> Project<'a> { | 46 | pub(crate) fn root(mut self, path: &str) -> Project<'a> { |
46 | self.roots.push(path.into()); | 47 | self.roots.push(path.into()); |
47 | self | 48 | self |
48 | } | 49 | } |
@@ -74,7 +75,16 @@ impl<'a> Project<'a> { | |||
74 | paths.push((path, entry.text)); | 75 | paths.push((path, entry.text)); |
75 | } | 76 | } |
76 | 77 | ||
77 | let roots = self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect(); | 78 | let mut roots = |
79 | self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect::<Vec<_>>(); | ||
80 | if roots.is_empty() { | ||
81 | roots.push(tmp_dir.path().to_path_buf()); | ||
82 | } | ||
83 | let linked_projects = roots | ||
84 | .into_iter() | ||
85 | .map(|it| ProjectManifest::discover_single(&it).unwrap()) | ||
86 | .map(LinkedProject::from) | ||
87 | .collect::<Vec<_>>(); | ||
78 | 88 | ||
79 | let mut config = Config { | 89 | let mut config = Config { |
80 | client_caps: ClientCapsConfig { | 90 | client_caps: ClientCapsConfig { |
@@ -84,6 +94,7 @@ impl<'a> Project<'a> { | |||
84 | ..Default::default() | 94 | ..Default::default() |
85 | }, | 95 | }, |
86 | with_sysroot: self.with_sysroot, | 96 | with_sysroot: self.with_sysroot, |
97 | linked_projects, | ||
87 | ..Config::default() | 98 | ..Config::default() |
88 | }; | 99 | }; |
89 | 100 | ||
@@ -91,7 +102,7 @@ impl<'a> Project<'a> { | |||
91 | f(&mut config) | 102 | f(&mut config) |
92 | } | 103 | } |
93 | 104 | ||
94 | Server::new(tmp_dir, config, roots, paths) | 105 | Server::new(tmp_dir, config, paths) |
95 | } | 106 | } |
96 | } | 107 | } |
97 | 108 | ||
@@ -109,20 +120,12 @@ pub struct Server { | |||
109 | } | 120 | } |
110 | 121 | ||
111 | impl Server { | 122 | impl Server { |
112 | fn new( | 123 | fn new(dir: TempDir, config: Config, files: Vec<(PathBuf, String)>) -> Server { |
113 | dir: TempDir, | ||
114 | config: Config, | ||
115 | roots: Vec<PathBuf>, | ||
116 | files: Vec<(PathBuf, String)>, | ||
117 | ) -> Server { | ||
118 | let path = dir.path().to_path_buf(); | ||
119 | |||
120 | let roots = if roots.is_empty() { vec![path] } else { roots }; | ||
121 | let (connection, client) = Connection::memory(); | 124 | let (connection, client) = Connection::memory(); |
122 | 125 | ||
123 | let _thread = jod_thread::Builder::new() | 126 | let _thread = jod_thread::Builder::new() |
124 | .name("test server".to_string()) | 127 | .name("test server".to_string()) |
125 | .spawn(move || main_loop(roots, config, connection).unwrap()) | 128 | .spawn(move || main_loop(config, connection).unwrap()) |
126 | .expect("failed to spawn a thread"); | 129 | .expect("failed to spawn a thread"); |
127 | 130 | ||
128 | let res = | 131 | let res = |