aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assist_context.rs60
-rw-r--r--crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs326
-rw-r--r--crates/ra_assists/src/lib.rs2
-rw-r--r--crates/ra_assists/src/tests/generated.rs15
-rw-r--r--crates/ra_project_model/src/lib.rs27
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs21
-rw-r--r--crates/rust-analyzer/src/global_state.rs12
7 files changed, 423 insertions, 40 deletions
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index 5b1a4680b..1925db8b2 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -19,6 +19,7 @@ use crate::{
19 assist_config::{AssistConfig, SnippetCap}, 19 assist_config::{AssistConfig, SnippetCap},
20 Assist, AssistId, GroupLabel, ResolvedAssist, 20 Assist, AssistId, GroupLabel, ResolvedAssist,
21}; 21};
22use rustc_hash::FxHashMap;
22 23
23/// `AssistContext` allows to apply an assist or check if it could be applied. 24/// `AssistContext` allows to apply an assist or check if it could be applied.
24/// 25///
@@ -138,6 +139,16 @@ impl Assists {
138 let label = Assist::new(id, label.into(), None, target); 139 let label = Assist::new(id, label.into(), None, target);
139 self.add_impl(label, f) 140 self.add_impl(label, f)
140 } 141 }
142 pub(crate) fn add_in_multiple_files(
143 &mut self,
144 id: AssistId,
145 label: impl Into<String>,
146 target: TextRange,
147 f: impl FnOnce(&mut AssistDirector),
148 ) -> Option<()> {
149 let label = Assist::new(id, label.into(), None, target);
150 self.add_impl_multiple_files(label, f)
151 }
141 pub(crate) fn add_group( 152 pub(crate) fn add_group(
142 &mut self, 153 &mut self,
143 group: &GroupLabel, 154 group: &GroupLabel,
@@ -162,6 +173,31 @@ impl Assists {
162 Some(()) 173 Some(())
163 } 174 }
164 175
176 fn add_impl_multiple_files(
177 &mut self,
178 label: Assist,
179 f: impl FnOnce(&mut AssistDirector),
180 ) -> Option<()> {
181 if !self.resolve {
182 self.buf.push((label, None));
183 return None;
184 }
185 let mut director = AssistDirector::default();
186 f(&mut director);
187 let changes = director.finish();
188 let file_edits: Vec<SourceFileEdit> =
189 changes.into_iter().map(|mut change| change.source_file_edits.pop().unwrap()).collect();
190
191 let source_change = SourceChange {
192 source_file_edits: file_edits,
193 file_system_edits: vec![],
194 is_snippet: false,
195 };
196
197 self.buf.push((label, Some(source_change)));
198 Some(())
199 }
200
165 fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> { 201 fn finish(mut self) -> Vec<(Assist, Option<SourceChange>)> {
166 self.buf.sort_by_key(|(label, _edit)| label.target.len()); 202 self.buf.sort_by_key(|(label, _edit)| label.target.len());
167 self.buf 203 self.buf
@@ -255,3 +291,27 @@ impl AssistBuilder {
255 res 291 res
256 } 292 }
257} 293}
294
295pub(crate) struct AssistDirector {
296 builders: FxHashMap<FileId, AssistBuilder>,
297}
298
299impl AssistDirector {
300 pub(crate) fn perform(&mut self, file_id: FileId, f: impl FnOnce(&mut AssistBuilder)) {
301 let mut builder = self.builders.entry(file_id).or_insert(AssistBuilder::new(file_id));
302 f(&mut builder);
303 }
304
305 fn finish(self) -> Vec<SourceChange> {
306 self.builders
307 .into_iter()
308 .map(|(_, builder)| builder.finish())
309 .collect::<Vec<SourceChange>>()
310 }
311}
312
313impl Default for AssistDirector {
314 fn default() -> Self {
315 AssistDirector { builders: FxHashMap::default() }
316 }
317}
diff --git a/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs
new file mode 100644
index 000000000..2c455a1fd
--- /dev/null
+++ b/crates/ra_assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -0,0 +1,326 @@
1use ra_ide_db::{defs::Definition, search::Reference, RootDatabase};
2use ra_syntax::{
3 algo::find_node_at_offset,
4 ast::{self, AstNode, NameOwner},
5 SourceFile, SyntaxNode, TextRange, TextSize,
6};
7
8use crate::{
9 assist_context::{AssistBuilder, AssistDirector},
10 utils::insert_use_statement,
11 AssistContext, AssistId, Assists,
12};
13use ast::{ArgListOwner, VisibilityOwner};
14use hir::{EnumVariant, Module, ModuleDef, Name};
15use ra_db::FileId;
16use ra_fmt::leading_indent;
17use rustc_hash::FxHashSet;
18
19// Assist: extract_struct_from_enum_variant
20//
21// Extracts a struct from enum variant.
22//
23// ```
24// enum A { <|>One(u32, u32) }
25// ```
26// ->
27// ```
28// struct One(pub u32, pub u32);
29//
30// enum A { One(One) }
31// ```
32pub(crate) fn extract_struct_from_enum_variant(
33 acc: &mut Assists,
34 ctx: &AssistContext,
35) -> Option<()> {
36 let variant = ctx.find_node_at_offset::<ast::EnumVariant>()?;
37 let field_list = match variant.kind() {
38 ast::StructKind::Tuple(field_list) => field_list,
39 _ => return None,
40 };
41 let variant_name = variant.name()?.to_string();
42 let variant_hir = ctx.sema.to_def(&variant)?;
43 if existing_struct_def(ctx.db, &variant_name, &variant_hir) {
44 return None;
45 }
46 let enum_ast = variant.parent_enum();
47 let visibility = enum_ast.visibility();
48 let enum_hir = ctx.sema.to_def(&enum_ast)?;
49 let variant_hir_name = variant_hir.name(ctx.db);
50 let enum_module_def = ModuleDef::from(enum_hir);
51 let current_module = enum_hir.module(ctx.db);
52 let target = variant.syntax().text_range();
53 acc.add_in_multiple_files(
54 AssistId("extract_struct_from_enum_variant"),
55 "Extract struct from enum variant",
56 target,
57 |edit| {
58 let definition = Definition::ModuleDef(ModuleDef::EnumVariant(variant_hir));
59 let res = definition.find_usages(&ctx.db, None);
60 let start_offset = variant.parent_enum().syntax().text_range().start();
61 let mut visited_modules_set = FxHashSet::default();
62 visited_modules_set.insert(current_module);
63 for reference in res {
64 let source_file = ctx.sema.parse(reference.file_range.file_id);
65 update_reference(
66 ctx,
67 edit,
68 reference,
69 &source_file,
70 &enum_module_def,
71 &variant_hir_name,
72 &mut visited_modules_set,
73 );
74 }
75 extract_struct_def(
76 edit,
77 enum_ast.syntax(),
78 &variant_name,
79 &field_list.to_string(),
80 start_offset,
81 ctx.frange.file_id,
82 &visibility,
83 );
84 let list_range = field_list.syntax().text_range();
85 update_variant(edit, &variant_name, ctx.frange.file_id, list_range);
86 },
87 )
88}
89
90fn existing_struct_def(db: &RootDatabase, variant_name: &str, variant: &EnumVariant) -> bool {
91 variant
92 .parent_enum(db)
93 .module(db)
94 .scope(db, None)
95 .into_iter()
96 .any(|(name, _)| name.to_string() == variant_name.to_string())
97}
98
99fn insert_import(
100 ctx: &AssistContext,
101 builder: &mut AssistBuilder,
102 path: &ast::PathExpr,
103 module: &Module,
104 enum_module_def: &ModuleDef,
105 variant_hir_name: &Name,
106) -> Option<()> {
107 let db = ctx.db;
108 let mod_path = module.find_use_path(db, enum_module_def.clone());
109 if let Some(mut mod_path) = mod_path {
110 mod_path.segments.pop();
111 mod_path.segments.push(variant_hir_name.clone());
112 insert_use_statement(path.syntax(), &mod_path, ctx, builder.text_edit_builder());
113 }
114 Some(())
115}
116
117fn extract_struct_def(
118 edit: &mut AssistDirector,
119 enum_ast: &SyntaxNode,
120 variant_name: &str,
121 variant_list: &str,
122 start_offset: TextSize,
123 file_id: FileId,
124 visibility: &Option<ast::Visibility>,
125) -> Option<()> {
126 let visibility_string = if let Some(visibility) = visibility {
127 format!("{} ", visibility.to_string())
128 } else {
129 "".to_string()
130 };
131 let indent = if let Some(indent) = leading_indent(enum_ast) {
132 indent.to_string()
133 } else {
134 "".to_string()
135 };
136 let struct_def = format!(
137 r#"{}struct {}{};
138
139{}"#,
140 visibility_string,
141 variant_name,
142 list_with_visibility(variant_list),
143 indent
144 );
145 edit.perform(file_id, |builder| {
146 builder.insert(start_offset, struct_def);
147 });
148 Some(())
149}
150
151fn update_variant(
152 edit: &mut AssistDirector,
153 variant_name: &str,
154 file_id: FileId,
155 list_range: TextRange,
156) -> Option<()> {
157 let inside_variant_range = TextRange::new(
158 list_range.start().checked_add(TextSize::from(1))?,
159 list_range.end().checked_sub(TextSize::from(1))?,
160 );
161 edit.perform(file_id, |builder| {
162 builder.replace(inside_variant_range, variant_name);
163 });
164 Some(())
165}
166
167fn update_reference(
168 ctx: &AssistContext,
169 edit: &mut AssistDirector,
170 reference: Reference,
171 source_file: &SourceFile,
172 enum_module_def: &ModuleDef,
173 variant_hir_name: &Name,
174 visited_modules_set: &mut FxHashSet<Module>,
175) -> Option<()> {
176 let path_expr: ast::PathExpr = find_node_at_offset::<ast::PathExpr>(
177 source_file.syntax(),
178 reference.file_range.range.start(),
179 )?;
180 let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
181 let list = call.arg_list()?;
182 let segment = path_expr.path()?.segment()?;
183 let module = ctx.sema.scope(&path_expr.syntax()).module()?;
184 let list_range = list.syntax().text_range();
185 let inside_list_range = TextRange::new(
186 list_range.start().checked_add(TextSize::from(1))?,
187 list_range.end().checked_sub(TextSize::from(1))?,
188 );
189 edit.perform(reference.file_range.file_id, |builder| {
190 if !visited_modules_set.contains(&module) {
191 if insert_import(ctx, builder, &path_expr, &module, enum_module_def, variant_hir_name)
192 .is_some()
193 {
194 visited_modules_set.insert(module);
195 }
196 }
197 builder.replace(inside_list_range, format!("{}{}", segment, list));
198 });
199 Some(())
200}
201
202fn list_with_visibility(list: &str) -> String {
203 list.split(',')
204 .map(|part| {
205 let index = if part.chars().next().unwrap() == '(' { 1usize } else { 0 };
206 let mut mod_part = part.trim().to_string();
207 mod_part.insert_str(index, "pub ");
208 mod_part
209 })
210 .collect::<Vec<String>>()
211 .join(", ")
212}
213
214#[cfg(test)]
215mod tests {
216
217 use crate::{
218 tests::{check_assist, check_assist_not_applicable},
219 utils::FamousDefs,
220 };
221
222 use super::*;
223
224 #[test]
225 fn test_extract_struct_several_fields() {
226 check_assist(
227 extract_struct_from_enum_variant,
228 "enum A { <|>One(u32, u32) }",
229 r#"struct One(pub u32, pub u32);
230
231enum A { One(One) }"#,
232 );
233 }
234
235 #[test]
236 fn test_extract_struct_one_field() {
237 check_assist(
238 extract_struct_from_enum_variant,
239 "enum A { <|>One(u32) }",
240 r#"struct One(pub u32);
241
242enum A { One(One) }"#,
243 );
244 }
245
246 #[test]
247 fn test_extract_struct_pub_visibility() {
248 check_assist(
249 extract_struct_from_enum_variant,
250 "pub enum A { <|>One(u32, u32) }",
251 r#"pub struct One(pub u32, pub u32);
252
253pub enum A { One(One) }"#,
254 );
255 }
256
257 #[test]
258 fn test_extract_struct_with_complex_imports() {
259 check_assist(
260 extract_struct_from_enum_variant,
261 r#"mod my_mod {
262 fn another_fn() {
263 let m = my_other_mod::MyEnum::MyField(1, 1);
264 }
265
266 pub mod my_other_mod {
267 fn another_fn() {
268 let m = MyEnum::MyField(1, 1);
269 }
270
271 pub enum MyEnum {
272 <|>MyField(u8, u8),
273 }
274 }
275}
276
277fn another_fn() {
278 let m = my_mod::my_other_mod::MyEnum::MyField(1, 1);
279}"#,
280 r#"use my_mod::my_other_mod::MyField;
281
282mod my_mod {
283 use my_other_mod::MyField;
284
285 fn another_fn() {
286 let m = my_other_mod::MyEnum::MyField(MyField(1, 1));
287 }
288
289 pub mod my_other_mod {
290 fn another_fn() {
291 let m = MyEnum::MyField(MyField(1, 1));
292 }
293
294 pub struct MyField(pub u8, pub u8);
295
296 pub enum MyEnum {
297 MyField(MyField),
298 }
299 }
300}
301
302fn another_fn() {
303 let m = my_mod::my_other_mod::MyEnum::MyField(MyField(1, 1));
304}"#,
305 );
306 }
307
308 fn check_not_applicable(ra_fixture: &str) {
309 let fixture =
310 format!("//- main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE);
311 check_assist_not_applicable(extract_struct_from_enum_variant, &fixture)
312 }
313
314 #[test]
315 fn test_extract_enum_not_applicable_for_element_with_no_fields() {
316 check_not_applicable("enum A { <|>One }");
317 }
318
319 #[test]
320 fn test_extract_enum_not_applicable_if_struct_exists() {
321 check_not_applicable(
322 r#"struct One;
323 enum A { <|>One(u8) }"#,
324 );
325 }
326}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index fb5d59a87..185428bd5 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -115,6 +115,7 @@ mod handlers {
115 mod change_return_type_to_result; 115 mod change_return_type_to_result;
116 mod change_visibility; 116 mod change_visibility;
117 mod early_return; 117 mod early_return;
118 mod extract_struct_from_enum_variant;
118 mod fill_match_arms; 119 mod fill_match_arms;
119 mod fix_visibility; 120 mod fix_visibility;
120 mod flip_binexpr; 121 mod flip_binexpr;
@@ -155,6 +156,7 @@ mod handlers {
155 change_return_type_to_result::change_return_type_to_result, 156 change_return_type_to_result::change_return_type_to_result,
156 change_visibility::change_visibility, 157 change_visibility::change_visibility,
157 early_return::convert_to_guarded_return, 158 early_return::convert_to_guarded_return,
159 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
158 fill_match_arms::fill_match_arms, 160 fill_match_arms::fill_match_arms,
159 fix_visibility::fix_visibility, 161 fix_visibility::fix_visibility,
160 flip_binexpr::flip_binexpr, 162 flip_binexpr::flip_binexpr,
diff --git a/crates/ra_assists/src/tests/generated.rs b/crates/ra_assists/src/tests/generated.rs
index d17504529..40a223727 100644
--- a/crates/ra_assists/src/tests/generated.rs
+++ b/crates/ra_assists/src/tests/generated.rs
@@ -338,6 +338,21 @@ fn main() {
338} 338}
339 339
340#[test] 340#[test]
341fn doctest_extract_struct_from_enum_variant() {
342 check_doc_test(
343 "extract_struct_from_enum_variant",
344 r#####"
345enum A { <|>One(u32, u32) }
346"#####,
347 r#####"
348struct One(pub u32, pub u32);
349
350enum A { One(One) }
351"#####,
352 )
353}
354
355#[test]
341fn doctest_fill_match_arms() { 356fn doctest_fill_match_arms() {
342 check_doc_test( 357 check_doc_test(
343 "fill_match_arms", 358 "fill_match_arms",
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 7ad941279..fe03b509e 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -250,7 +250,7 @@ impl ProjectWorkspace {
250 250
251 pub fn to_crate_graph( 251 pub fn to_crate_graph(
252 &self, 252 &self,
253 default_cfg_options: &CfgOptions, 253 target: Option<&str>,
254 extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, 254 extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>,
255 proc_macro_client: &ProcMacroClient, 255 proc_macro_client: &ProcMacroClient,
256 load: &mut dyn FnMut(&Path) -> Option<FileId>, 256 load: &mut dyn FnMut(&Path) -> Option<FileId>,
@@ -269,7 +269,7 @@ impl ProjectWorkspace {
269 json_project::Edition::Edition2018 => Edition::Edition2018, 269 json_project::Edition::Edition2018 => Edition::Edition2018,
270 }; 270 };
271 let cfg_options = { 271 let cfg_options = {
272 let mut opts = default_cfg_options.clone(); 272 let mut opts = CfgOptions::default();
273 for cfg in &krate.cfg { 273 for cfg in &krate.cfg {
274 match cfg.find('=') { 274 match cfg.find('=') {
275 None => opts.insert_atom(cfg.into()), 275 None => opts.insert_atom(cfg.into()),
@@ -343,18 +343,13 @@ impl ProjectWorkspace {
343 } 343 }
344 } 344 }
345 ProjectWorkspace::Cargo { cargo, sysroot } => { 345 ProjectWorkspace::Cargo { cargo, sysroot } => {
346 let mut cfg_options = get_rustc_cfg_options(target);
347
346 let sysroot_crates: FxHashMap<_, _> = sysroot 348 let sysroot_crates: FxHashMap<_, _> = sysroot
347 .crates() 349 .crates()
348 .filter_map(|krate| { 350 .filter_map(|krate| {
349 let file_id = load(&sysroot[krate].root)?; 351 let file_id = load(&sysroot[krate].root)?;
350 352
351 // Crates from sysroot have `cfg(test)` disabled
352 let cfg_options = {
353 let mut opts = default_cfg_options.clone();
354 opts.remove_atom("test");
355 opts
356 };
357
358 let env = Env::default(); 353 let env = Env::default();
359 let extern_source = ExternSource::default(); 354 let extern_source = ExternSource::default();
360 let proc_macro = vec![]; 355 let proc_macro = vec![];
@@ -365,7 +360,7 @@ impl ProjectWorkspace {
365 file_id, 360 file_id,
366 Edition::Edition2018, 361 Edition::Edition2018,
367 Some(crate_name), 362 Some(crate_name),
368 cfg_options, 363 cfg_options.clone(),
369 env, 364 env,
370 extern_source, 365 extern_source,
371 proc_macro, 366 proc_macro,
@@ -396,6 +391,10 @@ impl ProjectWorkspace {
396 391
397 let mut pkg_to_lib_crate = FxHashMap::default(); 392 let mut pkg_to_lib_crate = FxHashMap::default();
398 let mut pkg_crates = FxHashMap::default(); 393 let mut pkg_crates = FxHashMap::default();
394
395 // Add test cfg for non-sysroot crates
396 cfg_options.insert_atom("test".into());
397
399 // Next, create crates for each package, target pair 398 // Next, create crates for each package, target pair
400 for pkg in cargo.packages() { 399 for pkg in cargo.packages() {
401 let mut lib_tgt = None; 400 let mut lib_tgt = None;
@@ -404,7 +403,7 @@ impl ProjectWorkspace {
404 if let Some(file_id) = load(root) { 403 if let Some(file_id) = load(root) {
405 let edition = cargo[pkg].edition; 404 let edition = cargo[pkg].edition;
406 let cfg_options = { 405 let cfg_options = {
407 let mut opts = default_cfg_options.clone(); 406 let mut opts = cfg_options.clone();
408 for feature in cargo[pkg].features.iter() { 407 for feature in cargo[pkg].features.iter() {
409 opts.insert_key_value("feature".into(), feature.into()); 408 opts.insert_key_value("feature".into(), feature.into());
410 } 409 }
@@ -561,7 +560,7 @@ impl ProjectWorkspace {
561 } 560 }
562} 561}
563 562
564pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions { 563fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions {
565 let mut cfg_options = CfgOptions::default(); 564 let mut cfg_options = CfgOptions::default();
566 565
567 // Some nightly-only cfgs, which are required for stdlib 566 // Some nightly-only cfgs, which are required for stdlib
@@ -579,7 +578,7 @@ pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions {
579 let mut cmd = Command::new(ra_toolchain::rustc()); 578 let mut cmd = Command::new(ra_toolchain::rustc());
580 cmd.args(&["--print", "cfg", "-O"]); 579 cmd.args(&["--print", "cfg", "-O"]);
581 if let Some(target) = target { 580 if let Some(target) = target {
582 cmd.args(&["--target", target.as_str()]); 581 cmd.args(&["--target", target]);
583 } 582 }
584 let output = output(cmd)?; 583 let output = output(cmd)?;
585 Ok(String::from_utf8(output.stdout)?) 584 Ok(String::from_utf8(output.stdout)?)
@@ -601,6 +600,8 @@ pub fn get_rustc_cfg_options(target: Option<&String>) -> CfgOptions {
601 Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), 600 Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
602 } 601 }
603 602
603 cfg_options.insert_atom("debug_assertion".into());
604
604 cfg_options 605 cfg_options
605} 606}
606 607
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index c7e86fe0c..8f2aeac77 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -8,8 +8,7 @@ use crossbeam_channel::{unbounded, Receiver};
8use ra_db::{ExternSourceId, FileId, SourceRootId}; 8use ra_db::{ExternSourceId, FileId, SourceRootId};
9use ra_ide::{AnalysisChange, AnalysisHost}; 9use ra_ide::{AnalysisChange, AnalysisHost};
10use ra_project_model::{ 10use ra_project_model::{
11 get_rustc_cfg_options, CargoConfig, PackageRoot, ProcMacroClient, ProjectManifest, 11 CargoConfig, PackageRoot, ProcMacroClient, ProjectManifest, ProjectWorkspace,
12 ProjectWorkspace,
13}; 12};
14use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch}; 13use ra_vfs::{RootEntry, Vfs, VfsChange, VfsTask, Watch};
15use rustc_hash::{FxHashMap, FxHashSet}; 14use rustc_hash::{FxHashMap, FxHashSet};
@@ -148,26 +147,14 @@ pub(crate) fn load(
148 } 147 }
149 } 148 }
150 149
151 // FIXME: cfg options? 150 let crate_graph =
152 let default_cfg_options = { 151 ws.to_crate_graph(None, &extern_source_roots, proc_macro_client, &mut |path: &Path| {
153 let mut opts = get_rustc_cfg_options(None);
154 opts.insert_atom("test".into());
155 opts.insert_atom("debug_assertion".into());
156 opts
157 };
158
159 let crate_graph = ws.to_crate_graph(
160 &default_cfg_options,
161 &extern_source_roots,
162 proc_macro_client,
163 &mut |path: &Path| {
164 // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs 152 // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs
165 let path = path.canonicalize().ok()?; 153 let path = path.canonicalize().ok()?;
166 let vfs_file = vfs.load(&path); 154 let vfs_file = vfs.load(&path);
167 log::debug!("vfs file {:?} -> {:?}", path, vfs_file); 155 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
168 vfs_file.map(vfs_file_to_id) 156 vfs_file.map(vfs_file_to_id)
169 }, 157 });
170 );
171 log::debug!("crate graph: {:?}", crate_graph); 158 log::debug!("crate graph: {:?}", crate_graph);
172 analysis_change.set_crate_graph(crate_graph); 159 analysis_change.set_crate_graph(crate_graph);
173 160
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 0bebb5bf6..73b0f881d 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -15,7 +15,7 @@ use ra_flycheck::{Flycheck, FlycheckConfig};
15use ra_ide::{ 15use ra_ide::{
16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId, 16 Analysis, AnalysisChange, AnalysisHost, CrateGraph, FileId, LibraryData, SourceRootId,
17}; 17};
18use ra_project_model::{get_rustc_cfg_options, ProcMacroClient, ProjectWorkspace}; 18use ra_project_model::{ProcMacroClient, ProjectWorkspace};
19use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; 19use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
20use relative_path::RelativePathBuf; 20use relative_path::RelativePathBuf;
21use stdx::format_to; 21use stdx::format_to;
@@ -135,14 +135,6 @@ impl GlobalState {
135 } 135 }
136 } 136 }
137 137
138 // FIXME: Read default cfgs from config
139 let default_cfg_options = {
140 let mut opts = get_rustc_cfg_options(config.cargo.target.as_ref());
141 opts.insert_atom("test".into());
142 opts.insert_atom("debug_assertion".into());
143 opts
144 };
145
146 let proc_macro_client = match &config.proc_macro_srv { 138 let proc_macro_client = match &config.proc_macro_srv {
147 None => ProcMacroClient::dummy(), 139 None => ProcMacroClient::dummy(),
148 Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) { 140 Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
@@ -168,7 +160,7 @@ impl GlobalState {
168 }; 160 };
169 for ws in workspaces.iter() { 161 for ws in workspaces.iter() {
170 crate_graph.extend(ws.to_crate_graph( 162 crate_graph.extend(ws.to_crate_graph(
171 &default_cfg_options, 163 config.cargo.target.as_deref(),
172 &extern_source_roots, 164 &extern_source_roots,
173 &proc_macro_client, 165 &proc_macro_client,
174 &mut load, 166 &mut load,