diff options
Diffstat (limited to 'crates/ra_ide_db/src')
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide_db/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_db/src/line_index.rs | 17 | ||||
-rw-r--r-- | crates/ra_ide_db/src/line_index_utils.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide_db/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_db/src/source_change.rs | 120 |
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 | ||
8 | use hir::{ | 8 | use 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 | }; |
12 | use ra_prof::profile; | 12 | use 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; | |||
10 | pub mod defs; | 10 | pub mod defs; |
11 | pub mod search; | 11 | pub mod search; |
12 | pub mod imports_locator; | 12 | pub mod imports_locator; |
13 | pub mod source_change; | ||
13 | mod wasm_shims; | 14 | mod wasm_shims; |
14 | 15 | ||
15 | use std::sync::Arc; | 16 | use 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 | ||
33 | impl Utf16Char { | 33 | impl 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 | ||
39 | impl LineIndex { | 49 | impl 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 @@ | |||
10 | use std::convert::TryInto; | 10 | use std::convert::TryInto; |
11 | 11 | ||
12 | use ra_syntax::{TextRange, TextSize}; | 12 | use ra_syntax::{TextRange, TextSize}; |
13 | use ra_text_edit::{AtomTextEdit, TextEdit}; | 13 | use ra_text_edit::{Indel, TextEdit}; |
14 | 14 | ||
15 | use crate::line_index::{LineCol, LineIndex, Utf16Char}; | 15 | use crate::line_index::{LineCol, LineIndex, Utf16Char}; |
16 | 16 | ||
@@ -182,14 +182,14 @@ struct TranslatedEdit<'a> { | |||
182 | } | 182 | } |
183 | 183 | ||
184 | struct Edits<'a> { | 184 | struct 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 | ||
190 | impl<'a> Edits<'a> { | 190 | impl<'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 | ||
3 | test_utils::marks![ | 3 | test_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 | |||
6 | use ra_db::{FileId, FilePosition, RelativePathBuf, SourceRootId}; | ||
7 | use ra_text_edit::{TextEdit, TextSize}; | ||
8 | |||
9 | #[derive(Debug, Clone)] | ||
10 | pub 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 | |||
18 | impl 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)] | ||
94 | pub struct SourceFileEdit { | ||
95 | pub file_id: FileId, | ||
96 | pub edit: TextEdit, | ||
97 | } | ||
98 | |||
99 | #[derive(Debug, Clone)] | ||
100 | pub enum FileSystemEdit { | ||
101 | CreateFile { source_root: SourceRootId, path: RelativePathBuf }, | ||
102 | MoveFile { src: FileId, dst_source_root: SourceRootId, dst_path: RelativePathBuf }, | ||
103 | } | ||
104 | |||
105 | pub struct SingleFileChange { | ||
106 | pub label: String, | ||
107 | pub edit: TextEdit, | ||
108 | pub cursor_position: Option<TextSize>, | ||
109 | } | ||
110 | |||
111 | impl 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 | } | ||