aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/semantics.rs6
-rw-r--r--crates/hir/src/source_analyzer.rs30
-rw-r--r--crates/hir_def/src/item_tree/lower.rs6
-rw-r--r--crates/hir_def/src/path/lower.rs4
-rw-r--r--crates/hir_expand/src/name.rs9
-rw-r--r--crates/hir_ty/src/lower.rs2
-rw-r--r--crates/hir_ty/src/tests/macros.rs26
-rw-r--r--crates/hir_ty/src/tests/traits.rs43
-rw-r--r--crates/ide/src/annotations.rs2
-rw-r--r--crates/ide/src/expand_macro.rs2
-rw-r--r--crates/ide/src/extend_selection.rs2
-rw-r--r--crates/ide/src/file_structure.rs3
-rw-r--r--crates/ide/src/goto_definition.rs2
-rw-r--r--crates/ide/src/goto_implementation.rs2
-rw-r--r--crates/ide/src/goto_type_definition.rs2
-rw-r--r--crates/ide/src/hover.rs65
-rw-r--r--crates/ide/src/inlay_hints.rs2
-rw-r--r--crates/ide/src/join_lines.rs2
-rw-r--r--crates/ide/src/matching_brace.rs2
-rw-r--r--crates/ide/src/move_item.rs2
-rw-r--r--crates/ide/src/parent_module.rs2
-rw-r--r--crates/ide/src/references.rs2
-rw-r--r--crates/ide/src/references/rename.rs2
-rw-r--r--crates/ide/src/runnables.rs1
-rw-r--r--crates/ide/src/status.rs1
-rw-r--r--crates/ide/src/syntax_highlighting.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs35
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html8
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html4
-rw-r--r--crates/ide/src/syntax_tree.rs1
-rw-r--r--crates/ide/src/typing.rs3
-rw-r--r--crates/ide/src/typing/on_enter.rs2
-rw-r--r--crates/ide/src/view_hir.rs1
-rw-r--r--crates/ide_assists/src/assist_context.rs5
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/extract_type_alias.rs149
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs19
-rw-r--r--crates/ide_completion/src/completions/postfix/format_like.rs2
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs2
-rw-r--r--crates/ide_completion/src/lib.rs2
-rw-r--r--crates/ide_db/src/apply_change.rs1
-rw-r--r--crates/proc_macro_srv/src/rustc_server.rs19
-rw-r--r--crates/rust-analyzer/src/handlers.rs3
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
-rw-r--r--editors/code/src/snippets.ts10
50 files changed, 478 insertions, 31 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index d3caeef4e..3bf722d2a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -76,9 +76,11 @@ impl PathResolution {
76 pub fn assoc_type_shorthand_candidates<R>( 76 pub fn assoc_type_shorthand_candidates<R>(
77 &self, 77 &self,
78 db: &dyn HirDatabase, 78 db: &dyn HirDatabase,
79 mut cb: impl FnMut(TypeAlias) -> Option<R>, 79 mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
80 ) -> Option<R> { 80 ) -> Option<R> {
81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into())) 81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| {
82 cb(name, id.into())
83 })
82 } 84 }
83} 85}
84 86
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 37d162b32..8e9ea0a03 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -20,7 +20,7 @@ use hir_def::{
20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{ 21use hir_ty::{
22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, 22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23 InferenceResult, Substitution, 23 InferenceResult, Substitution, TyLoweringContext,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -466,7 +466,21 @@ fn resolve_hir_path_(
466 prefer_value_ns: bool, 466 prefer_value_ns: bool,
467) -> Option<PathResolution> { 467) -> Option<PathResolution> {
468 let types = || { 468 let types = || {
469 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { 469 let (ty, unresolved) = match path.type_anchor() {
470 Some(type_ref) => {
471 let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
472 res.map(|ty_ns| (ty_ns, path.segments().first()))
473 }
474 None => {
475 let (ty, remaining) =
476 resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
477 match remaining {
478 Some(remaining) if remaining > 1 => None,
479 _ => Some((ty, path.segments().get(1))),
480 }
481 }
482 }?;
483 let res = match ty {
470 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 484 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
471 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), 485 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
472 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 486 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
@@ -476,7 +490,17 @@ fn resolve_hir_path_(
476 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), 490 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
477 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), 491 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
478 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 492 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
479 }) 493 };
494 match unresolved {
495 Some(unresolved) => res
496 .assoc_type_shorthand_candidates(db, |name, alias| {
497 (name == unresolved.name).then(|| alias)
498 })
499 .map(TypeAlias::from)
500 .map(Into::into)
501 .map(PathResolution::Def),
502 None => Some(res),
503 }
480 }; 504 };
481 505
482 let body_owner = resolver.body_owner(); 506 let body_owner = resolver.body_owner();
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 8d3862811..124dcc866 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -174,6 +174,12 @@ impl Ctx {
174 let forced_vis = self.forced_visibility.take(); 174 let forced_vis = self.forced_visibility.take();
175 175
176 let mut block_stack = Vec::new(); 176 let mut block_stack = Vec::new();
177
178 // if container itself is block, add it to the stack
179 if let Some(block) = ast::BlockExpr::cast(container.clone()) {
180 block_stack.push(self.source_ast_id_map.ast_id(&block));
181 }
182
177 for event in container.preorder().skip(1) { 183 for event in container.preorder().skip(1) {
178 match event { 184 match event {
179 WalkEvent::Enter(node) => { 185 WalkEvent::Enter(node) => {
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 505493a74..4de951fd3 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -74,6 +74,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
74 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo 74 // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
75 Some(trait_ref) => { 75 Some(trait_ref) => {
76 let path = Path::from_src(trait_ref.path()?, hygiene)?; 76 let path = Path::from_src(trait_ref.path()?, hygiene)?;
77 let num_segments = path.mod_path.segments.len();
77 kind = path.mod_path.kind; 78 kind = path.mod_path.kind;
78 79
79 let mut prefix_segments = path.mod_path.segments; 80 let mut prefix_segments = path.mod_path.segments;
@@ -85,7 +86,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
85 generic_args.extend(prefix_args); 86 generic_args.extend(prefix_args);
86 87
87 // Insert the type reference (T in the above example) as Self parameter for the trait 88 // Insert the type reference (T in the above example) as Self parameter for the trait
88 let last_segment = generic_args.last_mut()?; 89 let last_segment =
90 generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?;
89 if last_segment.is_none() { 91 if last_segment.is_none() {
90 *last_segment = Some(Arc::new(GenericArgs::empty())); 92 *last_segment = Some(Arc::new(GenericArgs::empty()));
91 }; 93 };
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index cd691b1d2..203ebbe85 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -55,6 +55,15 @@ impl Name {
55 } 55 }
56 } 56 }
57 57
58 /// A fake name for things missing in the source code.
59 ///
60 /// For example, `impl Foo for {}` should be treated as a trait impl for a
61 /// type with a missing name. Similarly, `struct S { : u32 }` should have a
62 /// single field with a missing name.
63 ///
64 /// Ideally, we want a `gensym` semantics for missing names -- each missing
65 /// name is equal only to itself. It's not clear how to implement this in
66 /// salsa though, so we punt on that bit for a moment.
58 pub fn missing() -> Name { 67 pub fn missing() -> Name {
59 Name::new_text("[missing name]".into()) 68 Name::new_text("[missing name]".into())
60 } 69 }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index afbfa12d5..14f34d73c 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -146,7 +146,7 @@ impl<'a> TyLoweringContext<'a> {
146 self.lower_ty_ext(type_ref).0 146 self.lower_ty_ext(type_ref).0
147 } 147 }
148 148
149 fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) { 149 pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
150 let mut res = None; 150 let mut res = None;
151 let ty = match type_ref { 151 let ty = match type_ref {
152 TypeRef::Never => TyKind::Never.intern(&Interner), 152 TypeRef::Never => TyKind::Never.intern(&Interner),
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 3eb01dbd0..86e3d8b86 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -373,6 +373,32 @@ fn recursive_inner_item_macro_rules() {
373} 373}
374 374
375#[test] 375#[test]
376fn infer_macro_defining_block_with_items() {
377 check_infer(
378 r#"
379 macro_rules! foo {
380 () => {{
381 fn bar() -> usize { 0 }
382 bar()
383 }};
384 }
385 fn main() {
386 let _a = foo!();
387 }
388 "#,
389 expect![[r#"
390 !15..18 '{0}': usize
391 !16..17 '0': usize
392 !0..24 '{fnbar...bar()}': usize
393 !18..21 'bar': fn bar() -> usize
394 !18..23 'bar()': usize
395 98..122 '{ ...!(); }': ()
396 108..110 '_a': usize
397 "#]],
398 );
399}
400
401#[test]
376fn infer_type_value_macro_having_same_name() { 402fn infer_type_value_macro_having_same_name() {
377 check_infer( 403 check_infer(
378 r#" 404 r#"
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 2ba97f814..65b71fdfa 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3370,3 +3370,46 @@ fn test() {
3370 "#]], 3370 "#]],
3371 ) 3371 )
3372} 3372}
3373
3374#[test]
3375fn qualified_path_as_qualified_trait() {
3376 check_infer(
3377 r#"
3378mod foo {
3379
3380 pub trait Foo {
3381 type Target;
3382 }
3383 pub trait Bar {
3384 type Output;
3385 fn boo() -> Self::Output {
3386 loop {}
3387 }
3388 }
3389}
3390
3391struct F;
3392impl foo::Foo for F {
3393 type Target = ();
3394}
3395impl foo::Bar for F {
3396 type Output = <F as foo::Foo>::Target;
3397}
3398
3399fn foo() {
3400 use foo::Bar;
3401 let x = <F as Bar>::boo();
3402}
3403
3404 "#,
3405 expect![[r#"
3406 132..163 '{ ... }': Bar::Output<Self>
3407 146..153 'loop {}': !
3408 151..153 '{}': ()
3409 306..358 '{ ...o(); }': ()
3410 334..335 'x': ()
3411 338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output
3412 338..355 '<F as ...:boo()': ()
3413 "#]],
3414 );
3415}
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 64bc926f1..5ebe7fd0e 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -19,6 +19,8 @@ use crate::{
19// 19//
20// Provides user with annotations above items for looking up references or impl blocks 20// Provides user with annotations above items for looking up references or impl blocks
21// and running/debugging binaries. 21// and running/debugging binaries.
22//
23// image::https://user-images.githubusercontent.com/48062697/113020672-b7c34f00-917a-11eb-8f6e-858735660a0e.png[]
22#[derive(Debug)] 24#[derive(Debug)]
23pub struct Annotation { 25pub struct Annotation {
24 pub range: TextRange, 26 pub range: TextRange,
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index ffb3a6f7d..9eeabbeda 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -23,6 +23,8 @@ pub struct ExpandedMacro {
23// 23//
24// | VS Code | **Rust Analyzer: Expand macro recursively** 24// | VS Code | **Rust Analyzer: Expand macro recursively**
25// |=== 25// |===
26//
27// image::https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif[]
26pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { 28pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> {
27 let sema = Semantics::new(db); 29 let sema = Semantics::new(db);
28 let file = sema.parse(position.file_id); 30 let file = sema.parse(position.file_id);
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index 5201ce587..7032889ac 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -24,6 +24,8 @@ use crate::FileRange;
24// 24//
25// | VS Code | kbd:[Alt+Shift+→], kbd:[Alt+Shift+←] 25// | VS Code | kbd:[Alt+Shift+→], kbd:[Alt+Shift+←]
26// |=== 26// |===
27//
28// image::https://user-images.githubusercontent.com/48062697/113020651-b42fc800-917a-11eb-8a4f-cf1a07859fac.gif[]
27pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange { 29pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRange {
28 let sema = Semantics::new(db); 30 let sema = Semantics::new(db);
29 let src = sema.parse(frange.file_id); 31 let src = sema.parse(frange.file_id);
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 2c898eae8..19071d6be 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -35,6 +35,9 @@ pub enum StructureNodeKind {
35// 35//
36// | VS Code | kbd:[Ctrl+Shift+O] 36// | VS Code | kbd:[Ctrl+Shift+O]
37// |=== 37// |===
38//
39// image::https://user-images.githubusercontent.com/48062697/113020654-b42fc800-917a-11eb-8388-e7dc4d92b02e.gif[]
40
38pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> { 41pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
39 let mut res = Vec::new(); 42 let mut res = Vec::new();
40 let mut stack = Vec::new(); 43 let mut stack = Vec::new();
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index c6556c487..8574d1e3f 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -21,6 +21,8 @@ use crate::{
21// 21//
22// | VS Code | kbd:[F12] 22// | VS Code | kbd:[F12]
23// |=== 23// |===
24//
25// image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[]
24pub(crate) fn goto_definition( 26pub(crate) fn goto_definition(
25 db: &RootDatabase, 27 db: &RootDatabase,
26 position: FilePosition, 28 position: FilePosition,
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index f4d7c14a6..05130a237 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -16,6 +16,8 @@ use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
16// 16//
17// | VS Code | kbd:[Ctrl+F12] 17// | VS Code | kbd:[Ctrl+F12]
18// |=== 18// |===
19//
20// image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
19pub(crate) fn goto_implementation( 21pub(crate) fn goto_implementation(
20 db: &RootDatabase, 22 db: &RootDatabase,
21 position: FilePosition, 23 position: FilePosition,
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs
index 2d38cb112..9d34b109b 100644
--- a/crates/ide/src/goto_type_definition.rs
+++ b/crates/ide/src/goto_type_definition.rs
@@ -12,6 +12,8 @@ use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
12// 12//
13// | VS Code | **Go to Type Definition* 13// | VS Code | **Go to Type Definition*
14// |=== 14// |===
15//
16// image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[]
15pub(crate) fn goto_type_definition( 17pub(crate) fn goto_type_definition(
16 db: &RootDatabase, 18 db: &RootDatabase,
17 position: FilePosition, 19 position: FilePosition,
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 7e35a1450..28e2e17dc 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -82,6 +82,8 @@ pub struct HoverResult {
82// 82//
83// Shows additional information, like type of an expression or documentation for definition when "focusing" code. 83// Shows additional information, like type of an expression or documentation for definition when "focusing" code.
84// Focusing is usually hovering with a mouse, but can also be triggered with a shortcut. 84// Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
85//
86// image::https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif[]
85pub(crate) fn hover( 87pub(crate) fn hover(
86 db: &RootDatabase, 88 db: &RootDatabase,
87 position: FilePosition, 89 position: FilePosition,
@@ -3832,4 +3834,67 @@ fn foo() {}
3832 "#]], 3834 "#]],
3833 ); 3835 );
3834 } 3836 }
3837
3838 #[test]
3839 fn hover_generic_assoc() {
3840 check(
3841 r#"
3842fn foo<T: A>() where T::Assoc$0: {}
3843
3844trait A {
3845 type Assoc;
3846}"#,
3847 expect![[r#"
3848 *Assoc*
3849
3850 ```rust
3851 test
3852 ```
3853
3854 ```rust
3855 type Assoc
3856 ```
3857 "#]],
3858 );
3859 check(
3860 r#"
3861fn foo<T: A>() {
3862 let _: <T>::Assoc$0;
3863}
3864
3865trait A {
3866 type Assoc;
3867}"#,
3868 expect![[r#"
3869 *Assoc*
3870
3871 ```rust
3872 test
3873 ```
3874
3875 ```rust
3876 type Assoc
3877 ```
3878 "#]],
3879 );
3880 check(
3881 r#"
3882trait A where
3883 Self::Assoc$0: ,
3884{
3885 type Assoc;
3886}"#,
3887 expect![[r#"
3888 *Assoc*
3889
3890 ```rust
3891 test
3892 ```
3893
3894 ```rust
3895 type Assoc
3896 ```
3897 "#]],
3898 );
3899 }
3835} 3900}
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index 25f96222c..f73edf8b6 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -52,6 +52,8 @@ pub struct InlayHint {
52// 52//
53// | VS Code | **Rust Analyzer: Toggle inlay hints* 53// | VS Code | **Rust Analyzer: Toggle inlay hints*
54// |=== 54// |===
55//
56// image::https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png[]
55pub(crate) fn inlay_hints( 57pub(crate) fn inlay_hints(
56 db: &RootDatabase, 58 db: &RootDatabase,
57 file_id: FileId, 59 file_id: FileId,
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs
index 4b25135cd..d584190f7 100644
--- a/crates/ide/src/join_lines.rs
+++ b/crates/ide/src/join_lines.rs
@@ -19,6 +19,8 @@ use text_edit::{TextEdit, TextEditBuilder};
19// 19//
20// | VS Code | **Rust Analyzer: Join lines** 20// | VS Code | **Rust Analyzer: Join lines**
21// |=== 21// |===
22//
23// image::https://user-images.githubusercontent.com/48062697/113020661-b6922200-917a-11eb-87c4-b75acc028f11.gif[]
22pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit { 24pub(crate) fn join_lines(file: &SourceFile, range: TextRange) -> TextEdit {
23 let range = if range.is_empty() { 25 let range = if range.is_empty() {
24 let syntax = file.syntax(); 26 let syntax = file.syntax();
diff --git a/crates/ide/src/matching_brace.rs b/crates/ide/src/matching_brace.rs
index 4241a6dac..261dcc255 100644
--- a/crates/ide/src/matching_brace.rs
+++ b/crates/ide/src/matching_brace.rs
@@ -14,6 +14,8 @@ use syntax::{
14// 14//
15// | VS Code | **Rust Analyzer: Find matching brace** 15// | VS Code | **Rust Analyzer: Find matching brace**
16// |=== 16// |===
17//
18// image::https://user-images.githubusercontent.com/48062697/113065573-04298180-91b1-11eb-8dec-d4e2a202f304.gif[]
17pub(crate) fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> { 19pub(crate) fn matching_brace(file: &SourceFile, offset: TextSize) -> Option<TextSize> {
18 const BRACES: &[SyntaxKind] = 20 const BRACES: &[SyntaxKind] =
19 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>], T![|], T![|]]; 21 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>], T![|], T![|]];
diff --git a/crates/ide/src/move_item.rs b/crates/ide/src/move_item.rs
index d36dcd4e4..8d37f4f92 100644
--- a/crates/ide/src/move_item.rs
+++ b/crates/ide/src/move_item.rs
@@ -25,6 +25,8 @@ pub enum Direction {
25// | VS Code | **Rust Analyzer: Move item up** 25// | VS Code | **Rust Analyzer: Move item up**
26// | VS Code | **Rust Analyzer: Move item down** 26// | VS Code | **Rust Analyzer: Move item down**
27// |=== 27// |===
28//
29// image::https://user-images.githubusercontent.com/48062697/113065576-04298180-91b1-11eb-91ce-4505e99ed598.gif[]
28pub(crate) fn move_item( 30pub(crate) fn move_item(
29 db: &RootDatabase, 31 db: &RootDatabase,
30 range: FileRange, 32 range: FileRange,
diff --git a/crates/ide/src/parent_module.rs b/crates/ide/src/parent_module.rs
index 22b0d6ecb..99365c8a7 100644
--- a/crates/ide/src/parent_module.rs
+++ b/crates/ide/src/parent_module.rs
@@ -18,6 +18,8 @@ use crate::NavigationTarget;
18// 18//
19// | VS Code | **Rust Analyzer: Locate parent module** 19// | VS Code | **Rust Analyzer: Locate parent module**
20// |=== 20// |===
21//
22// image::https://user-images.githubusercontent.com/48062697/113065580-04c21800-91b1-11eb-9a32-00086161c0bd.gif[]
21 23
22/// This returns `Vec` because a module may be included from several places. 24/// This returns `Vec` because a module may be included from several places.
23pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> { 25pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> {
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 95ed8a045..11ca7ec6b 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -48,6 +48,8 @@ pub struct Declaration {
48// 48//
49// | VS Code | kbd:[Shift+Alt+F12] 49// | VS Code | kbd:[Shift+Alt+F12]
50// |=== 50// |===
51//
52// image::https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif[]
51pub(crate) fn find_all_refs( 53pub(crate) fn find_all_refs(
52 sema: &Semantics<RootDatabase>, 54 sema: &Semantics<RootDatabase>,
53 position: FilePosition, 55 position: FilePosition,
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 98456967a..2408a0181 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -70,6 +70,8 @@ pub(crate) fn prepare_rename(
70// 70//
71// | VS Code | kbd:[F2] 71// | VS Code | kbd:[F2]
72// |=== 72// |===
73//
74// image::https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif[]
73pub(crate) fn rename( 75pub(crate) fn rename(
74 db: &RootDatabase, 76 db: &RootDatabase,
75 position: FilePosition, 77 position: FilePosition,
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 11bd385bb..3eb9e27ee 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -98,6 +98,7 @@ impl Runnable {
98// 98//
99// | VS Code | **Rust Analyzer: Run** 99// | VS Code | **Rust Analyzer: Run**
100// |=== 100// |===
101// image::https://user-images.githubusercontent.com/48062697/113065583-055aae80-91b1-11eb-958f-d67efcaf6a2f.gif[]
101pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 102pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
102 let sema = Semantics::new(db); 103 let sema = Semantics::new(db);
103 104
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index 137c38c0d..49fde1945 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -31,6 +31,7 @@ fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
31// 31//
32// | VS Code | **Rust Analyzer: Status** 32// | VS Code | **Rust Analyzer: Status**
33// |=== 33// |===
34// image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
34pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String { 35pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
35 let mut buf = String::new(); 36 let mut buf = String::new();
36 format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>()); 37 format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>());
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 67a10766b..9df8d21af 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -48,6 +48,9 @@ pub struct HlRange {
48// 48//
49// The general rule is that a reference to an entity gets colored the same way as the entity itself. 49// The general rule is that a reference to an entity gets colored the same way as the entity itself.
50// We also give special modifier for `mut` and `&mut` local variables. 50// We also give special modifier for `mut` and `&mut` local variables.
51//
52// image::https://user-images.githubusercontent.com/48062697/113164457-06cfb980-9239-11eb-819b-0f93e646acf8.png[]
53// image::https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png[]
51pub(crate) fn highlight( 54pub(crate) fn highlight(
52 db: &RootDatabase, 55 db: &RootDatabase,
53 file_id: FileId, 56 file_id: FileId,
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index b0cfdd8b7..5ccb84714 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -1,6 +1,6 @@
1//! Computes color for a single element. 1//! Computes color for a single element.
2 2
3use hir::{AsAssocItem, Semantics, VariantDef}; 3use hir::{AsAssocItem, AssocItemContainer, Semantics, VariantDef};
4use ide_db::{ 4use ide_db::{
5 defs::{Definition, NameClass, NameRefClass}, 5 defs::{Definition, NameClass, NameRefClass},
6 RootDatabase, SymbolKind, 6 RootDatabase, SymbolKind,
@@ -275,12 +275,24 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
275 hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module), 275 hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module),
276 hir::ModuleDef::Function(func) => { 276 hir::ModuleDef::Function(func) => {
277 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); 277 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function));
278 if func.as_assoc_item(db).is_some() { 278 if let Some(item) = func.as_assoc_item(db) {
279 h |= HlMod::Associated; 279 h |= HlMod::Associated;
280 if func.self_param(db).is_none() { 280 if func.self_param(db).is_none() {
281 h |= HlMod::Static 281 h |= HlMod::Static
282 } 282 }
283
284 match item.container(db) {
285 AssocItemContainer::Impl(i) => {
286 if i.trait_(db).is_some() {
287 h |= HlMod::Trait;
288 }
289 }
290 AssocItemContainer::Trait(_t) => {
291 h |= HlMod::Trait;
292 }
293 }
283 } 294 }
295
284 if func.is_unsafe(db) { 296 if func.is_unsafe(db) {
285 h |= HlMod::Unsafe; 297 h |= HlMod::Unsafe;
286 } 298 }
@@ -292,9 +304,20 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
292 hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant), 304 hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant),
293 hir::ModuleDef::Const(konst) => { 305 hir::ModuleDef::Const(konst) => {
294 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); 306 let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const));
295 if konst.as_assoc_item(db).is_some() { 307 if let Some(item) = konst.as_assoc_item(db) {
296 h |= HlMod::Associated 308 h |= HlMod::Associated;
309 match item.container(db) {
310 AssocItemContainer::Impl(i) => {
311 if i.trait_(db).is_some() {
312 h |= HlMod::Trait;
313 }
314 }
315 AssocItemContainer::Trait(_t) => {
316 h |= HlMod::Trait;
317 }
318 }
297 } 319 }
320
298 return h; 321 return h;
299 } 322 }
300 hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait), 323 hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait),
@@ -362,6 +385,10 @@ fn highlight_method_call(
362 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { 385 if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
363 h |= HlMod::Unsafe; 386 h |= HlMod::Unsafe;
364 } 387 }
388 if func.as_assoc_item(sema.db).and_then(|it| it.containing_trait(sema.db)).is_some() {
389 h |= HlMod::Trait
390 }
391
365 if let Some(self_param) = func.self_param(sema.db) { 392 if let Some(self_param) = func.self_param(sema.db) {
366 match self_param.access(sema.db) { 393 match self_param.access(sema.db) {
367 hir::Access::Shared => (), 394 hir::Access::Shared => (),
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 93db79b89..1cec991aa 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -58,6 +58,8 @@ pub enum HlMod {
58 Associated, 58 Associated,
59 /// Used for intra doc links in doc injection. 59 /// Used for intra doc links in doc injection.
60 IntraDocLink, 60 IntraDocLink,
61 /// Used for items in traits and trait impls.
62 Trait,
61 63
62 /// Keep this last! 64 /// Keep this last!
63 Unsafe, 65 Unsafe,
@@ -158,6 +160,7 @@ impl HlMod {
158 HlMod::Callable, 160 HlMod::Callable,
159 HlMod::Static, 161 HlMod::Static,
160 HlMod::Associated, 162 HlMod::Associated,
163 HlMod::Trait,
161 HlMod::Unsafe, 164 HlMod::Unsafe,
162 ]; 165 ];
163 166
@@ -174,6 +177,7 @@ impl HlMod {
174 HlMod::IntraDocLink => "intra_doc_link", 177 HlMod::IntraDocLink => "intra_doc_link",
175 HlMod::Mutable => "mutable", 178 HlMod::Mutable => "mutable",
176 HlMod::Static => "static", 179 HlMod::Static => "static",
180 HlMod::Trait => "trait",
177 HlMod::Unsafe => "unsafe", 181 HlMod::Unsafe => "unsafe",
178 } 182 }
179 } 183 }
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 4635ea927..8cde3906c 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -47,12 +47,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
47<span class="brace">}</span> 47<span class="brace">}</span>
48 48
49<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> 49<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
50 <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 50 <span class="keyword">fn</span> <span class="function declaration static associated trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
51 <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 51 <span class="keyword">fn</span> <span class="function declaration associated trait">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
52<span class="brace">}</span> 52<span class="brace">}</span>
53 53
54<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> 54<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 55 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
56 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 56 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated trait">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
57<span class="brace">}</span> 57<span class="brace">}</span>
58 </code></pre> \ No newline at end of file 58 </code></pre> \ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 9215ddd9e..7c6694a27 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -42,7 +42,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
42<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> 42<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
43 <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> 43 <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span>
44 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> 44 <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span>
45 <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> 45 <span class="keyword">fn</span> <span class="function declaration static associated trait">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
46 <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> 46 <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span>
47 <span class="brace">}</span> 47 <span class="brace">}</span>
48 <span class="brace">}</span><span class="string_literal">"#</span> 48 <span class="brace">}</span><span class="string_literal">"#</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 6a6555208..72910421d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -62,11 +62,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
62<span class="brace">}</span> 62<span class="brace">}</span>
63 63
64<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> 64<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
65 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> 65 <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
66<span class="brace">}</span> 66<span class="brace">}</span>
67 67
68<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> 68<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
69 <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> 69 <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
70<span class="brace">}</span> 70<span class="brace">}</span>
71 71
72<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> 72<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -96,6 +96,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
96 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span> 96 <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span>
97 97
98 <span class="comment">// unsafe auto ref of packed field</span> 98 <span class="comment">// unsafe auto ref of packed field</span>
99 <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> 99 <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated trait unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
100 <span class="brace">}</span> 100 <span class="brace">}</span>
101<span class="brace">}</span></code></pre> \ No newline at end of file 101<span class="brace">}</span></code></pre> \ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
index 1eaa7b75b..973173254 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html
@@ -67,11 +67,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
67<span class="brace">}</span> 67<span class="brace">}</span>
68 68
69<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> 69<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
70 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span> 70 <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
71<span class="brace">}</span> 71<span class="brace">}</span>
72 72
73<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> 73<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
74 <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span> 74 <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
75 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> 75 <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
76 <span class="brace">}</span> 76 <span class="brace">}</span>
77<span class="brace">}</span> 77<span class="brace">}</span>
diff --git a/crates/ide/src/syntax_tree.rs b/crates/ide/src/syntax_tree.rs
index 8979de528..633878d1c 100644
--- a/crates/ide/src/syntax_tree.rs
+++ b/crates/ide/src/syntax_tree.rs
@@ -14,6 +14,7 @@ use syntax::{
14// 14//
15// | VS Code | **Rust Analyzer: Show Syntax Tree** 15// | VS Code | **Rust Analyzer: Show Syntax Tree**
16// |=== 16// |===
17// image::https://user-images.githubusercontent.com/48062697/113065586-068bdb80-91b1-11eb-9507-fee67f9f45a0.gif[]
17pub(crate) fn syntax_tree( 18pub(crate) fn syntax_tree(
18 db: &RootDatabase, 19 db: &RootDatabase,
19 file_id: FileId, 20 file_id: FileId,
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index e10b7d98e..11408d445 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -49,6 +49,9 @@ pub(crate) const TRIGGER_CHARS: &str = ".=>";
49// ---- 49// ----
50// "editor.formatOnType": true, 50// "editor.formatOnType": true,
51// ---- 51// ----
52//
53// image::https://user-images.githubusercontent.com/48062697/113166163-69758500-923a-11eb-81ee-eb33ec380399.gif[]
54// image::https://user-images.githubusercontent.com/48062697/113171066-105c2000-923f-11eb-87ab-f4a263346567.gif[]
52pub(crate) fn on_char_typed( 55pub(crate) fn on_char_typed(
53 db: &RootDatabase, 56 db: &RootDatabase,
54 position: FilePosition, 57 position: FilePosition,
diff --git a/crates/ide/src/typing/on_enter.rs b/crates/ide/src/typing/on_enter.rs
index 978c479de..9144681bf 100644
--- a/crates/ide/src/typing/on_enter.rs
+++ b/crates/ide/src/typing/on_enter.rs
@@ -32,6 +32,8 @@ use text_edit::TextEdit;
32// "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust" 32// "when": "editorTextFocus && !suggestWidgetVisible && editorLangId == rust"
33// } 33// }
34// ---- 34// ----
35//
36// image::https://user-images.githubusercontent.com/48062697/113065578-04c21800-91b1-11eb-82b8-22b8c481e645.gif[]
35pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> { 37pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<TextEdit> {
36 let parse = db.parse(position.file_id); 38 let parse = db.parse(position.file_id);
37 let file = parse.tree(); 39 let file = parse.tree();
diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs
index f8f3fae3d..7312afe53 100644
--- a/crates/ide/src/view_hir.rs
+++ b/crates/ide/src/view_hir.rs
@@ -10,6 +10,7 @@ use syntax::{algo::find_node_at_offset, ast, AstNode};
10// 10//
11// | VS Code | **Rust Analyzer: View Hir** 11// | VS Code | **Rust Analyzer: View Hir**
12// |=== 12// |===
13// image::https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif[]
13pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String { 14pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
14 body_hir(db, position).unwrap_or_else(|| "Not inside a function body".to_string()) 15 body_hir(db, position).unwrap_or_else(|| "Not inside a function body".to_string())
15} 16}
diff --git a/crates/ide_assists/src/assist_context.rs b/crates/ide_assists/src/assist_context.rs
index 1482d37f8..8714e4978 100644
--- a/crates/ide_assists/src/assist_context.rs
+++ b/crates/ide_assists/src/assist_context.rs
@@ -13,7 +13,7 @@ use ide_db::{
13 RootDatabase, 13 RootDatabase,
14}; 14};
15use syntax::{ 15use syntax::{
16 algo::{self, find_node_at_offset, SyntaxRewriter}, 16 algo::{self, find_node_at_offset, find_node_at_range, SyntaxRewriter},
17 AstNode, AstToken, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr, 17 AstNode, AstToken, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr,
18 SyntaxToken, TextRange, TextSize, TokenAtOffset, 18 SyntaxToken, TextRange, TextSize, TokenAtOffset,
19}; 19};
@@ -89,6 +89,9 @@ impl<'a> AssistContext<'a> {
89 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> { 89 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
90 find_node_at_offset(self.source_file.syntax(), self.offset()) 90 find_node_at_offset(self.source_file.syntax(), self.offset())
91 } 91 }
92 pub(crate) fn find_node_at_range<N: AstNode>(&self) -> Option<N> {
93 find_node_at_range(self.source_file.syntax(), self.frange.range)
94 }
92 pub(crate) fn find_node_at_offset_with_descend<N: AstNode>(&self) -> Option<N> { 95 pub(crate) fn find_node_at_offset_with_descend<N: AstNode>(&self) -> Option<N> {
93 self.sema.find_node_at_offset_with_descend(self.source_file.syntax(), self.offset()) 96 self.sema.find_node_at_offset_with_descend(self.source_file.syntax(), self.offset())
94 } 97 }
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 7019039b9..5ccd7f7a2 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -61,6 +61,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
61// - `plain`: This setting does not impose any restrictions in imports. 61// - `plain`: This setting does not impose any restrictions in imports.
62// 62//
63// In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`. 63// In `VS Code` the configuration for this is `rust-analyzer.assist.importPrefix`.
64//
65// image::https://user-images.githubusercontent.com/48062697/113020673-b85be580-917a-11eb-9022-59585f35d4f8.gif[]
64 66
65// Assist: auto_import 67// Assist: auto_import
66// 68//
diff --git a/crates/ide_assists/src/handlers/extract_type_alias.rs b/crates/ide_assists/src/handlers/extract_type_alias.rs
new file mode 100644
index 000000000..442a209b9
--- /dev/null
+++ b/crates/ide_assists/src/handlers/extract_type_alias.rs
@@ -0,0 +1,149 @@
1use syntax::ast::{self, AstNode};
2
3use crate::{AssistContext, AssistId, AssistKind, Assists};
4
5// Assist: extract_type_alias
6//
7// Extracts the selected type as a type alias.
8//
9// ```
10// struct S {
11// field: $0(u8, u8, u8)$0,
12// }
13// ```
14// ->
15// ```
16// type $0Type = (u8, u8, u8);
17//
18// struct S {
19// field: Type,
20// }
21// ```
22pub(crate) fn extract_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
23 if ctx.frange.range.is_empty() {
24 return None;
25 }
26
27 let node = ctx.find_node_at_range::<ast::Type>()?;
28 let insert = ctx.find_node_at_offset::<ast::Item>()?.syntax().text_range().start();
29 let target = node.syntax().text_range();
30
31 acc.add(
32 AssistId("extract_type_alias", AssistKind::RefactorExtract),
33 "Extract type as type alias",
34 target,
35 |builder| {
36 builder.edit_file(ctx.frange.file_id);
37 builder.replace(target, "Type");
38 match ctx.config.snippet_cap {
39 Some(cap) => {
40 builder.insert_snippet(cap, insert, format!("type $0Type = {};\n\n", node));
41 }
42 None => {
43 builder.insert(insert, format!("type Type = {};\n\n", node));
44 }
45 }
46 },
47 )
48}
49
50#[cfg(test)]
51mod tests {
52 use crate::tests::{check_assist, check_assist_not_applicable};
53
54 use super::*;
55
56 #[test]
57 fn test_not_applicable_without_selection() {
58 check_assist_not_applicable(
59 extract_type_alias,
60 r"
61struct S {
62 field: $0(u8, u8, u8),
63}
64 ",
65 );
66 }
67
68 #[test]
69 fn test_simple_types() {
70 check_assist(
71 extract_type_alias,
72 r"
73struct S {
74 field: $0u8$0,
75}
76 ",
77 r#"
78type $0Type = u8;
79
80struct S {
81 field: Type,
82}
83 "#,
84 );
85 }
86
87 #[test]
88 fn test_generic_type_arg() {
89 check_assist(
90 extract_type_alias,
91 r"
92fn generic<T>() {}
93
94fn f() {
95 generic::<$0()$0>();
96}
97 ",
98 r#"
99fn generic<T>() {}
100
101type $0Type = ();
102
103fn f() {
104 generic::<Type>();
105}
106 "#,
107 );
108 }
109
110 #[test]
111 fn test_inner_type_arg() {
112 check_assist(
113 extract_type_alias,
114 r"
115struct Vec<T> {}
116struct S {
117 v: Vec<Vec<$0Vec<u8>$0>>,
118}
119 ",
120 r#"
121struct Vec<T> {}
122type $0Type = Vec<u8>;
123
124struct S {
125 v: Vec<Vec<Type>>,
126}
127 "#,
128 );
129 }
130
131 #[test]
132 fn test_extract_inner_type() {
133 check_assist(
134 extract_type_alias,
135 r"
136struct S {
137 field: ($0u8$0,),
138}
139 ",
140 r#"
141type $0Type = u8;
142
143struct S {
144 field: (Type,),
145}
146 "#,
147 );
148 }
149}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 8c068a6c0..3d1dcef4c 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -121,6 +121,7 @@ mod handlers {
121 mod expand_glob_import; 121 mod expand_glob_import;
122 mod extract_function; 122 mod extract_function;
123 mod extract_struct_from_enum_variant; 123 mod extract_struct_from_enum_variant;
124 mod extract_type_alias;
124 mod extract_variable; 125 mod extract_variable;
125 mod fill_match_arms; 126 mod fill_match_arms;
126 mod fix_visibility; 127 mod fix_visibility;
@@ -187,6 +188,7 @@ mod handlers {
187 early_return::convert_to_guarded_return, 188 early_return::convert_to_guarded_return,
188 expand_glob_import::expand_glob_import, 189 expand_glob_import::expand_glob_import,
189 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 190 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
191 extract_type_alias::extract_type_alias,
190 fill_match_arms::fill_match_arms, 192 fill_match_arms::fill_match_arms,
191 fix_visibility::fix_visibility, 193 fix_visibility::fix_visibility,
192 flip_binexpr::flip_binexpr, 194 flip_binexpr::flip_binexpr,
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 736027ff0..03b7fb366 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -329,6 +329,25 @@ enum A { One(One) }
329} 329}
330 330
331#[test] 331#[test]
332fn doctest_extract_type_alias() {
333 check_doc_test(
334 "extract_type_alias",
335 r#####"
336struct S {
337 field: $0(u8, u8, u8)$0,
338}
339"#####,
340 r#####"
341type $0Type = (u8, u8, u8);
342
343struct S {
344 field: Type,
345}
346"#####,
347 )
348}
349
350#[test]
332fn doctest_extract_variable() { 351fn doctest_extract_variable() {
333 check_doc_test( 352 check_doc_test(
334 "extract_variable", 353 "extract_variable",
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs
index 3f1c6730b..e86ffa8f8 100644
--- a/crates/ide_completion/src/completions/postfix/format_like.rs
+++ b/crates/ide_completion/src/completions/postfix/format_like.rs
@@ -13,6 +13,8 @@
13// + `logi` -> `log::info!(...)` 13// + `logi` -> `log::info!(...)`
14// + `logw` -> `log::warn!(...)` 14// + `logw` -> `log::warn!(...)`
15// + `loge` -> `log::error!(...)` 15// + `loge` -> `log::error!(...)`
16//
17// image::https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif[]
16 18
17use ide_db::helpers::SnippetCap; 19use ide_db::helpers::SnippetCap;
18use syntax::ast::{self, AstToken}; 20use syntax::ast::{self, AstToken};
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 1891eb5b3..969249df6 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -24,7 +24,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
24 }; 24 };
25 25
26 // Add associated types on type parameters and `Self`. 26 // Add associated types on type parameters and `Self`.
27 resolution.assoc_type_shorthand_candidates(ctx.db, |alias| { 27 resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
28 acc.add_type_alias(ctx, alias); 28 acc.add_type_alias(ctx, alias);
29 None::<()> 29 None::<()>
30 }); 30 });
diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs
index 5ac1cb48d..831d543bb 100644
--- a/crates/ide_completion/src/lib.rs
+++ b/crates/ide_completion/src/lib.rs
@@ -81,6 +81,8 @@ pub use crate::{
81// And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities. 81// And the auto import completions, enabled with the `rust-analyzer.completion.autoimport.enable` setting and the corresponding LSP client capabilities.
82// Those are the additional completion options with automatic `use` import and options from all project importable items, 82// Those are the additional completion options with automatic `use` import and options from all project importable items,
83// fuzzy matched agains the completion imput. 83// fuzzy matched agains the completion imput.
84//
85// image::https://user-images.githubusercontent.com/48062697/113020667-b72ab880-917a-11eb-8778-716cf26a0eb3.gif[]
84 86
85/// Main entry point for completion. We run completion as a two-phase process. 87/// Main entry point for completion. We run completion as a two-phase process.
86/// 88///
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs
index 047a9b6bc..111e9325a 100644
--- a/crates/ide_db/src/apply_change.rs
+++ b/crates/ide_db/src/apply_change.rs
@@ -101,6 +101,7 @@ impl RootDatabase {
101 // 101 //
102 // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)** 102 // | VS Code | **Rust Analyzer: Memory Usage (Clears Database)**
103 // |=== 103 // |===
104 // image::https://user-images.githubusercontent.com/48062697/113065592-08559f00-91b1-11eb-8c96-64b88068ec02.gif[]
104 pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> { 105 pub fn per_query_memory_usage(&mut self) -> Vec<(String, Bytes)> {
105 let mut acc: Vec<(String, Bytes)> = vec![]; 106 let mut acc: Vec<(String, Bytes)> = vec![];
106 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); 107 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs
index c147484c0..5d765f6e2 100644
--- a/crates/proc_macro_srv/src/rustc_server.rs
+++ b/crates/proc_macro_srv/src/rustc_server.rs
@@ -534,8 +534,12 @@ impl server::Literal for Rustc {
534 } 534 }
535 535
536 fn integer(&mut self, n: &str) -> Self::Literal { 536 fn integer(&mut self, n: &str) -> Self::Literal {
537 let n: i128 = n.parse().unwrap(); 537 let n = if let Ok(n) = n.parse::<i128>() {
538 Literal { text: n.to_string().into(), id: tt::TokenId::unspecified() } 538 n.to_string()
539 } else {
540 n.parse::<u128>().unwrap().to_string()
541 };
542 return Literal { text: n.into(), id: tt::TokenId::unspecified() };
539 } 543 }
540 544
541 fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal { 545 fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
@@ -757,6 +761,17 @@ mod tests {
757 assert_eq!(srv.string("hello_world").text, "\"hello_world\""); 761 assert_eq!(srv.string("hello_world").text, "\"hello_world\"");
758 assert_eq!(srv.character('c').text, "'c'"); 762 assert_eq!(srv.character('c').text, "'c'");
759 assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\""); 763 assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\"");
764
765 // u128::max
766 assert_eq!(
767 srv.integer("340282366920938463463374607431768211455").text,
768 "340282366920938463463374607431768211455"
769 );
770 // i128::min
771 assert_eq!(
772 srv.integer("-170141183460469231731687303715884105728").text,
773 "-170141183460469231731687303715884105728"
774 );
760 } 775 }
761 776
762 #[test] 777 #[test]
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 85e67554c..53d29ddfc 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -84,7 +84,8 @@ pub(crate) fn handle_analyzer_status(
84 84
85pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> Result<String> { 85pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> Result<String> {
86 let _p = profile::span("handle_memory_usage"); 86 let _p = profile::span("handle_memory_usage");
87 let mem = state.analysis_host.per_query_memory_usage(); 87 let mut mem = state.analysis_host.per_query_memory_usage();
88 mem.push(("Remaining".into(), profile::memory_usage().allocated));
88 89
89 let mut out = String::new(); 90 let mut out = String::new();
90 for (name, bytes) in mem { 91 for (name, bytes) in mem {
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index a3c5e9ccf..2dc8a42f1 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -88,6 +88,7 @@ define_semantic_token_modifiers![
88 (CONSUMING, "consuming"), 88 (CONSUMING, "consuming"),
89 (UNSAFE, "unsafe"), 89 (UNSAFE, "unsafe"),
90 (ATTRIBUTE_MODIFIER, "attribute"), 90 (ATTRIBUTE_MODIFIER, "attribute"),
91 (TRAIT_MODIFIER, "trait"),
91 (CALLABLE, "callable"), 92 (CALLABLE, "callable"),
92 (INTRA_DOC_LINK, "intraDocLink"), 93 (INTRA_DOC_LINK, "intraDocLink"),
93]; 94];
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index e297a72e6..c3820944b 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -474,6 +474,7 @@ fn semantic_token_type_and_modifiers(
474 HlMod::Callable => semantic_tokens::CALLABLE, 474 HlMod::Callable => semantic_tokens::CALLABLE,
475 HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, 475 HlMod::Static => lsp_types::SemanticTokenModifier::STATIC,
476 HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, 476 HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK,
477 HlMod::Trait => semantic_tokens::TRAIT_MODIFIER,
477 HlMod::Associated => continue, 478 HlMod::Associated => continue,
478 }; 479 };
479 mods |= modifier; 480 mods |= modifier;
diff --git a/editors/code/src/snippets.ts b/editors/code/src/snippets.ts
index dc53ebe2e..9561aa345 100644
--- a/editors/code/src/snippets.ts
+++ b/editors/code/src/snippets.ts
@@ -29,7 +29,7 @@ async function editorFromUri(uri: vscode.Uri): Promise<vscode.TextEditor | undef
29} 29}
30 30
31export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) { 31export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vscode.TextEdit[]) {
32 let selection: vscode.Selection | undefined = undefined; 32 const selections: vscode.Selection[] = [];
33 let lineDelta = 0; 33 let lineDelta = 0;
34 await editor.edit((builder) => { 34 await editor.edit((builder) => {
35 for (const indel of edits) { 35 for (const indel of edits) {
@@ -44,18 +44,18 @@ export async function applySnippetTextEdits(editor: vscode.TextEditor, edits: vs
44 indel.range.start.character + placeholderStart 44 indel.range.start.character + placeholderStart
45 : prefix.length - lastNewline - 1; 45 : prefix.length - lastNewline - 1;
46 const endColumn = startColumn + placeholderLength; 46 const endColumn = startColumn + placeholderLength;
47 selection = new vscode.Selection( 47 selections.push(new vscode.Selection(
48 new vscode.Position(startLine, startColumn), 48 new vscode.Position(startLine, startColumn),
49 new vscode.Position(startLine, endColumn), 49 new vscode.Position(startLine, endColumn),
50 ); 50 ));
51 builder.replace(indel.range, newText); 51 builder.replace(indel.range, newText);
52 } else { 52 } else {
53 lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line);
54 builder.replace(indel.range, indel.newText); 53 builder.replace(indel.range, indel.newText);
55 } 54 }
55 lineDelta = countLines(indel.newText) - (indel.range.end.line - indel.range.start.line);
56 } 56 }
57 }); 57 });
58 if (selection) editor.selection = selection; 58 if (selections.length > 0) editor.selections = selections;
59} 59}
60 60
61function parseSnippet(snip: string): [string, [number, number]] | undefined { 61function parseSnippet(snip: string): [string, [number, number]] | undefined {