aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_db/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_db/src')
-rw-r--r--crates/ra_ide_db/src/defs.rs20
-rw-r--r--crates/ra_ide_db/src/lib.rs1
-rw-r--r--crates/ra_ide_db/src/line_index.rs17
-rw-r--r--crates/ra_ide_db/src/line_index_utils.rs6
-rw-r--r--crates/ra_ide_db/src/marks.rs1
-rw-r--r--crates/ra_ide_db/src/source_change.rs120
6 files changed, 158 insertions, 7 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index 7cd2384e9..f990e3bb9 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -6,7 +6,7 @@
6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). 6// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
7 7
8use hir::{ 8use hir::{
9 Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution, 9 Adt, Field, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, Name, PathResolution,
10 Semantics, TypeParam, Visibility, 10 Semantics, TypeParam, Visibility,
11}; 11};
12use ra_prof::profile; 12use ra_prof::profile;
@@ -47,7 +47,13 @@ impl Definition {
47 match self { 47 match self {
48 Definition::Macro(_) => None, 48 Definition::Macro(_) => None,
49 Definition::Field(sf) => Some(sf.visibility(db)), 49 Definition::Field(sf) => Some(sf.visibility(db)),
50 Definition::ModuleDef(def) => module?.visibility_of(db, def), 50 Definition::ModuleDef(def) => match def {
51 ModuleDef::EnumVariant(id) => {
52 let parent = id.parent_enum(db);
53 module?.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)))
54 }
55 _ => module?.visibility_of(db, def),
56 },
51 Definition::SelfType(_) => None, 57 Definition::SelfType(_) => None,
52 Definition::Local(_) => None, 58 Definition::Local(_) => None,
53 Definition::TypeParam(_) => None, 59 Definition::TypeParam(_) => None,
@@ -119,6 +125,16 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti
119 125
120 match_ast! { 126 match_ast! {
121 match parent { 127 match parent {
128 ast::Alias(it) => {
129 tested_by!(goto_def_for_use_alias; force);
130 let use_tree = it.syntax().parent().and_then(ast::UseTree::cast)?;
131 let path = use_tree.path()?;
132 let path_segment = path.segment()?;
133 let name_ref = path_segment.name_ref()?;
134 let name_ref_class = classify_name_ref(sema, &name_ref)?;
135
136 Some(name_ref_class.definition())
137 },
122 ast::BindPat(it) => { 138 ast::BindPat(it) => {
123 let local = sema.to_def(&it)?; 139 let local = sema.to_def(&it)?;
124 Some(Definition::Local(local)) 140 Some(Definition::Local(local))
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs
index e6f2d36e9..52fcd7b6f 100644
--- a/crates/ra_ide_db/src/lib.rs
+++ b/crates/ra_ide_db/src/lib.rs
@@ -10,6 +10,7 @@ pub mod change;
10pub mod defs; 10pub mod defs;
11pub mod search; 11pub mod search;
12pub mod imports_locator; 12pub mod imports_locator;
13pub mod source_change;
13mod wasm_shims; 14mod wasm_shims;
14 15
15use std::sync::Arc; 16use std::sync::Arc;
diff --git a/crates/ra_ide_db/src/line_index.rs b/crates/ra_ide_db/src/line_index.rs
index 212cb7b5b..c7c744fce 100644
--- a/crates/ra_ide_db/src/line_index.rs
+++ b/crates/ra_ide_db/src/line_index.rs
@@ -31,9 +31,19 @@ pub(crate) struct Utf16Char {
31} 31}
32 32
33impl Utf16Char { 33impl Utf16Char {
34 /// Returns the length in 8-bit UTF-8 code units.
34 fn len(&self) -> TextSize { 35 fn len(&self) -> TextSize {
35 self.end - self.start 36 self.end - self.start
36 } 37 }
38
39 /// Returns the length in 16-bit UTF-16 code units.
40 fn len_utf16(&self) -> usize {
41 if self.len() == TextSize::from(4) {
42 2
43 } else {
44 1
45 }
46 }
37} 47}
38 48
39impl LineIndex { 49impl LineIndex {
@@ -110,7 +120,7 @@ impl LineIndex {
110 if let Some(utf16_chars) = self.utf16_lines.get(&line) { 120 if let Some(utf16_chars) = self.utf16_lines.get(&line) {
111 for c in utf16_chars { 121 for c in utf16_chars {
112 if c.end <= col { 122 if c.end <= col {
113 res -= usize::from(c.len()) - 1; 123 res -= usize::from(c.len()) - c.len_utf16();
114 } else { 124 } else {
115 // From here on, all utf16 characters come *after* the character we are mapping, 125 // From here on, all utf16 characters come *after* the character we are mapping,
116 // so we don't need to take them into account 126 // so we don't need to take them into account
@@ -125,7 +135,7 @@ impl LineIndex {
125 if let Some(utf16_chars) = self.utf16_lines.get(&line) { 135 if let Some(utf16_chars) = self.utf16_lines.get(&line) {
126 for c in utf16_chars { 136 for c in utf16_chars {
127 if col > u32::from(c.start) { 137 if col > u32::from(c.start) {
128 col += u32::from(c.len()) - 1; 138 col += u32::from(c.len()) - c.len_utf16() as u32;
129 } else { 139 } else {
130 // From here on, all utf16 characters come *after* the character we are mapping, 140 // From here on, all utf16 characters come *after* the character we are mapping,
131 // so we don't need to take them into account 141 // so we don't need to take them into account
@@ -204,6 +214,9 @@ const C: char = 'メ';
204 214
205 // UTF-16 to UTF-8 215 // UTF-16 to UTF-8
206 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21)); 216 assert_eq!(col_index.utf16_to_utf8_col(1, 19), TextSize::from(21));
217
218 let col_index = LineIndex::new("a𐐏b");
219 assert_eq!(col_index.utf16_to_utf8_col(0, 3), TextSize::from(5));
207 } 220 }
208 221
209 #[test] 222 #[test]
diff --git a/crates/ra_ide_db/src/line_index_utils.rs b/crates/ra_ide_db/src/line_index_utils.rs
index 039a12c0d..7fa6fc448 100644
--- a/crates/ra_ide_db/src/line_index_utils.rs
+++ b/crates/ra_ide_db/src/line_index_utils.rs
@@ -10,7 +10,7 @@
10use std::convert::TryInto; 10use std::convert::TryInto;
11 11
12use ra_syntax::{TextRange, TextSize}; 12use ra_syntax::{TextRange, TextSize};
13use ra_text_edit::{AtomTextEdit, TextEdit}; 13use ra_text_edit::{Indel, TextEdit};
14 14
15use crate::line_index::{LineCol, LineIndex, Utf16Char}; 15use crate::line_index::{LineCol, LineIndex, Utf16Char};
16 16
@@ -182,14 +182,14 @@ struct TranslatedEdit<'a> {
182} 182}
183 183
184struct Edits<'a> { 184struct Edits<'a> {
185 edits: &'a [AtomTextEdit], 185 edits: &'a [Indel],
186 current: Option<TranslatedEdit<'a>>, 186 current: Option<TranslatedEdit<'a>>,
187 acc_diff: i64, 187 acc_diff: i64,
188} 188}
189 189
190impl<'a> Edits<'a> { 190impl<'a> Edits<'a> {
191 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> { 191 fn from_text_edit(text_edit: &'a TextEdit) -> Edits<'a> {
192 let mut x = Edits { edits: text_edit.as_atoms(), current: None, acc_diff: 0 }; 192 let mut x = Edits { edits: text_edit.as_indels(), current: None, acc_diff: 0 };
193 x.advance_edit(); 193 x.advance_edit();
194 x 194 x
195 } 195 }
diff --git a/crates/ra_ide_db/src/marks.rs b/crates/ra_ide_db/src/marks.rs
index 03b4be21c..386fe605c 100644
--- a/crates/ra_ide_db/src/marks.rs
+++ b/crates/ra_ide_db/src/marks.rs
@@ -2,6 +2,7 @@
2 2
3test_utils::marks![ 3test_utils::marks![
4 goto_def_for_macros 4 goto_def_for_macros
5 goto_def_for_use_alias
5 goto_def_for_methods 6 goto_def_for_methods
6 goto_def_for_fields 7 goto_def_for_fields
7 goto_def_for_record_fields 8 goto_def_for_record_fields
diff --git a/crates/ra_ide_db/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs
new file mode 100644
index 000000000..af81a91a4
--- /dev/null
+++ b/crates/ra_ide_db/src/source_change.rs
@@ -0,0 +1,120 @@
1//! This modules defines type to represent changes to the source code, that flow
2//! from the server to the client.
3//!
4//! It can be viewed as a dual for `AnalysisChange`.
5
6use ra_db::{FileId, FilePosition, RelativePathBuf, SourceRootId};
7use ra_text_edit::{TextEdit, TextSize};
8
9#[derive(Debug, Clone)]
10pub struct SourceChange {
11 /// For display in the undo log in the editor
12 pub label: String,
13 pub source_file_edits: Vec<SourceFileEdit>,
14 pub file_system_edits: Vec<FileSystemEdit>,
15 pub cursor_position: Option<FilePosition>,
16}
17
18impl SourceChange {
19 /// Creates a new SourceChange with the given label
20 /// from the edits.
21 pub fn from_edits<L: Into<String>>(
22 label: L,
23 source_file_edits: Vec<SourceFileEdit>,
24 file_system_edits: Vec<FileSystemEdit>,
25 ) -> Self {
26 SourceChange {
27 label: label.into(),
28 source_file_edits,
29 file_system_edits,
30 cursor_position: None,
31 }
32 }
33
34 /// Creates a new SourceChange with the given label,
35 /// containing only the given `SourceFileEdits`.
36 pub fn source_file_edits<L: Into<String>>(label: L, edits: Vec<SourceFileEdit>) -> Self {
37 let label = label.into();
38 assert!(label.starts_with(char::is_uppercase));
39 SourceChange {
40 label: label,
41 source_file_edits: edits,
42 file_system_edits: vec![],
43 cursor_position: None,
44 }
45 }
46
47 /// Creates a new SourceChange with the given label,
48 /// containing only the given `FileSystemEdits`.
49 pub(crate) fn file_system_edits<L: Into<String>>(label: L, edits: Vec<FileSystemEdit>) -> Self {
50 SourceChange {
51 label: label.into(),
52 source_file_edits: vec![],
53 file_system_edits: edits,
54 cursor_position: None,
55 }
56 }
57
58 /// Creates a new SourceChange with the given label,
59 /// containing only a single `SourceFileEdit`.
60 pub fn source_file_edit<L: Into<String>>(label: L, edit: SourceFileEdit) -> Self {
61 SourceChange::source_file_edits(label, vec![edit])
62 }
63
64 /// Creates a new SourceChange with the given label
65 /// from the given `FileId` and `TextEdit`
66 pub fn source_file_edit_from<L: Into<String>>(
67 label: L,
68 file_id: FileId,
69 edit: TextEdit,
70 ) -> Self {
71 SourceChange::source_file_edit(label, SourceFileEdit { file_id, edit })
72 }
73
74 /// Creates a new SourceChange with the given label
75 /// from the given `FileId` and `TextEdit`
76 pub fn file_system_edit<L: Into<String>>(label: L, edit: FileSystemEdit) -> Self {
77 SourceChange::file_system_edits(label, vec![edit])
78 }
79
80 /// Sets the cursor position to the given `FilePosition`
81 pub fn with_cursor(mut self, cursor_position: FilePosition) -> Self {
82 self.cursor_position = Some(cursor_position);
83 self
84 }
85
86 /// Sets the cursor position to the given `FilePosition`
87 pub fn with_cursor_opt(mut self, cursor_position: Option<FilePosition>) -> Self {
88 self.cursor_position = cursor_position;
89 self
90 }
91}
92
93#[derive(Debug, Clone)]
94pub struct SourceFileEdit {
95 pub file_id: FileId,
96 pub edit: TextEdit,
97}
98
99#[derive(Debug, Clone)]
100pub enum FileSystemEdit {
101 CreateFile { source_root: SourceRootId, path: RelativePathBuf },
102 MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf },
103}
104
105pub struct SingleFileChange {
106 pub label: String,
107 pub edit: TextEdit,
108 pub cursor_position: Option<TextSize>,
109}
110
111impl SingleFileChange {
112 pub fn into_source_change(self, file_id: FileId) -> SourceChange {
113 SourceChange {
114 label: self.label,
115 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }],
116 file_system_edits: Vec::new(),
117 cursor_position: self.cursor_position.map(|offset| FilePosition { file_id, offset }),
118 }
119 }
120}