diff options
Diffstat (limited to 'crates/ra_ide/src')
-rw-r--r-- | crates/ra_ide/src/call_info.rs | 43 | ||||
-rw-r--r-- | crates/ra_ide/src/display/navigation_target.rs | 15 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 243 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 19 | ||||
-rw-r--r-- | crates/ra_ide/src/inlay_hints.rs | 26 | ||||
-rw-r--r-- | crates/ra_ide/src/marks.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 9 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/highlighting.html | 4 | ||||
-rw-r--r-- | crates/ra_ide/src/snapshots/rainbow_highlighting.html | 1 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 11 |
10 files changed, 278 insertions, 102 deletions
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index b3c323d38..2c2b6fa48 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -1,24 +1,26 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use ra_db::SourceDatabase; | 3 | use hir::db::AstDatabase; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | algo::ancestors_at_offset, | ||
6 | ast::{self, ArgListOwner}, | 5 | ast::{self, ArgListOwner}, |
7 | match_ast, AstNode, SyntaxNode, TextUnit, | 6 | match_ast, AstNode, SyntaxNode, |
8 | }; | 7 | }; |
9 | use test_utils::tested_by; | 8 | use test_utils::tested_by; |
10 | 9 | ||
11 | use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature}; | 10 | use crate::{ |
11 | db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature, | ||
12 | }; | ||
12 | 13 | ||
13 | /// Computes parameter information for the given call expression. | 14 | /// Computes parameter information for the given call expression. |
14 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { | 15 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> { |
15 | let parse = db.parse(position.file_id); | 16 | let file = db.parse_or_expand(position.file_id.into())?; |
16 | let syntax = parse.tree().syntax().clone(); | 17 | let token = file.token_at_offset(position.offset).next()?; |
18 | let token = descend_into_macros(db, position.file_id, token); | ||
17 | 19 | ||
18 | // Find the calling expression and it's NameRef | 20 | // Find the calling expression and it's NameRef |
19 | let calling_node = FnCallNode::with_node(&syntax, position.offset)?; | 21 | let calling_node = FnCallNode::with_node(&token.value.parent())?; |
20 | let name_ref = calling_node.name_ref()?; | 22 | let name_ref = calling_node.name_ref()?; |
21 | let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax()); | 23 | let name_ref = token.with_value(name_ref.syntax()); |
22 | 24 | ||
23 | let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); | 25 | let analyzer = hir::SourceAnalyzer::new(db, name_ref, None); |
24 | let (mut call_info, has_self) = match &calling_node { | 26 | let (mut call_info, has_self) = match &calling_node { |
@@ -93,8 +95,8 @@ enum FnCallNode { | |||
93 | } | 95 | } |
94 | 96 | ||
95 | impl FnCallNode { | 97 | impl FnCallNode { |
96 | fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> { | 98 | fn with_node(syntax: &SyntaxNode) -> Option<FnCallNode> { |
97 | ancestors_at_offset(syntax, offset).find_map(|node| { | 99 | syntax.ancestors().find_map(|node| { |
98 | match_ast! { | 100 | match_ast! { |
99 | match node { | 101 | match node { |
100 | ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, | 102 | ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, |
@@ -589,4 +591,25 @@ fn f() { | |||
589 | assert_eq!(info.label(), "foo!()"); | 591 | assert_eq!(info.label(), "foo!()"); |
590 | assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); | 592 | assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); |
591 | } | 593 | } |
594 | |||
595 | #[test] | ||
596 | fn fn_signature_for_call_in_macro() { | ||
597 | let info = call_info( | ||
598 | r#" | ||
599 | macro_rules! id { | ||
600 | ($($tt:tt)*) => { $($tt)* } | ||
601 | } | ||
602 | fn foo() { | ||
603 | |||
604 | } | ||
605 | id! { | ||
606 | fn bar() { | ||
607 | foo(<|>); | ||
608 | } | ||
609 | } | ||
610 | "#, | ||
611 | ); | ||
612 | |||
613 | assert_eq!(info.label(), "fn foo()"); | ||
614 | } | ||
592 | } | 615 | } |
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6a6b49afd..b9ae67828 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs | |||
@@ -328,22 +328,23 @@ impl ToNav for hir::AssocItem { | |||
328 | impl ToNav for hir::Local { | 328 | impl ToNav for hir::Local { |
329 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 329 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
330 | let src = self.source(db); | 330 | let src = self.source(db); |
331 | let (full_range, focus_range) = match src.value { | 331 | let node = match &src.value { |
332 | Either::Left(it) => { | 332 | Either::Left(bind_pat) => { |
333 | (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) | 333 | bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone()) |
334 | } | 334 | } |
335 | Either::Right(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), | 335 | Either::Right(it) => it.syntax().clone(), |
336 | }; | 336 | }; |
337 | let full_range = original_range(db, src.with_value(&node)); | ||
337 | let name = match self.name(db) { | 338 | let name = match self.name(db) { |
338 | Some(it) => it.to_string().into(), | 339 | Some(it) => it.to_string().into(), |
339 | None => "".into(), | 340 | None => "".into(), |
340 | }; | 341 | }; |
341 | NavigationTarget { | 342 | NavigationTarget { |
342 | file_id: src.file_id.original_file(db), | 343 | file_id: full_range.file_id, |
343 | name, | 344 | name, |
344 | kind: BIND_PAT, | 345 | kind: BIND_PAT, |
345 | full_range, | 346 | full_range: full_range.range, |
346 | focus_range, | 347 | focus_range: None, |
347 | container_name: None, | 348 | container_name: None, |
348 | description: None, | 349 | description: None, |
349 | docs: None, | 350 | docs: None, |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index bee8e9df2..9b5744789 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -225,35 +225,40 @@ mod tests { | |||
225 | 225 | ||
226 | use crate::mock_analysis::analysis_and_position; | 226 | use crate::mock_analysis::analysis_and_position; |
227 | 227 | ||
228 | fn check_goto(fixture: &str, expected: &str) { | 228 | fn check_goto(fixture: &str, expected: &str, expected_range: &str) { |
229 | let (analysis, pos) = analysis_and_position(fixture); | 229 | let (analysis, pos) = analysis_and_position(fixture); |
230 | 230 | ||
231 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; | 231 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; |
232 | assert_eq!(navs.len(), 1); | 232 | assert_eq!(navs.len(), 1); |
233 | let nav = navs.pop().unwrap(); | ||
234 | nav.assert_match(expected); | ||
235 | } | ||
236 | |||
237 | fn check_goto_with_range_content(fixture: &str, expected: &str, expected_range: &str) { | ||
238 | let (analysis, pos) = analysis_and_position(fixture); | ||
239 | 233 | ||
240 | let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; | ||
241 | assert_eq!(navs.len(), 1); | ||
242 | let nav = navs.pop().unwrap(); | 234 | let nav = navs.pop().unwrap(); |
243 | let file_text = analysis.file_text(pos.file_id).unwrap(); | 235 | let file_text = analysis.file_text(nav.file_id()).unwrap(); |
236 | |||
237 | let mut actual = file_text[nav.full_range()].to_string(); | ||
238 | if let Some(focus) = nav.focus_range() { | ||
239 | actual += "|"; | ||
240 | actual += &file_text[focus]; | ||
241 | } | ||
244 | 242 | ||
245 | let actual_full_range = &file_text[nav.full_range()]; | 243 | if !expected_range.contains("...") { |
246 | let actual_range = &file_text[nav.range()]; | 244 | test_utils::assert_eq_text!(&actual, expected_range); |
245 | } else { | ||
246 | let mut parts = expected_range.split("..."); | ||
247 | let prefix = parts.next().unwrap(); | ||
248 | let suffix = parts.next().unwrap(); | ||
249 | assert!( | ||
250 | actual.starts_with(prefix) && actual.ends_with(suffix), | ||
251 | "\nExpected: {}\n Actual: {}\n", | ||
252 | expected_range, | ||
253 | actual | ||
254 | ); | ||
255 | } | ||
247 | 256 | ||
248 | test_utils::assert_eq_text!( | ||
249 | &format!("{}|{}", actual_full_range, actual_range), | ||
250 | expected_range | ||
251 | ); | ||
252 | nav.assert_match(expected); | 257 | nav.assert_match(expected); |
253 | } | 258 | } |
254 | 259 | ||
255 | #[test] | 260 | #[test] |
256 | fn goto_definition_works_in_items() { | 261 | fn goto_def_in_items() { |
257 | check_goto( | 262 | check_goto( |
258 | " | 263 | " |
259 | //- /lib.rs | 264 | //- /lib.rs |
@@ -261,11 +266,12 @@ mod tests { | |||
261 | enum E { X(Foo<|>) } | 266 | enum E { X(Foo<|>) } |
262 | ", | 267 | ", |
263 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 268 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", |
269 | "struct Foo;|Foo", | ||
264 | ); | 270 | ); |
265 | } | 271 | } |
266 | 272 | ||
267 | #[test] | 273 | #[test] |
268 | fn goto_definition_works_at_start_of_item() { | 274 | fn goto_def_at_start_of_item() { |
269 | check_goto( | 275 | check_goto( |
270 | " | 276 | " |
271 | //- /lib.rs | 277 | //- /lib.rs |
@@ -273,6 +279,7 @@ mod tests { | |||
273 | enum E { X(<|>Foo) } | 279 | enum E { X(<|>Foo) } |
274 | ", | 280 | ", |
275 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", | 281 | "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", |
282 | "struct Foo;|Foo", | ||
276 | ); | 283 | ); |
277 | } | 284 | } |
278 | 285 | ||
@@ -285,61 +292,65 @@ mod tests { | |||
285 | mod a; | 292 | mod a; |
286 | mod b; | 293 | mod b; |
287 | enum E { X(Foo<|>) } | 294 | enum E { X(Foo<|>) } |
295 | |||
288 | //- /a.rs | 296 | //- /a.rs |
289 | struct Foo; | 297 | struct Foo; |
298 | |||
290 | //- /b.rs | 299 | //- /b.rs |
291 | struct Foo; | 300 | struct Foo; |
292 | ", | 301 | ", |
293 | "Foo STRUCT_DEF FileId(2) [0; 11) [7; 10)", | 302 | "Foo STRUCT_DEF FileId(2) [0; 11) [7; 10)", |
303 | "struct Foo;|Foo", | ||
294 | ); | 304 | ); |
295 | } | 305 | } |
296 | 306 | ||
297 | #[test] | 307 | #[test] |
298 | fn goto_definition_works_for_module_declaration() { | 308 | fn goto_def_for_module_declaration() { |
299 | check_goto( | 309 | check_goto( |
300 | " | 310 | " |
301 | //- /lib.rs | 311 | //- /lib.rs |
302 | mod <|>foo; | 312 | mod <|>foo; |
313 | |||
303 | //- /foo.rs | 314 | //- /foo.rs |
304 | // empty | 315 | // empty |
305 | ", | 316 | ", |
306 | "foo SOURCE_FILE FileId(2) [0; 10)", | 317 | "foo SOURCE_FILE FileId(2) [0; 10)", |
318 | "// empty\n\n", | ||
307 | ); | 319 | ); |
308 | 320 | ||
309 | check_goto( | 321 | check_goto( |
310 | " | 322 | " |
311 | //- /lib.rs | 323 | //- /lib.rs |
312 | mod <|>foo; | 324 | mod <|>foo; |
325 | |||
313 | //- /foo/mod.rs | 326 | //- /foo/mod.rs |
314 | // empty | 327 | // empty |
315 | ", | 328 | ", |
316 | "foo SOURCE_FILE FileId(2) [0; 10)", | 329 | "foo SOURCE_FILE FileId(2) [0; 10)", |
330 | "// empty\n\n", | ||
317 | ); | 331 | ); |
318 | } | 332 | } |
319 | 333 | ||
320 | #[test] | 334 | #[test] |
321 | fn goto_definition_works_for_macros() { | 335 | fn goto_def_for_macros() { |
322 | covers!(goto_definition_works_for_macros); | 336 | covers!(goto_def_for_macros); |
323 | check_goto( | 337 | check_goto( |
324 | " | 338 | " |
325 | //- /lib.rs | 339 | //- /lib.rs |
326 | macro_rules! foo { | 340 | macro_rules! foo { () => { () } } |
327 | () => { | ||
328 | {} | ||
329 | }; | ||
330 | } | ||
331 | 341 | ||
332 | fn bar() { | 342 | fn bar() { |
333 | <|>foo!(); | 343 | <|>foo!(); |
334 | } | 344 | } |
335 | ", | 345 | ", |
336 | "foo MACRO_CALL FileId(1) [0; 50) [13; 16)", | 346 | "foo MACRO_CALL FileId(1) [0; 33) [13; 16)", |
347 | "macro_rules! foo { () => { () } }|foo", | ||
337 | ); | 348 | ); |
338 | } | 349 | } |
339 | 350 | ||
340 | #[test] | 351 | #[test] |
341 | fn goto_definition_works_for_macros_from_other_crates() { | 352 | fn goto_def_for_macros_from_other_crates() { |
342 | covers!(goto_definition_works_for_macros); | 353 | covers!(goto_def_for_macros); |
343 | check_goto( | 354 | check_goto( |
344 | " | 355 | " |
345 | //- /lib.rs | 356 | //- /lib.rs |
@@ -350,18 +361,15 @@ mod tests { | |||
350 | 361 | ||
351 | //- /foo/lib.rs | 362 | //- /foo/lib.rs |
352 | #[macro_export] | 363 | #[macro_export] |
353 | macro_rules! foo { | 364 | macro_rules! foo { () => { () } } |
354 | () => { | ||
355 | {} | ||
356 | }; | ||
357 | } | ||
358 | ", | 365 | ", |
359 | "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", | 366 | "foo MACRO_CALL FileId(2) [0; 49) [29; 32)", |
367 | "#[macro_export]\nmacro_rules! foo { () => { () } }|foo", | ||
360 | ); | 368 | ); |
361 | } | 369 | } |
362 | 370 | ||
363 | #[test] | 371 | #[test] |
364 | fn goto_definition_works_for_macros_in_use_tree() { | 372 | fn goto_def_for_macros_in_use_tree() { |
365 | check_goto( | 373 | check_goto( |
366 | " | 374 | " |
367 | //- /lib.rs | 375 | //- /lib.rs |
@@ -369,19 +377,16 @@ mod tests { | |||
369 | 377 | ||
370 | //- /foo/lib.rs | 378 | //- /foo/lib.rs |
371 | #[macro_export] | 379 | #[macro_export] |
372 | macro_rules! foo { | 380 | macro_rules! foo { () => { () } } |
373 | () => { | ||
374 | {} | ||
375 | }; | ||
376 | } | ||
377 | ", | 381 | ", |
378 | "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", | 382 | "foo MACRO_CALL FileId(2) [0; 49) [29; 32)", |
383 | "#[macro_export]\nmacro_rules! foo { () => { () } }|foo", | ||
379 | ); | 384 | ); |
380 | } | 385 | } |
381 | 386 | ||
382 | #[test] | 387 | #[test] |
383 | fn goto_definition_works_for_macro_defined_fn_with_arg() { | 388 | fn goto_def_for_macro_defined_fn_with_arg() { |
384 | check_goto_with_range_content( | 389 | check_goto( |
385 | " | 390 | " |
386 | //- /lib.rs | 391 | //- /lib.rs |
387 | macro_rules! define_fn { | 392 | macro_rules! define_fn { |
@@ -400,8 +405,8 @@ mod tests { | |||
400 | } | 405 | } |
401 | 406 | ||
402 | #[test] | 407 | #[test] |
403 | fn goto_definition_works_for_macro_defined_fn_no_arg() { | 408 | fn goto_def_for_macro_defined_fn_no_arg() { |
404 | check_goto_with_range_content( | 409 | check_goto( |
405 | " | 410 | " |
406 | //- /lib.rs | 411 | //- /lib.rs |
407 | macro_rules! define_fn { | 412 | macro_rules! define_fn { |
@@ -420,27 +425,28 @@ mod tests { | |||
420 | } | 425 | } |
421 | 426 | ||
422 | #[test] | 427 | #[test] |
423 | fn goto_definition_works_for_methods() { | 428 | fn goto_def_for_methods() { |
424 | covers!(goto_definition_works_for_methods); | 429 | covers!(goto_def_for_methods); |
425 | check_goto( | 430 | check_goto( |
426 | " | 431 | " |
427 | //- /lib.rs | 432 | //- /lib.rs |
428 | struct Foo; | 433 | struct Foo; |
429 | impl Foo { | 434 | impl Foo { |
430 | fn frobnicate(&self) { } | 435 | fn frobnicate(&self) { } |
431 | } | 436 | } |
432 | 437 | ||
433 | fn bar(foo: &Foo) { | 438 | fn bar(foo: &Foo) { |
434 | foo.frobnicate<|>(); | 439 | foo.frobnicate<|>(); |
435 | } | 440 | } |
436 | ", | 441 | ", |
437 | "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", | 442 | "frobnicate FN_DEF FileId(1) [27; 51) [30; 40)", |
443 | "fn frobnicate(&self) { }|frobnicate", | ||
438 | ); | 444 | ); |
439 | } | 445 | } |
440 | 446 | ||
441 | #[test] | 447 | #[test] |
442 | fn goto_definition_works_for_fields() { | 448 | fn goto_def_for_fields() { |
443 | covers!(goto_definition_works_for_fields); | 449 | covers!(goto_def_for_fields); |
444 | check_goto( | 450 | check_goto( |
445 | " | 451 | " |
446 | //- /lib.rs | 452 | //- /lib.rs |
@@ -453,12 +459,13 @@ mod tests { | |||
453 | } | 459 | } |
454 | ", | 460 | ", |
455 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", | 461 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", |
462 | "spam: u32|spam", | ||
456 | ); | 463 | ); |
457 | } | 464 | } |
458 | 465 | ||
459 | #[test] | 466 | #[test] |
460 | fn goto_definition_works_for_record_fields() { | 467 | fn goto_def_for_record_fields() { |
461 | covers!(goto_definition_works_for_record_fields); | 468 | covers!(goto_def_for_record_fields); |
462 | check_goto( | 469 | check_goto( |
463 | " | 470 | " |
464 | //- /lib.rs | 471 | //- /lib.rs |
@@ -473,6 +480,7 @@ mod tests { | |||
473 | } | 480 | } |
474 | ", | 481 | ", |
475 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", | 482 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", |
483 | "spam: u32|spam", | ||
476 | ); | 484 | ); |
477 | } | 485 | } |
478 | 486 | ||
@@ -489,29 +497,31 @@ mod tests { | |||
489 | } | 497 | } |
490 | ", | 498 | ", |
491 | "TUPLE_FIELD_DEF FileId(1) [11; 14)", | 499 | "TUPLE_FIELD_DEF FileId(1) [11; 14)", |
500 | "u32", | ||
492 | ); | 501 | ); |
493 | } | 502 | } |
494 | 503 | ||
495 | #[test] | 504 | #[test] |
496 | fn goto_definition_works_for_ufcs_inherent_methods() { | 505 | fn goto_def_for_ufcs_inherent_methods() { |
497 | check_goto( | 506 | check_goto( |
498 | " | 507 | " |
499 | //- /lib.rs | 508 | //- /lib.rs |
500 | struct Foo; | 509 | struct Foo; |
501 | impl Foo { | 510 | impl Foo { |
502 | fn frobnicate() { } | 511 | fn frobnicate() { } |
503 | } | 512 | } |
504 | 513 | ||
505 | fn bar(foo: &Foo) { | 514 | fn bar(foo: &Foo) { |
506 | Foo::frobnicate<|>(); | 515 | Foo::frobnicate<|>(); |
507 | } | 516 | } |
508 | ", | 517 | ", |
509 | "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)", | 518 | "frobnicate FN_DEF FileId(1) [27; 46) [30; 40)", |
519 | "fn frobnicate() { }|frobnicate", | ||
510 | ); | 520 | ); |
511 | } | 521 | } |
512 | 522 | ||
513 | #[test] | 523 | #[test] |
514 | fn goto_definition_works_for_ufcs_trait_methods_through_traits() { | 524 | fn goto_def_for_ufcs_trait_methods_through_traits() { |
515 | check_goto( | 525 | check_goto( |
516 | " | 526 | " |
517 | //- /lib.rs | 527 | //- /lib.rs |
@@ -524,11 +534,12 @@ mod tests { | |||
524 | } | 534 | } |
525 | ", | 535 | ", |
526 | "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", | 536 | "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", |
537 | "fn frobnicate();|frobnicate", | ||
527 | ); | 538 | ); |
528 | } | 539 | } |
529 | 540 | ||
530 | #[test] | 541 | #[test] |
531 | fn goto_definition_works_for_ufcs_trait_methods_through_self() { | 542 | fn goto_def_for_ufcs_trait_methods_through_self() { |
532 | check_goto( | 543 | check_goto( |
533 | " | 544 | " |
534 | //- /lib.rs | 545 | //- /lib.rs |
@@ -543,6 +554,7 @@ mod tests { | |||
543 | } | 554 | } |
544 | ", | 555 | ", |
545 | "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", | 556 | "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", |
557 | "fn frobnicate();|frobnicate", | ||
546 | ); | 558 | ); |
547 | } | 559 | } |
548 | 560 | ||
@@ -559,6 +571,7 @@ mod tests { | |||
559 | } | 571 | } |
560 | ", | 572 | ", |
561 | "impl IMPL_BLOCK FileId(1) [12; 73)", | 573 | "impl IMPL_BLOCK FileId(1) [12; 73)", |
574 | "impl Foo {...}", | ||
562 | ); | 575 | ); |
563 | 576 | ||
564 | check_goto( | 577 | check_goto( |
@@ -572,6 +585,7 @@ mod tests { | |||
572 | } | 585 | } |
573 | ", | 586 | ", |
574 | "impl IMPL_BLOCK FileId(1) [12; 73)", | 587 | "impl IMPL_BLOCK FileId(1) [12; 73)", |
588 | "impl Foo {...}", | ||
575 | ); | 589 | ); |
576 | 590 | ||
577 | check_goto( | 591 | check_goto( |
@@ -585,6 +599,7 @@ mod tests { | |||
585 | } | 599 | } |
586 | ", | 600 | ", |
587 | "impl IMPL_BLOCK FileId(1) [15; 75)", | 601 | "impl IMPL_BLOCK FileId(1) [15; 75)", |
602 | "impl Foo {...}", | ||
588 | ); | 603 | ); |
589 | 604 | ||
590 | check_goto( | 605 | check_goto( |
@@ -597,6 +612,7 @@ mod tests { | |||
597 | } | 612 | } |
598 | ", | 613 | ", |
599 | "impl IMPL_BLOCK FileId(1) [15; 62)", | 614 | "impl IMPL_BLOCK FileId(1) [15; 62)", |
615 | "impl Foo {...}", | ||
600 | ); | 616 | ); |
601 | } | 617 | } |
602 | 618 | ||
@@ -616,6 +632,7 @@ mod tests { | |||
616 | } | 632 | } |
617 | ", | 633 | ", |
618 | "impl IMPL_BLOCK FileId(1) [49; 115)", | 634 | "impl IMPL_BLOCK FileId(1) [49; 115)", |
635 | "impl Make for Foo {...}", | ||
619 | ); | 636 | ); |
620 | 637 | ||
621 | check_goto( | 638 | check_goto( |
@@ -632,17 +649,19 @@ mod tests { | |||
632 | } | 649 | } |
633 | ", | 650 | ", |
634 | "impl IMPL_BLOCK FileId(1) [49; 115)", | 651 | "impl IMPL_BLOCK FileId(1) [49; 115)", |
652 | "impl Make for Foo {...}", | ||
635 | ); | 653 | ); |
636 | } | 654 | } |
637 | 655 | ||
638 | #[test] | 656 | #[test] |
639 | fn goto_definition_works_when_used_on_definition_name_itself() { | 657 | fn goto_def_when_used_on_definition_name_itself() { |
640 | check_goto( | 658 | check_goto( |
641 | " | 659 | " |
642 | //- /lib.rs | 660 | //- /lib.rs |
643 | struct Foo<|> { value: u32 } | 661 | struct Foo<|> { value: u32 } |
644 | ", | 662 | ", |
645 | "Foo STRUCT_DEF FileId(1) [0; 25) [7; 10)", | 663 | "Foo STRUCT_DEF FileId(1) [0; 25) [7; 10)", |
664 | "struct Foo { value: u32 }|Foo", | ||
646 | ); | 665 | ); |
647 | 666 | ||
648 | check_goto( | 667 | check_goto( |
@@ -653,15 +672,16 @@ mod tests { | |||
653 | } | 672 | } |
654 | "#, | 673 | "#, |
655 | "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)", | 674 | "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)", |
675 | "field: string|field", | ||
656 | ); | 676 | ); |
657 | 677 | ||
658 | check_goto( | 678 | check_goto( |
659 | " | 679 | " |
660 | //- /lib.rs | 680 | //- /lib.rs |
661 | fn foo_test<|>() { | 681 | fn foo_test<|>() { } |
662 | } | ||
663 | ", | 682 | ", |
664 | "foo_test FN_DEF FileId(1) [0; 17) [3; 11)", | 683 | "foo_test FN_DEF FileId(1) [0; 17) [3; 11)", |
684 | "fn foo_test() { }|foo_test", | ||
665 | ); | 685 | ); |
666 | 686 | ||
667 | check_goto( | 687 | check_goto( |
@@ -672,6 +692,7 @@ mod tests { | |||
672 | } | 692 | } |
673 | ", | 693 | ", |
674 | "Foo ENUM_DEF FileId(1) [0; 25) [5; 8)", | 694 | "Foo ENUM_DEF FileId(1) [0; 25) [5; 8)", |
695 | "enum Foo {...}|Foo", | ||
675 | ); | 696 | ); |
676 | 697 | ||
677 | check_goto( | 698 | check_goto( |
@@ -684,22 +705,25 @@ mod tests { | |||
684 | } | 705 | } |
685 | ", | 706 | ", |
686 | "Variant2 ENUM_VARIANT FileId(1) [29; 37) [29; 37)", | 707 | "Variant2 ENUM_VARIANT FileId(1) [29; 37) [29; 37)", |
708 | "Variant2|Variant2", | ||
687 | ); | 709 | ); |
688 | 710 | ||
689 | check_goto( | 711 | check_goto( |
690 | r#" | 712 | r#" |
691 | //- /lib.rs | 713 | //- /lib.rs |
692 | static inner<|>: &str = ""; | 714 | static INNER<|>: &str = ""; |
693 | "#, | 715 | "#, |
694 | "inner STATIC_DEF FileId(1) [0; 24) [7; 12)", | 716 | "INNER STATIC_DEF FileId(1) [0; 24) [7; 12)", |
717 | "static INNER: &str = \"\";|INNER", | ||
695 | ); | 718 | ); |
696 | 719 | ||
697 | check_goto( | 720 | check_goto( |
698 | r#" | 721 | r#" |
699 | //- /lib.rs | 722 | //- /lib.rs |
700 | const inner<|>: &str = ""; | 723 | const INNER<|>: &str = ""; |
701 | "#, | 724 | "#, |
702 | "inner CONST_DEF FileId(1) [0; 23) [6; 11)", | 725 | "INNER CONST_DEF FileId(1) [0; 23) [6; 11)", |
726 | "const INNER: &str = \"\";|INNER", | ||
703 | ); | 727 | ); |
704 | 728 | ||
705 | check_goto( | 729 | check_goto( |
@@ -708,24 +732,25 @@ mod tests { | |||
708 | type Thing<|> = Option<()>; | 732 | type Thing<|> = Option<()>; |
709 | "#, | 733 | "#, |
710 | "Thing TYPE_ALIAS_DEF FileId(1) [0; 24) [5; 10)", | 734 | "Thing TYPE_ALIAS_DEF FileId(1) [0; 24) [5; 10)", |
735 | "type Thing = Option<()>;|Thing", | ||
711 | ); | 736 | ); |
712 | 737 | ||
713 | check_goto( | 738 | check_goto( |
714 | r#" | 739 | r#" |
715 | //- /lib.rs | 740 | //- /lib.rs |
716 | trait Foo<|> { | 741 | trait Foo<|> { } |
717 | } | ||
718 | "#, | 742 | "#, |
719 | "Foo TRAIT_DEF FileId(1) [0; 13) [6; 9)", | 743 | "Foo TRAIT_DEF FileId(1) [0; 13) [6; 9)", |
744 | "trait Foo { }|Foo", | ||
720 | ); | 745 | ); |
721 | 746 | ||
722 | check_goto( | 747 | check_goto( |
723 | r#" | 748 | r#" |
724 | //- /lib.rs | 749 | //- /lib.rs |
725 | mod bar<|> { | 750 | mod bar<|> { } |
726 | } | ||
727 | "#, | 751 | "#, |
728 | "bar MODULE FileId(1) [0; 11) [4; 7)", | 752 | "bar MODULE FileId(1) [0; 11) [4; 7)", |
753 | "mod bar { }|bar", | ||
729 | ); | 754 | ); |
730 | } | 755 | } |
731 | 756 | ||
@@ -746,6 +771,7 @@ mod tests { | |||
746 | mod confuse_index { fn foo(); } | 771 | mod confuse_index { fn foo(); } |
747 | ", | 772 | ", |
748 | "foo FN_DEF FileId(1) [52; 63) [55; 58)", | 773 | "foo FN_DEF FileId(1) [52; 63) [55; 58)", |
774 | "fn foo() {}|foo", | ||
749 | ); | 775 | ); |
750 | } | 776 | } |
751 | 777 | ||
@@ -774,6 +800,7 @@ mod tests { | |||
774 | } | 800 | } |
775 | ", | 801 | ", |
776 | "foo FN_DEF FileId(1) [398; 415) [401; 404)", | 802 | "foo FN_DEF FileId(1) [398; 415) [401; 404)", |
803 | "fn foo() -> i8 {}|foo", | ||
777 | ); | 804 | ); |
778 | } | 805 | } |
779 | 806 | ||
@@ -787,6 +814,82 @@ mod tests { | |||
787 | } | 814 | } |
788 | ", | 815 | ", |
789 | "T TYPE_PARAM FileId(1) [11; 12)", | 816 | "T TYPE_PARAM FileId(1) [11; 12)", |
817 | "T", | ||
790 | ); | 818 | ); |
791 | } | 819 | } |
820 | |||
821 | #[test] | ||
822 | fn goto_within_macro() { | ||
823 | check_goto( | ||
824 | " | ||
825 | //- /lib.rs | ||
826 | macro_rules! id { | ||
827 | ($($tt:tt)*) => ($($tt)*) | ||
828 | } | ||
829 | |||
830 | fn foo() { | ||
831 | let x = 1; | ||
832 | id!({ | ||
833 | let y = <|>x; | ||
834 | let z = y; | ||
835 | }); | ||
836 | } | ||
837 | ", | ||
838 | "x BIND_PAT FileId(1) [69; 70)", | ||
839 | "x", | ||
840 | ); | ||
841 | |||
842 | check_goto( | ||
843 | " | ||
844 | //- /lib.rs | ||
845 | macro_rules! id { | ||
846 | ($($tt:tt)*) => ($($tt)*) | ||
847 | } | ||
848 | |||
849 | fn foo() { | ||
850 | let x = 1; | ||
851 | id!({ | ||
852 | let y = x; | ||
853 | let z = <|>y; | ||
854 | }); | ||
855 | } | ||
856 | ", | ||
857 | "y BIND_PAT FileId(1) [98; 99)", | ||
858 | "y", | ||
859 | ); | ||
860 | } | ||
861 | |||
862 | #[test] | ||
863 | fn goto_def_in_local_fn() { | ||
864 | check_goto( | ||
865 | " | ||
866 | //- /lib.rs | ||
867 | fn main() { | ||
868 | fn foo() { | ||
869 | let x = 92; | ||
870 | <|>x; | ||
871 | } | ||
872 | } | ||
873 | ", | ||
874 | "x BIND_PAT FileId(1) [39; 40)", | ||
875 | "x", | ||
876 | ); | ||
877 | } | ||
878 | |||
879 | #[test] | ||
880 | fn goto_def_for_field_init_shorthand() { | ||
881 | covers!(goto_def_for_field_init_shorthand); | ||
882 | check_goto( | ||
883 | " | ||
884 | //- /lib.rs | ||
885 | struct Foo { x: i32 } | ||
886 | fn main() { | ||
887 | let x = 92; | ||
888 | Foo { x<|> }; | ||
889 | } | ||
890 | ", | ||
891 | "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", | ||
892 | "x: i32|x", | ||
893 | ) | ||
894 | } | ||
792 | } | 895 | } |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 51e320128..a227bf546 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -250,7 +250,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { | |||
250 | } else { | 250 | } else { |
251 | return None; | 251 | return None; |
252 | }; | 252 | }; |
253 | Some(ty.display(db).to_string()) | 253 | Some(ty.display_truncated(db, None).to_string()) |
254 | } | 254 | } |
255 | 255 | ||
256 | #[cfg(test)] | 256 | #[cfg(test)] |
@@ -425,6 +425,23 @@ mod tests { | |||
425 | } | 425 | } |
426 | 426 | ||
427 | #[test] | 427 | #[test] |
428 | fn hover_omits_default_generic_types() { | ||
429 | check_hover_result( | ||
430 | r#" | ||
431 | //- /main.rs | ||
432 | struct Test<K, T = u8> { | ||
433 | k: K, | ||
434 | t: T, | ||
435 | } | ||
436 | |||
437 | fn main() { | ||
438 | let zz<|> = Test { t: 23, k: 33 }; | ||
439 | }"#, | ||
440 | &["Test<i32>"], | ||
441 | ); | ||
442 | } | ||
443 | |||
444 | #[test] | ||
428 | fn hover_some() { | 445 | fn hover_some() { |
429 | let (analysis, position) = single_file_with_position( | 446 | let (analysis, position) = single_file_with_position( |
430 | " | 447 | " |
diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3730121af..3154df457 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs | |||
@@ -160,6 +160,32 @@ mod tests { | |||
160 | use crate::mock_analysis::single_file; | 160 | use crate::mock_analysis::single_file; |
161 | 161 | ||
162 | #[test] | 162 | #[test] |
163 | fn default_generic_types_should_not_be_displayed() { | ||
164 | let (analysis, file_id) = single_file( | ||
165 | r#" | ||
166 | struct Test<K, T = u8> { | ||
167 | k: K, | ||
168 | t: T, | ||
169 | } | ||
170 | |||
171 | fn main() { | ||
172 | let zz = Test { t: 23, k: 33 }; | ||
173 | }"#, | ||
174 | ); | ||
175 | |||
176 | assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" | ||
177 | [ | ||
178 | InlayHint { | ||
179 | range: [69; 71), | ||
180 | kind: TypeHint, | ||
181 | label: "Test<i32>", | ||
182 | }, | ||
183 | ] | ||
184 | "### | ||
185 | ); | ||
186 | } | ||
187 | |||
188 | #[test] | ||
163 | fn let_statement() { | 189 | fn let_statement() { |
164 | let (analysis, file_id) = single_file( | 190 | let (analysis, file_id) = single_file( |
165 | r#" | 191 | r#" |
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs index 848ae4dc7..077a44473 100644 --- a/crates/ra_ide/src/marks.rs +++ b/crates/ra_ide/src/marks.rs | |||
@@ -3,10 +3,11 @@ | |||
3 | test_utils::marks!( | 3 | test_utils::marks!( |
4 | inserts_angle_brackets_for_generics | 4 | inserts_angle_brackets_for_generics |
5 | inserts_parens_for_function_calls | 5 | inserts_parens_for_function_calls |
6 | goto_definition_works_for_macros | 6 | goto_def_for_macros |
7 | goto_definition_works_for_methods | 7 | goto_def_for_methods |
8 | goto_definition_works_for_fields | 8 | goto_def_for_fields |
9 | goto_definition_works_for_record_fields | 9 | goto_def_for_record_fields |
10 | goto_def_for_field_init_shorthand | ||
10 | call_info_bad_offset | 11 | call_info_bad_offset |
11 | dont_complete_current_use | 12 | dont_complete_current_use |
12 | dont_complete_primitive_in_use | 13 | dont_complete_primitive_in_use |
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index c1f091ec0..3483a7176 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -134,21 +134,22 @@ pub(crate) fn classify_name_ref( | |||
134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); | 134 | let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); |
135 | 135 | ||
136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 136 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
137 | tested_by!(goto_definition_works_for_methods); | 137 | tested_by!(goto_def_for_methods); |
138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 138 | if let Some(func) = analyzer.resolve_method_call(&method_call) { |
139 | return Some(from_assoc_item(db, func.into())); | 139 | return Some(from_assoc_item(db, func.into())); |
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 143 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
144 | tested_by!(goto_definition_works_for_fields); | 144 | tested_by!(goto_def_for_fields); |
145 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 145 | if let Some(field) = analyzer.resolve_field(&field_expr) { |
146 | return Some(from_struct_field(db, field)); | 146 | return Some(from_struct_field(db, field)); |
147 | } | 147 | } |
148 | } | 148 | } |
149 | 149 | ||
150 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 150 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
151 | tested_by!(goto_definition_works_for_record_fields); | 151 | tested_by!(goto_def_for_record_fields); |
152 | tested_by!(goto_def_for_field_init_shorthand); | ||
152 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | 153 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { |
153 | return Some(from_struct_field(db, field_def)); | 154 | return Some(from_struct_field(db, field_def)); |
154 | } | 155 | } |
@@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref( | |||
160 | let visibility = None; | 161 | let visibility = None; |
161 | 162 | ||
162 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 163 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
163 | tested_by!(goto_definition_works_for_macros); | 164 | tested_by!(goto_def_for_macros); |
164 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { | 165 | if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { |
165 | let kind = NameKind::Macro(macro_def); | 166 | let kind = NameKind::Macro(macro_def); |
166 | return Some(NameDefinition { kind, container, visibility }); | 167 | return Some(NameDefinition { kind, container, visibility }); |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 2157139f6..a097cf8e8 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
5 | 5 | ||
6 | .comment { color: #7F9F7F; } | 6 | .comment { color: #7F9F7F; } |
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .field { color: #94BFF3; } | ||
8 | .function { color: #93E0E3; } | 9 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 10 | .parameter { color: #94BFF3; } |
10 | .text { color: #DCDCCC; } | 11 | .text { color: #DCDCCC; } |
@@ -39,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
39 | 40 | ||
40 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); | 41 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable.mut">vec</span> = <span class="text">Vec</span>::<span class="text">new</span>(); |
41 | <span class="keyword.control">if</span> <span class="keyword">true</span> { | 42 | <span class="keyword.control">if</span> <span class="keyword">true</span> { |
42 | <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>: <span class="literal.numeric">0</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> }); | 43 | <span class="keyword">let</span> <span class="variable">x</span> = <span class="literal.numeric">92</span>; |
44 | <span class="variable.mut">vec</span>.<span class="text">push</span>(<span class="type">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="literal.numeric">1</span> }); | ||
43 | } | 45 | } |
44 | <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); } | 46 | <span class="keyword.unsafe">unsafe</span> { <span class="variable.mut">vec</span>.<span class="text">set_len</span>(<span class="literal.numeric">0</span>); } |
45 | 47 | ||
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 871a52cf6..110556c09 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
5 | 5 | ||
6 | .comment { color: #7F9F7F; } | 6 | .comment { color: #7F9F7F; } |
7 | .string { color: #CC9393; } | 7 | .string { color: #CC9393; } |
8 | .field { color: #94BFF3; } | ||
8 | .function { color: #93E0E3; } | 9 | .function { color: #93E0E3; } |
9 | .parameter { color: #94BFF3; } | 10 | .parameter { color: #94BFF3; } |
10 | .text { color: #DCDCCC; } | 11 | .text { color: #DCDCCC; } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 15e75709c..657c7b21a 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -102,11 +102,10 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
102 | COMMENT => tags::LITERAL_COMMENT, | 102 | COMMENT => tags::LITERAL_COMMENT, |
103 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, | 103 | STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, |
104 | ATTR => tags::LITERAL_ATTRIBUTE, | 104 | ATTR => tags::LITERAL_ATTRIBUTE, |
105 | // Special-case field init shorthand | ||
106 | NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => tags::FIELD, | ||
107 | NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => continue, | ||
105 | NAME_REF => { | 108 | NAME_REF => { |
106 | if node.ancestors().any(|it| it.kind() == ATTR) { | ||
107 | continue; | ||
108 | } | ||
109 | |||
110 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); | 109 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
111 | let name_kind = | 110 | let name_kind = |
112 | classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); | 111 | classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); |
@@ -282,6 +281,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
282 | 281 | ||
283 | .comment { color: #7F9F7F; } | 282 | .comment { color: #7F9F7F; } |
284 | .string { color: #CC9393; } | 283 | .string { color: #CC9393; } |
284 | .field { color: #94BFF3; } | ||
285 | .function { color: #93E0E3; } | 285 | .function { color: #93E0E3; } |
286 | .parameter { color: #94BFF3; } | 286 | .parameter { color: #94BFF3; } |
287 | .text { color: #DCDCCC; } | 287 | .text { color: #DCDCCC; } |
@@ -327,7 +327,8 @@ fn main() { | |||
327 | 327 | ||
328 | let mut vec = Vec::new(); | 328 | let mut vec = Vec::new(); |
329 | if true { | 329 | if true { |
330 | vec.push(Foo { x: 0, y: 1 }); | 330 | let x = 92; |
331 | vec.push(Foo { x, y: 1 }); | ||
331 | } | 332 | } |
332 | unsafe { vec.set_len(0); } | 333 | unsafe { vec.set_len(0); } |
333 | 334 | ||