aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/assist_ctx.rs30
-rw-r--r--crates/ra_assists/src/handlers/auto_import.rs42
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--crates/ra_assists/src/utils.rs2
-rw-r--r--crates/ra_assists/src/utils/insert_use.rs9
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs2
-rw-r--r--crates/rust-analyzer/src/caps.rs7
-rw-r--r--crates/rust-analyzer/src/main_loop.rs18
-rw-r--r--docs/dev/debugging.md8
-rw-r--r--xtask/src/ast_src.rs4
10 files changed, 97 insertions, 27 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 2fe7c3de3..da2880037 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -105,7 +105,7 @@ impl<'a> AssistCtx<'a> {
105 let mut info = AssistInfo::new(label); 105 let mut info = AssistInfo::new(label);
106 if self.should_compute_edit { 106 if self.should_compute_edit {
107 let action = { 107 let action = {
108 let mut edit = ActionBuilder::default(); 108 let mut edit = ActionBuilder::new(&self);
109 f(&mut edit); 109 f(&mut edit);
110 edit.build() 110 edit.build()
111 }; 111 };
@@ -130,6 +130,12 @@ impl<'a> AssistCtx<'a> {
130 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> { 130 pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> {
131 find_node_at_offset(self.source_file.syntax(), self.frange.range.start()) 131 find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
132 } 132 }
133
134 pub(crate) fn find_node_at_offset_with_descend<N: AstNode>(&self) -> Option<N> {
135 self.sema
136 .find_node_at_offset_with_descend(self.source_file.syntax(), self.frange.range.start())
137 }
138
133 pub(crate) fn covering_element(&self) -> SyntaxElement { 139 pub(crate) fn covering_element(&self) -> SyntaxElement {
134 find_covering_element(self.source_file.syntax(), self.frange.range) 140 find_covering_element(self.source_file.syntax(), self.frange.range)
135 } 141 }
@@ -156,7 +162,7 @@ impl<'a> AssistGroup<'a> {
156 let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone())); 162 let mut info = AssistInfo::new(label).with_group(GroupLabel(self.group_name.clone()));
157 if self.ctx.should_compute_edit { 163 if self.ctx.should_compute_edit {
158 let action = { 164 let action = {
159 let mut edit = ActionBuilder::default(); 165 let mut edit = ActionBuilder::new(&self.ctx);
160 f(&mut edit); 166 f(&mut edit);
161 edit.build() 167 edit.build()
162 }; 168 };
@@ -175,15 +181,29 @@ impl<'a> AssistGroup<'a> {
175 } 181 }
176} 182}
177 183
178#[derive(Default)] 184pub(crate) struct ActionBuilder<'a, 'b> {
179pub(crate) struct ActionBuilder {
180 edit: TextEditBuilder, 185 edit: TextEditBuilder,
181 cursor_position: Option<TextSize>, 186 cursor_position: Option<TextSize>,
182 target: Option<TextRange>, 187 target: Option<TextRange>,
183 file: AssistFile, 188 file: AssistFile,
189 ctx: &'a AssistCtx<'b>,
184} 190}
185 191
186impl ActionBuilder { 192impl<'a, 'b> ActionBuilder<'a, 'b> {
193 fn new(ctx: &'a AssistCtx<'b>) -> Self {
194 Self {
195 edit: TextEditBuilder::default(),
196 cursor_position: None,
197 target: None,
198 file: AssistFile::default(),
199 ctx,
200 }
201 }
202
203 pub(crate) fn ctx(&self) -> &AssistCtx<'b> {
204 &self.ctx
205 }
206
187 /// Replaces specified `range` of text with a given string. 207 /// Replaces specified `range` of text with a given string.
188 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { 208 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
189 self.edit.replace(range, replace_with.into()) 209 self.edit.replace(range, replace_with.into())
diff --git a/crates/ra_assists/src/handlers/auto_import.rs b/crates/ra_assists/src/handlers/auto_import.rs
index 99682e023..db6c4d2fa 100644
--- a/crates/ra_assists/src/handlers/auto_import.rs
+++ b/crates/ra_assists/src/handlers/auto_import.rs
@@ -45,15 +45,12 @@ pub(crate) fn auto_import(ctx: AssistCtx) -> Option<Assist> {
45 return None; 45 return None;
46 } 46 }
47 47
48 let range = ctx.sema.original_range(&auto_import_assets.syntax_under_caret).range;
48 let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message()); 49 let mut group = ctx.add_assist_group(auto_import_assets.get_import_group_message());
49 for import in proposed_imports { 50 for import in proposed_imports {
50 group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| { 51 group.add_assist(AssistId("auto_import"), format!("Import `{}`", &import), |edit| {
51 edit.target(auto_import_assets.syntax_under_caret.text_range()); 52 edit.target(range);
52 insert_use_statement( 53 insert_use_statement(&auto_import_assets.syntax_under_caret, &import, edit);
53 &auto_import_assets.syntax_under_caret,
54 &import,
55 edit.text_edit_builder(),
56 );
57 }); 54 });
58 } 55 }
59 group.finish() 56 group.finish()
@@ -68,10 +65,10 @@ struct AutoImportAssets {
68 65
69impl AutoImportAssets { 66impl AutoImportAssets {
70 fn new(ctx: &AssistCtx) -> Option<Self> { 67 fn new(ctx: &AssistCtx) -> Option<Self> {
71 if let Some(path_under_caret) = ctx.find_node_at_offset::<ast::Path>() { 68 if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() {
72 Self::for_regular_path(path_under_caret, &ctx) 69 Self::for_regular_path(path_under_caret, &ctx)
73 } else { 70 } else {
74 Self::for_method_call(ctx.find_node_at_offset()?, &ctx) 71 Self::for_method_call(ctx.find_node_at_offset_with_descend()?, &ctx)
75 } 72 }
76 } 73 }
77 74
@@ -306,6 +303,35 @@ mod tests {
306 } 303 }
307 304
308 #[test] 305 #[test]
306 fn applicable_when_found_an_import_in_macros() {
307 check_assist(
308 auto_import,
309 r"
310 macro_rules! foo {
311 ($i:ident) => { fn foo(a: $i) {} }
312 }
313 foo!(Pub<|>Struct);
314
315 pub mod PubMod {
316 pub struct PubStruct;
317 }
318 ",
319 r"
320 use PubMod::PubStruct;
321
322 macro_rules! foo {
323 ($i:ident) => { fn foo(a: $i) {} }
324 }
325 foo!(Pub<|>Struct);
326
327 pub mod PubMod {
328 pub struct PubStruct;
329 }
330 ",
331 );
332 }
333
334 #[test]
309 fn auto_imports_are_merged() { 335 fn auto_imports_are_merged() {
310 check_assist( 336 check_assist(
311 auto_import, 337 auto_import,
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
index 918e8dd8d..ff2463c77 100644
--- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -38,7 +38,7 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist>
38 "Replace qualified path with use", 38 "Replace qualified path with use",
39 |edit| { 39 |edit| {
40 let path_to_import = hir_path.mod_path().clone(); 40 let path_to_import = hir_path.mod_path().clone();
41 insert_use_statement(path.syntax(), &path_to_import, edit.text_edit_builder()); 41 insert_use_statement(path.syntax(), &path_to_import, edit);
42 42
43 if let Some(last) = path.segment() { 43 if let Some(last) = path.segment() {
44 // Here we are assuming the assist will provide a correct use statement 44 // Here we are assuming the assist will provide a correct use statement
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index efd988697..6be704ce3 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use rustc_hash::FxHashSet; 12use rustc_hash::FxHashSet;
13 13
14pub use insert_use::insert_use_statement; 14pub(crate) use insert_use::insert_use_statement;
15 15
16pub fn get_missing_impl_items( 16pub fn get_missing_impl_items(
17 sema: &Semantics<RootDatabase>, 17 sema: &Semantics<RootDatabase>,
diff --git a/crates/ra_assists/src/utils/insert_use.rs b/crates/ra_assists/src/utils/insert_use.rs
index c507e71e0..c1f447efe 100644
--- a/crates/ra_assists/src/utils/insert_use.rs
+++ b/crates/ra_assists/src/utils/insert_use.rs
@@ -2,6 +2,7 @@
2// FIXME: rewrite according to the plan, outlined in 2// FIXME: rewrite according to the plan, outlined in
3// https://github.com/rust-analyzer/rust-analyzer/issues/3301#issuecomment-592931553 3// https://github.com/rust-analyzer/rust-analyzer/issues/3301#issuecomment-592931553
4 4
5use crate::assist_ctx::ActionBuilder;
5use hir::{self, ModPath}; 6use hir::{self, ModPath};
6use ra_syntax::{ 7use ra_syntax::{
7 ast::{self, NameOwner}, 8 ast::{self, NameOwner},
@@ -14,14 +15,14 @@ use ra_text_edit::TextEditBuilder;
14/// Creates and inserts a use statement for the given path to import. 15/// Creates and inserts a use statement for the given path to import.
15/// The use statement is inserted in the scope most appropriate to the 16/// The use statement is inserted in the scope most appropriate to the
16/// the cursor position given, additionally merged with the existing use imports. 17/// the cursor position given, additionally merged with the existing use imports.
17pub fn insert_use_statement( 18pub(crate) fn insert_use_statement(
18 // Ideally the position of the cursor, used to 19 // Ideally the position of the cursor, used to
19 position: &SyntaxNode, 20 position: &SyntaxNode,
20 path_to_import: &ModPath, 21 path_to_import: &ModPath,
21 edit: &mut TextEditBuilder, 22 edit: &mut ActionBuilder,
22) { 23) {
23 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>(); 24 let target = path_to_import.to_string().split("::").map(SmolStr::new).collect::<Vec<_>>();
24 let container = position.ancestors().find_map(|n| { 25 let container = edit.ctx().sema.ancestors_with_macros(position.clone()).find_map(|n| {
25 if let Some(module) = ast::Module::cast(n.clone()) { 26 if let Some(module) = ast::Module::cast(n.clone()) {
26 return module.item_list().map(|it| it.syntax().clone()); 27 return module.item_list().map(|it| it.syntax().clone());
27 } 28 }
@@ -30,7 +31,7 @@ pub fn insert_use_statement(
30 31
31 if let Some(container) = container { 32 if let Some(container) = container {
32 let action = best_action_for_target(container, position.clone(), &target); 33 let action = best_action_for_target(container, position.clone(), &target);
33 make_assist(&action, &target, edit); 34 make_assist(&action, &target, edit.text_edit_builder());
34 } 35 }
35} 36}
36 37
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index 5e844d5ae..c2cc25958 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -12,6 +12,7 @@ pub struct SourceFile {
12} 12}
13impl ast::ModuleItemOwner for SourceFile {} 13impl ast::ModuleItemOwner for SourceFile {}
14impl ast::AttrsOwner for SourceFile {} 14impl ast::AttrsOwner for SourceFile {}
15impl ast::DocCommentsOwner for SourceFile {}
15impl SourceFile { 16impl SourceFile {
16 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) } 17 pub fn modules(&self) -> AstChildren<Module> { support::children(&self.syntax) }
17} 18}
@@ -259,6 +260,7 @@ pub struct ImplDef {
259} 260}
260impl ast::TypeParamsOwner for ImplDef {} 261impl ast::TypeParamsOwner for ImplDef {}
261impl ast::AttrsOwner for ImplDef {} 262impl ast::AttrsOwner for ImplDef {}
263impl ast::DocCommentsOwner for ImplDef {}
262impl ImplDef { 264impl ImplDef {
263 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) } 265 pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
264 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } 266 pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 44222d8bd..680415cac 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -1,4 +1,5 @@
1//! Advertizes the capabilities of the LSP Server. 1//! Advertizes the capabilities of the LSP Server.
2use std::env;
2 3
3use crate::semantic_tokens; 4use crate::semantic_tokens;
4 5
@@ -16,7 +17,11 @@ pub fn server_capabilities() -> ServerCapabilities {
16 ServerCapabilities { 17 ServerCapabilities {
17 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions { 18 text_document_sync: Some(TextDocumentSyncCapability::Options(TextDocumentSyncOptions {
18 open_close: Some(true), 19 open_close: Some(true),
19 change: Some(TextDocumentSyncKind::Incremental), 20 change: Some(if env::var("RA_PROFILE").is_ok() {
21 TextDocumentSyncKind::Incremental
22 } else {
23 TextDocumentSyncKind::Full
24 }),
20 will_save: None, 25 will_save: None,
21 will_save_wait_until: None, 26 will_save_wait_until: None,
22 save: Some(SaveOptions::default()), 27 save: Some(SaveOptions::default()),
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 3bc2e0a46..401fae755 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -666,6 +666,10 @@ fn apply_document_changes(
666 mut line_index: Cow<'_, LineIndex>, 666 mut line_index: Cow<'_, LineIndex>,
667 content_changes: Vec<TextDocumentContentChangeEvent>, 667 content_changes: Vec<TextDocumentContentChangeEvent>,
668) { 668) {
669 // Remove when https://github.com/rust-analyzer/rust-analyzer/issues/4263 is fixed.
670 let backup_text = old_text.clone();
671 let backup_changes = content_changes.clone();
672
669 // The changes we got must be applied sequentially, but can cross lines so we 673 // The changes we got must be applied sequentially, but can cross lines so we
670 // have to keep our line index updated. 674 // have to keep our line index updated.
671 // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we 675 // Some clients (e.g. Code) sort the ranges in reverse. As an optimization, we
@@ -693,7 +697,19 @@ fn apply_document_changes(
693 } 697 }
694 index_valid = IndexValid::UpToLine(range.start.line); 698 index_valid = IndexValid::UpToLine(range.start.line);
695 let range = range.conv_with(&line_index); 699 let range = range.conv_with(&line_index);
696 old_text.replace_range(Range::<usize>::from(range), &change.text); 700 let mut text = old_text.to_owned();
701 match std::panic::catch_unwind(move || {
702 text.replace_range(Range::<usize>::from(range), &change.text);
703 text
704 }) {
705 Ok(t) => *old_text = t,
706 Err(e) => {
707 eprintln!("Bug in incremental text synchronization. Please report the following output on https://github.com/rust-analyzer/rust-analyzer/issues/4263");
708 dbg!(&backup_text);
709 dbg!(&backup_changes);
710 std::panic::resume_unwind(e);
711 }
712 }
697 } 713 }
698 None => { 714 None => {
699 *old_text = change.text; 715 *old_text = change.text;
diff --git a/docs/dev/debugging.md b/docs/dev/debugging.md
index bece6a572..1aa392935 100644
--- a/docs/dev/debugging.md
+++ b/docs/dev/debugging.md
@@ -26,7 +26,7 @@ where **only** the `rust-analyzer` extension being debugged is enabled.
26- `Run Extension (Dev Server)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`). 26- `Run Extension (Dev Server)` - runs extension with the locally built LSP server (`target/debug/rust-analyzer`).
27 27
28TypeScript debugging is configured to watch your source edits and recompile. 28TypeScript debugging is configured to watch your source edits and recompile.
29To apply changes to an already running debug process press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]` 29To apply changes to an already running debug process, press <kbd>Ctrl+Shift+P</kbd> and run the following command in your `[Extension Development Host]`
30 30
31``` 31```
32> Developer: Reload Window 32> Developer: Reload Window
@@ -76,11 +76,11 @@ Make sure you open a rust file in the `[Extension Development Host]` and try aga
76 76
77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`. 77Make sure you have run `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`.
78 78
79By default this should reset back to 1 everytime you log in. 79By default this should reset back to 1 every time you log in.
80 80
81### Breakpoints are never being hit 81### Breakpoints are never being hit
82 82
83Check your version of `lldb` if it's version 6 and lower use the `classic` adapter type. 83Check your version of `lldb`. If it's version 6 and lower, use the `classic` adapter type.
84It's `lldb.adapterType` in settings file. 84It's `lldb.adapterType` in settings file.
85 85
86If you're running `lldb` version 7 change the lldb adapter type to `bundled` or `native`. 86If you're running `lldb` version 7, change the lldb adapter type to `bundled` or `native`.
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 028f7cbe1..2f8065b73 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -305,7 +305,7 @@ macro_rules! ast_enums {
305pub(crate) const AST_SRC: AstSrc = AstSrc { 305pub(crate) const AST_SRC: AstSrc = AstSrc {
306 tokens: &["Whitespace", "Comment", "String", "RawString"], 306 tokens: &["Whitespace", "Comment", "String", "RawString"],
307 nodes: &ast_nodes! { 307 nodes: &ast_nodes! {
308 struct SourceFile: ModuleItemOwner, AttrsOwner { 308 struct SourceFile: ModuleItemOwner, AttrsOwner, DocCommentsOwner {
309 modules: [Module], 309 modules: [Module],
310 } 310 }
311 311
@@ -401,7 +401,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
401 T![;] 401 T![;]
402 } 402 }
403 403
404 struct ImplDef: TypeParamsOwner, AttrsOwner { 404 struct ImplDef: TypeParamsOwner, AttrsOwner, DocCommentsOwner {
405 T![default], 405 T![default],
406 T![const], 406 T![const],
407 T![unsafe], 407 T![unsafe],