diff options
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 38 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 66 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting/tests.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide/test_data/highlight_unsafe.html | 11 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 3 | ||||
-rw-r--r-- | editors/code/src/util.ts | 6 |
11 files changed, 170 insertions, 26 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 28f32a0a4..3d12039a6 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -440,6 +440,12 @@ impl<'a> InferenceContext<'a> { | |||
440 | let ty = self.insert_type_vars(ty.subst(&substs)); | 440 | let ty = self.insert_type_vars(ty.subst(&substs)); |
441 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) | 441 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) |
442 | } | 442 | } |
443 | TypeNs::AdtId(AdtId::UnionId(u)) => { | ||
444 | let substs = Ty::substs_from_path(&ctx, path, u.into(), true); | ||
445 | let ty = self.db.ty(u.into()); | ||
446 | let ty = self.insert_type_vars(ty.subst(&substs)); | ||
447 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) | ||
448 | } | ||
443 | TypeNs::EnumVariantId(var) => { | 449 | TypeNs::EnumVariantId(var) => { |
444 | let substs = Ty::substs_from_path(&ctx, path, var.into(), true); | 450 | let substs = Ty::substs_from_path(&ctx, path, var.into(), true); |
445 | let ty = self.db.ty(var.parent.into()); | 451 | let ty = self.db.ty(var.parent.into()); |
@@ -490,10 +496,7 @@ impl<'a> InferenceContext<'a> { | |||
490 | // FIXME potentially resolve assoc type | 496 | // FIXME potentially resolve assoc type |
491 | (Ty::Unknown, None) | 497 | (Ty::Unknown, None) |
492 | } | 498 | } |
493 | TypeNs::AdtId(AdtId::EnumId(_)) | 499 | TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => { |
494 | | TypeNs::AdtId(AdtId::UnionId(_)) | ||
495 | | TypeNs::BuiltinType(_) | ||
496 | | TypeNs::TraitId(_) => { | ||
497 | // FIXME diagnostic | 500 | // FIXME diagnostic |
498 | (Ty::Unknown, None) | 501 | (Ty::Unknown, None) |
499 | } | 502 | } |
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 1eacc6f95..7638f167b 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -518,6 +518,7 @@ impl Ty { | |||
518 | let (segment, generic_def) = match resolved { | 518 | let (segment, generic_def) = match resolved { |
519 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), | 519 | ValueTyDefId::FunctionId(it) => (last, Some(it.into())), |
520 | ValueTyDefId::StructId(it) => (last, Some(it.into())), | 520 | ValueTyDefId::StructId(it) => (last, Some(it.into())), |
521 | ValueTyDefId::UnionId(it) => (last, Some(it.into())), | ||
521 | ValueTyDefId::ConstId(it) => (last, Some(it.into())), | 522 | ValueTyDefId::ConstId(it) => (last, Some(it.into())), |
522 | ValueTyDefId::StaticId(_) => (last, None), | 523 | ValueTyDefId::StaticId(_) => (last, None), |
523 | ValueTyDefId::EnumVariantId(var) => { | 524 | ValueTyDefId::EnumVariantId(var) => { |
@@ -1148,11 +1149,12 @@ impl_from!(BuiltinType, AdtId(StructId, EnumId, UnionId), TypeAliasId for TyDefI | |||
1148 | pub enum ValueTyDefId { | 1149 | pub enum ValueTyDefId { |
1149 | FunctionId(FunctionId), | 1150 | FunctionId(FunctionId), |
1150 | StructId(StructId), | 1151 | StructId(StructId), |
1152 | UnionId(UnionId), | ||
1151 | EnumVariantId(EnumVariantId), | 1153 | EnumVariantId(EnumVariantId), |
1152 | ConstId(ConstId), | 1154 | ConstId(ConstId), |
1153 | StaticId(StaticId), | 1155 | StaticId(StaticId), |
1154 | } | 1156 | } |
1155 | impl_from!(FunctionId, StructId, EnumVariantId, ConstId, StaticId for ValueTyDefId); | 1157 | impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId); |
1156 | 1158 | ||
1157 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 1159 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
1158 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 1160 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
@@ -1179,6 +1181,7 @@ pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders | |||
1179 | match def { | 1181 | match def { |
1180 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), | 1182 | ValueTyDefId::FunctionId(it) => type_for_fn(db, it), |
1181 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), | 1183 | ValueTyDefId::StructId(it) => type_for_struct_constructor(db, it), |
1184 | ValueTyDefId::UnionId(it) => type_for_adt(db, it.into()), | ||
1182 | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), | 1185 | ValueTyDefId::EnumVariantId(it) => type_for_enum_variant_constructor(db, it), |
1183 | ValueTyDefId::ConstId(it) => type_for_const(db, it), | 1186 | ValueTyDefId::ConstId(it) => type_for_const(db, it), |
1184 | ValueTyDefId::StaticId(it) => type_for_static(db, it), | 1187 | ValueTyDefId::StaticId(it) => type_for_static(db, it), |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 3fd7d5cd4..5a7cf9455 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -334,16 +334,44 @@ fn infer_union() { | |||
334 | bar: f32, | 334 | bar: f32, |
335 | } | 335 | } |
336 | 336 | ||
337 | fn test() { | ||
338 | let u = MyUnion { foo: 0 }; | ||
339 | unsafe { baz(u); } | ||
340 | let u = MyUnion { bar: 0.0 }; | ||
341 | unsafe { baz(u); } | ||
342 | } | ||
343 | |||
337 | unsafe fn baz(u: MyUnion) { | 344 | unsafe fn baz(u: MyUnion) { |
338 | let inner = u.foo; | 345 | let inner = u.foo; |
346 | let inner = u.bar; | ||
339 | } | 347 | } |
340 | "#, | 348 | "#, |
341 | expect![[r#" | 349 | expect![[r#" |
342 | 61..62 'u': MyUnion | 350 | 57..172 '{ ...); } }': () |
343 | 73..99 '{ ...foo; }': () | 351 | 67..68 'u': MyUnion |
344 | 83..88 'inner': u32 | 352 | 71..89 'MyUnio...o: 0 }': MyUnion |
345 | 91..92 'u': MyUnion | 353 | 86..87 '0': u32 |
346 | 91..96 'u.foo': u32 | 354 | 95..113 'unsafe...(u); }': () |
355 | 102..113 '{ baz(u); }': () | ||
356 | 104..107 'baz': fn baz(MyUnion) | ||
357 | 104..110 'baz(u)': () | ||
358 | 108..109 'u': MyUnion | ||
359 | 122..123 'u': MyUnion | ||
360 | 126..146 'MyUnio... 0.0 }': MyUnion | ||
361 | 141..144 '0.0': f32 | ||
362 | 152..170 'unsafe...(u); }': () | ||
363 | 159..170 '{ baz(u); }': () | ||
364 | 161..164 'baz': fn baz(MyUnion) | ||
365 | 161..167 'baz(u)': () | ||
366 | 165..166 'u': MyUnion | ||
367 | 188..189 'u': MyUnion | ||
368 | 200..249 '{ ...bar; }': () | ||
369 | 210..215 'inner': u32 | ||
370 | 218..219 'u': MyUnion | ||
371 | 218..223 'u.foo': u32 | ||
372 | 233..238 'inner': f32 | ||
373 | 241..242 'u': MyUnion | ||
374 | 241..246 'u.bar': f32 | ||
347 | "#]], | 375 | "#]], |
348 | ); | 376 | ); |
349 | } | 377 | } |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index f6e493817..9c7348898 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -512,6 +512,37 @@ fn main() { } | |||
512 | } | 512 | } |
513 | 513 | ||
514 | #[test] | 514 | #[test] |
515 | fn hover_shows_fn_doc() { | ||
516 | check( | ||
517 | r#" | ||
518 | /// # Example | ||
519 | /// ``` | ||
520 | /// # use std::path::Path; | ||
521 | /// # | ||
522 | /// foo(Path::new("hello, world!")) | ||
523 | /// ``` | ||
524 | pub fn foo<|>(_: &Path) {} | ||
525 | |||
526 | fn main() { } | ||
527 | "#, | ||
528 | expect![[r#" | ||
529 | *foo* | ||
530 | ```rust | ||
531 | pub fn foo(_: &Path) | ||
532 | ``` | ||
533 | ___ | ||
534 | |||
535 | # Example | ||
536 | ``` | ||
537 | # use std::path::Path; | ||
538 | # | ||
539 | foo(Path::new("hello, world!")) | ||
540 | ``` | ||
541 | "#]], | ||
542 | ); | ||
543 | } | ||
544 | |||
545 | #[test] | ||
515 | fn hover_shows_struct_field_info() { | 546 | fn hover_shows_struct_field_info() { |
516 | // Hovering over the field when instantiating | 547 | // Hovering over the field when instantiating |
517 | check( | 548 | check( |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index ec442bcd8..6b7874460 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -4,7 +4,7 @@ mod injection; | |||
4 | #[cfg(test)] | 4 | #[cfg(test)] |
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use hir::{Name, Semantics}; | 7 | use hir::{Name, Semantics, VariantDef}; |
8 | use ra_ide_db::{ | 8 | use ra_ide_db::{ |
9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, |
10 | RootDatabase, | 10 | RootDatabase, |
@@ -455,6 +455,18 @@ fn macro_call_range(macro_call: &ast::MacroCall) -> Option<TextRange> { | |||
455 | Some(TextRange::new(range_start, range_end)) | 455 | Some(TextRange::new(range_start, range_end)) |
456 | } | 456 | } |
457 | 457 | ||
458 | fn is_possibly_unsafe(name_ref: &ast::NameRef) -> bool { | ||
459 | name_ref | ||
460 | .syntax() | ||
461 | .parent() | ||
462 | .and_then(|parent| { | ||
463 | ast::FieldExpr::cast(parent.clone()) | ||
464 | .map(|_| true) | ||
465 | .or_else(|| ast::RecordPatField::cast(parent).map(|_| true)) | ||
466 | }) | ||
467 | .unwrap_or(false) | ||
468 | } | ||
469 | |||
458 | fn highlight_element( | 470 | fn highlight_element( |
459 | sema: &Semantics<RootDatabase>, | 471 | sema: &Semantics<RootDatabase>, |
460 | bindings_shadow_count: &mut FxHashMap<Name, u32>, | 472 | bindings_shadow_count: &mut FxHashMap<Name, u32>, |
@@ -485,10 +497,19 @@ fn highlight_element( | |||
485 | match name_kind { | 497 | match name_kind { |
486 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), | 498 | Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(), |
487 | Some(NameClass::Definition(def)) => { | 499 | Some(NameClass::Definition(def)) => { |
488 | highlight_name(db, def) | HighlightModifier::Definition | 500 | highlight_name(db, def, false) | HighlightModifier::Definition |
501 | } | ||
502 | Some(NameClass::ConstReference(def)) => highlight_name(db, def, false), | ||
503 | Some(NameClass::FieldShorthand { field, .. }) => { | ||
504 | let mut h = HighlightTag::Field.into(); | ||
505 | if let Definition::Field(field) = field { | ||
506 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
507 | h |= HighlightModifier::Unsafe; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | h | ||
489 | } | 512 | } |
490 | Some(NameClass::ConstReference(def)) => highlight_name(db, def), | ||
491 | Some(NameClass::FieldShorthand { .. }) => HighlightTag::Field.into(), | ||
492 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, | 513 | None => highlight_name_by_syntax(name) | HighlightModifier::Definition, |
493 | } | 514 | } |
494 | } | 515 | } |
@@ -499,6 +520,7 @@ fn highlight_element( | |||
499 | } | 520 | } |
500 | NAME_REF => { | 521 | NAME_REF => { |
501 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 522 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
523 | let possibly_unsafe = is_possibly_unsafe(&name_ref); | ||
502 | match classify_name_ref(sema, &name_ref) { | 524 | match classify_name_ref(sema, &name_ref) { |
503 | Some(name_kind) => match name_kind { | 525 | Some(name_kind) => match name_kind { |
504 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), | 526 | NameRefClass::ExternCrate(_) => HighlightTag::Module.into(), |
@@ -510,11 +532,13 @@ fn highlight_element( | |||
510 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 532 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
511 | } | 533 | } |
512 | }; | 534 | }; |
513 | highlight_name(db, def) | 535 | highlight_name(db, def, possibly_unsafe) |
514 | } | 536 | } |
515 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 537 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
516 | }, | 538 | }, |
517 | None if syntactic_name_ref_highlighting => highlight_name_ref_by_syntax(name_ref), | 539 | None if syntactic_name_ref_highlighting => { |
540 | highlight_name_ref_by_syntax(name_ref, sema) | ||
541 | } | ||
518 | None => HighlightTag::UnresolvedReference.into(), | 542 | None => HighlightTag::UnresolvedReference.into(), |
519 | } | 543 | } |
520 | } | 544 | } |
@@ -654,10 +678,19 @@ fn is_child_of_impl(element: &SyntaxElement) -> bool { | |||
654 | } | 678 | } |
655 | } | 679 | } |
656 | 680 | ||
657 | fn highlight_name(db: &RootDatabase, def: Definition) -> Highlight { | 681 | fn highlight_name(db: &RootDatabase, def: Definition, possibly_unsafe: bool) -> Highlight { |
658 | match def { | 682 | match def { |
659 | Definition::Macro(_) => HighlightTag::Macro, | 683 | Definition::Macro(_) => HighlightTag::Macro, |
660 | Definition::Field(_) => HighlightTag::Field, | 684 | Definition::Field(field) => { |
685 | let mut h = HighlightTag::Field.into(); | ||
686 | if possibly_unsafe { | ||
687 | if let VariantDef::Union(_) = field.parent_def(db) { | ||
688 | h |= HighlightModifier::Unsafe; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | return h; | ||
693 | } | ||
661 | Definition::ModuleDef(def) => match def { | 694 | Definition::ModuleDef(def) => match def { |
662 | hir::ModuleDef::Module(_) => HighlightTag::Module, | 695 | hir::ModuleDef::Module(_) => HighlightTag::Module, |
663 | hir::ModuleDef::Function(func) => { | 696 | hir::ModuleDef::Function(func) => { |
@@ -727,7 +760,7 @@ fn highlight_name_by_syntax(name: ast::Name) -> Highlight { | |||
727 | tag.into() | 760 | tag.into() |
728 | } | 761 | } |
729 | 762 | ||
730 | fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | 763 | fn highlight_name_ref_by_syntax(name: ast::NameRef, sema: &Semantics<RootDatabase>) -> Highlight { |
731 | let default = HighlightTag::UnresolvedReference; | 764 | let default = HighlightTag::UnresolvedReference; |
732 | 765 | ||
733 | let parent = match name.syntax().parent() { | 766 | let parent = match name.syntax().parent() { |
@@ -737,7 +770,20 @@ fn highlight_name_ref_by_syntax(name: ast::NameRef) -> Highlight { | |||
737 | 770 | ||
738 | let tag = match parent.kind() { | 771 | let tag = match parent.kind() { |
739 | METHOD_CALL_EXPR => HighlightTag::Function, | 772 | METHOD_CALL_EXPR => HighlightTag::Function, |
740 | FIELD_EXPR => HighlightTag::Field, | 773 | FIELD_EXPR => { |
774 | let h = HighlightTag::Field; | ||
775 | let is_union = ast::FieldExpr::cast(parent) | ||
776 | .and_then(|field_expr| { | ||
777 | let field = sema.resolve_field(&field_expr)?; | ||
778 | Some(if let VariantDef::Union(_) = field.parent_def(sema.db) { | ||
779 | true | ||
780 | } else { | ||
781 | false | ||
782 | }) | ||
783 | }) | ||
784 | .unwrap_or(false); | ||
785 | return if is_union { h | HighlightModifier::Unsafe } else { h.into() }; | ||
786 | } | ||
741 | PATH_SEGMENT => { | 787 | PATH_SEGMENT => { |
742 | let path = match parent.parent().and_then(ast::Path::cast) { | 788 | let path = match parent.parent().and_then(ast::Path::cast) { |
743 | Some(it) => it, | 789 | Some(it) => it, |
diff --git a/crates/ra_ide/src/syntax_highlighting/tests.rs b/crates/ra_ide/src/syntax_highlighting/tests.rs index b8d60bdc6..09062c38e 100644 --- a/crates/ra_ide/src/syntax_highlighting/tests.rs +++ b/crates/ra_ide/src/syntax_highlighting/tests.rs | |||
@@ -275,6 +275,11 @@ fn test_unsafe_highlighting() { | |||
275 | r#" | 275 | r#" |
276 | unsafe fn unsafe_fn() {} | 276 | unsafe fn unsafe_fn() {} |
277 | 277 | ||
278 | union Union { | ||
279 | a: u32, | ||
280 | b: f32, | ||
281 | } | ||
282 | |||
278 | struct HasUnsafeFn; | 283 | struct HasUnsafeFn; |
279 | 284 | ||
280 | impl HasUnsafeFn { | 285 | impl HasUnsafeFn { |
@@ -289,8 +294,14 @@ static mut global_mut: TypeForStaticMut = TypeForStaticMut { a: 0 }; | |||
289 | 294 | ||
290 | fn main() { | 295 | fn main() { |
291 | let x = &5 as *const usize; | 296 | let x = &5 as *const usize; |
297 | let u = Union { b: 0 }; | ||
292 | unsafe { | 298 | unsafe { |
293 | unsafe_fn(); | 299 | unsafe_fn(); |
300 | let b = u.b; | ||
301 | match u { | ||
302 | Union { b: 0 } => (), | ||
303 | Union { a } => (), | ||
304 | } | ||
294 | HasUnsafeFn.unsafe_method(); | 305 | HasUnsafeFn.unsafe_method(); |
295 | let y = *(x); | 306 | let y = *(x); |
296 | let z = -x; | 307 | let z = -x; |
diff --git a/crates/ra_ide/test_data/highlight_unsafe.html b/crates/ra_ide/test_data/highlight_unsafe.html index 87d8c1556..79409fe81 100644 --- a/crates/ra_ide/test_data/highlight_unsafe.html +++ b/crates/ra_ide/test_data/highlight_unsafe.html | |||
@@ -37,6 +37,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
37 | </style> | 37 | </style> |
38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> | 38 | <pre><code><span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span> |
39 | 39 | ||
40 | <span class="keyword">union</span> <span class="union declaration">Union</span> <span class="punctuation">{</span> | ||
41 | <span class="field declaration">a</span><span class="punctuation">:</span> <span class="builtin_type">u32</span><span class="punctuation">,</span> | ||
42 | <span class="field declaration">b</span><span class="punctuation">:</span> <span class="builtin_type">f32</span><span class="punctuation">,</span> | ||
43 | <span class="punctuation">}</span> | ||
44 | |||
40 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> | 45 | <span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span> |
41 | 46 | ||
42 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> | 47 | <span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span> |
@@ -51,8 +56,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
51 | 56 | ||
52 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> | 57 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span> |
53 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> | 58 | <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="punctuation">;</span> |
59 | <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="punctuation">{</span> <span class="field">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span><span class="punctuation">;</span> | ||
54 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> | 60 | <span class="keyword unsafe">unsafe</span> <span class="punctuation">{</span> |
55 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 61 | <span class="function unsafe">unsafe_fn</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
62 | <span class="keyword">let</span> <span class="variable declaration">b</span> <span class="operator">=</span> <span class="variable">u</span><span class="punctuation">.</span><span class="field unsafe">b</span><span class="punctuation">;</span> | ||
63 | <span class="keyword control">match</span> <span class="variable">u</span> <span class="punctuation">{</span> | ||
64 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | ||
65 | <span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span> | ||
66 | <span class="punctuation">}</span> | ||
56 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> | 67 | <span class="struct">HasUnsafeFn</span><span class="punctuation">.</span><span class="function unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span> |
57 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span> | 68 | <span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="punctuation">(</span><span class="variable">x</span><span class="punctuation">)</span><span class="punctuation">;</span> |
58 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="variable">x</span><span class="punctuation">;</span> | 69 | <span class="keyword">let</span> <span class="variable declaration">z</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="variable">x</span><span class="punctuation">;</span> |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 067259e24..895af1dd7 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -892,7 +892,7 @@ pub(crate) fn handle_code_lens( | |||
892 | } | 892 | } |
893 | 893 | ||
894 | let action = runnable.action(); | 894 | let action = runnable.action(); |
895 | let range = to_proto::range(&line_index, runnable.nav.focus_or_full_range()); | 895 | let range = to_proto::range(&line_index, runnable.nav.full_range); |
896 | let r = to_proto::runnable(&snap, file_id, runnable)?; | 896 | let r = to_proto::runnable(&snap, file_id, runnable)?; |
897 | if snap.config.lens.run { | 897 | if snap.config.lens.run { |
898 | let lens = CodeLens { | 898 | let lens = CodeLens { |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index ceddb2b05..0ac6434dd 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -47,7 +47,7 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> { | |||
47 | SetThreadPriority(thread, thread_priority_above_normal); | 47 | SetThreadPriority(thread, thread_priority_above_normal); |
48 | } | 48 | } |
49 | 49 | ||
50 | GlobalState::new(connection.sender.clone(), config).run(connection.receiver) | 50 | GlobalState::new(connection.sender, config).run(connection.receiver) |
51 | } | 51 | } |
52 | 52 | ||
53 | enum Event { | 53 | enum Event { |
@@ -337,6 +337,16 @@ impl GlobalState { | |||
337 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { | 337 | fn on_request(&mut self, request_received: Instant, req: Request) -> Result<()> { |
338 | self.register_request(&req, request_received); | 338 | self.register_request(&req, request_received); |
339 | 339 | ||
340 | if self.status == Status::Loading && req.method != "shutdown" { | ||
341 | self.respond(lsp_server::Response::new_err( | ||
342 | req.id, | ||
343 | // FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion) | ||
344 | lsp_server::ErrorCode::ContentModified as i32, | ||
345 | "Rust Analyzer is still loading...".to_owned(), | ||
346 | )); | ||
347 | return Ok(()); | ||
348 | } | ||
349 | |||
340 | RequestDispatcher { req: Some(req), global_state: self } | 350 | RequestDispatcher { req: Some(req), global_state: self } |
341 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? | 351 | .on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces()))? |
342 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? | 352 | .on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))? |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 5eba1f155..27460db78 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -755,7 +755,8 @@ pub(crate) fn runnable( | |||
755 | } | 755 | } |
756 | 756 | ||
757 | pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { | 757 | pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { |
758 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value: markup.into() } | 758 | let value = crate::markdown::format_docs(markup.as_str()); |
759 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } | ||
759 | } | 760 | } |
760 | 761 | ||
761 | #[cfg(test)] | 762 | #[cfg(test)] |
diff --git a/editors/code/src/util.ts b/editors/code/src/util.ts index 970fedb37..49d2d1c6f 100644 --- a/editors/code/src/util.ts +++ b/editors/code/src/util.ts | |||
@@ -64,7 +64,8 @@ export async function sendRequestWithRetry<TParam, TRet>( | |||
64 | param: TParam, | 64 | param: TParam, |
65 | token?: vscode.CancellationToken, | 65 | token?: vscode.CancellationToken, |
66 | ): Promise<TRet> { | 66 | ): Promise<TRet> { |
67 | for (const delay of [2, 4, 6, 8, 10, null]) { | 67 | // The sequence is `10 * (2 ** (2 * n))` where n is 1, 2, 3... |
68 | for (const delay of [40, 160, 640, 2560, 10240, null]) { | ||
68 | try { | 69 | try { |
69 | return await (token | 70 | return await (token |
70 | ? client.sendRequest(reqType, param, token) | 71 | ? client.sendRequest(reqType, param, token) |
@@ -84,8 +85,7 @@ export async function sendRequestWithRetry<TParam, TRet>( | |||
84 | log.warn("LSP request failed", { method: reqType.method, param, error }); | 85 | log.warn("LSP request failed", { method: reqType.method, param, error }); |
85 | throw error; | 86 | throw error; |
86 | } | 87 | } |
87 | 88 | await sleep(delay); | |
88 | await sleep(10 * (1 << delay)); | ||
89 | } | 89 | } |
90 | } | 90 | } |
91 | throw 'unreachable'; | 91 | throw 'unreachable'; |