diff options
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 51 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 20 |
2 files changed, 24 insertions, 47 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 3adb8baf6..4f098b706 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -88,46 +88,28 @@ impl ProjectRoot { | |||
88 | } | 88 | } |
89 | 89 | ||
90 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> { | 90 | pub fn discover(path: &Path) -> io::Result<Vec<ProjectRoot>> { |
91 | if let Some(project_json) = find_rust_project_json(path) { | 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![ProjectRoot::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(ProjectRoot::CargoToml).collect()); |
96 | 96 | ||
97 | fn find_rust_project_json(path: &Path) -> Option<PathBuf> { | ||
98 | if path.ends_with("rust-project.json") { | ||
99 | return Some(path.to_path_buf()); | ||
100 | } | ||
101 | |||
102 | let mut curr = Some(path); | ||
103 | while let Some(path) = curr { | ||
104 | let candidate = path.join("rust-project.json"); | ||
105 | if candidate.exists() { | ||
106 | return Some(candidate); | ||
107 | } | ||
108 | curr = path.parent(); | ||
109 | } | ||
110 | |||
111 | None | ||
112 | } | ||
113 | |||
114 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { | 97 | fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> { |
115 | if path.ends_with("Cargo.toml") { | 98 | match find_in_parent_dirs(path, "Cargo.toml") { |
116 | return Ok(vec![path.to_path_buf()]); | 99 | Some(it) => Ok(vec![it]), |
100 | None => Ok(find_cargo_toml_in_child_dir(read_dir(path)?)), | ||
117 | } | 101 | } |
102 | } | ||
118 | 103 | ||
119 | if let Some(p) = find_cargo_toml_in_parent_dir(path) { | 104 | fn find_in_parent_dirs(path: &Path, target_file_name: &str) -> Option<PathBuf> { |
120 | return Ok(vec![p]); | 105 | if path.ends_with(target_file_name) { |
106 | return Some(path.to_owned()); | ||
121 | } | 107 | } |
122 | 108 | ||
123 | let entities = read_dir(path)?; | ||
124 | Ok(find_cargo_toml_in_child_dir(entities)) | ||
125 | } | ||
126 | |||
127 | fn find_cargo_toml_in_parent_dir(path: &Path) -> Option<PathBuf> { | ||
128 | let mut curr = Some(path); | 109 | let mut curr = Some(path); |
110 | |||
129 | while let Some(path) = curr { | 111 | while let Some(path) = curr { |
130 | let candidate = path.join("Cargo.toml"); | 112 | let candidate = path.join(target_file_name); |
131 | if candidate.exists() { | 113 | if candidate.exists() { |
132 | return Some(candidate); | 114 | return Some(candidate); |
133 | } | 115 | } |
@@ -139,14 +121,11 @@ impl ProjectRoot { | |||
139 | 121 | ||
140 | fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> { | 122 | fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> { |
141 | // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects | 123 | // Only one level down to avoid cycles the easy way and stop a runaway scan with large projects |
142 | let mut valid_canditates = vec![]; | 124 | entities |
143 | for entity in entities.filter_map(Result::ok) { | 125 | .filter_map(Result::ok) |
144 | let candidate = entity.path().join("Cargo.toml"); | 126 | .map(|it| it.path().join("Cargo.toml")) |
145 | if candidate.exists() { | 127 | .filter(|it| it.exists()) |
146 | valid_canditates.push(candidate) | 128 | .collect() |
147 | } | ||
148 | } | ||
149 | valid_canditates | ||
150 | } | 129 | } |
151 | } | 130 | } |
152 | } | 131 | } |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index b77f0c5a9..17b0b95b9 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -96,23 +96,21 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection) | |||
96 | let mut world_state = { | 96 | let mut world_state = { |
97 | let workspaces = { | 97 | let workspaces = { |
98 | // FIXME: support dynamic workspace loading. | 98 | // FIXME: support dynamic workspace loading. |
99 | let mut visited = FxHashSet::default(); | 99 | let project_roots: FxHashSet<_> = ws_roots |
100 | let project_roots = ws_roots | ||
101 | .iter() | 100 | .iter() |
102 | .filter_map(|it| ra_project_model::ProjectRoot::discover(it).ok()) | 101 | .filter_map(|it| ra_project_model::ProjectRoot::discover(it).ok()) |
103 | .flatten() | 102 | .flatten() |
104 | .filter(|it| visited.insert(it.clone())) | 103 | .collect(); |
105 | .collect::<Vec<_>>(); | ||
106 | 104 | ||
107 | if project_roots.is_empty() && config.notifications.cargo_toml_not_found { | 105 | if project_roots.is_empty() && config.notifications.cargo_toml_not_found { |
108 | show_message( | 106 | show_message( |
109 | req::MessageType::Error, | 107 | req::MessageType::Error, |
110 | format!( | 108 | format!( |
111 | "rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: {}", | 109 | "rust-analyzer failed to discover workspace, no Cargo.toml found, dirs searched: {}", |
112 | ws_roots.iter().format_with(", ", |it, f| f(&it.display())) | 110 | ws_roots.iter().format_with(", ", |it, f| f(&it.display())) |
113 | ), | 111 | ), |
114 | &connection.sender, | 112 | &connection.sender, |
115 | ); | 113 | ); |
116 | }; | 114 | }; |
117 | 115 | ||
118 | project_roots | 116 | project_roots |