diff options
Diffstat (limited to 'crates/server/src/conv.rs')
-rw-r--r-- | crates/server/src/conv.rs | 82 |
1 files changed, 71 insertions, 11 deletions
diff --git a/crates/server/src/conv.rs b/crates/server/src/conv.rs index c7bea15df..0ed989b32 100644 --- a/crates/server/src/conv.rs +++ b/crates/server/src/conv.rs | |||
@@ -1,23 +1,23 @@ | |||
1 | use languageserver_types::{Range, SymbolKind, Position}; | 1 | use languageserver_types::{Range, SymbolKind, Position, TextEdit}; |
2 | use libeditor::{LineIndex, LineCol}; | 2 | use libeditor::{LineIndex, LineCol, Edit, AtomEdit}; |
3 | use libsyntax2::{SyntaxKind, TextUnit, TextRange}; | 3 | use libsyntax2::{SyntaxKind, TextUnit, TextRange}; |
4 | 4 | ||
5 | pub trait Conv { | 5 | pub trait Conv { |
6 | type Output; | 6 | type Output; |
7 | fn conv(&self) -> Self::Output; | 7 | fn conv(self) -> Self::Output; |
8 | } | 8 | } |
9 | 9 | ||
10 | pub trait ConvWith { | 10 | pub trait ConvWith { |
11 | type Ctx; | 11 | type Ctx; |
12 | type Output; | 12 | type Output; |
13 | fn conv_with(&self, ctx: &Self::Ctx) -> Self::Output; | 13 | fn conv_with(self, ctx: &Self::Ctx) -> Self::Output; |
14 | } | 14 | } |
15 | 15 | ||
16 | impl Conv for SyntaxKind { | 16 | impl Conv for SyntaxKind { |
17 | type Output = SymbolKind; | 17 | type Output = SymbolKind; |
18 | 18 | ||
19 | fn conv(&self) -> <Self as Conv>::Output { | 19 | fn conv(self) -> <Self as Conv>::Output { |
20 | match *self { | 20 | match self { |
21 | SyntaxKind::FUNCTION => SymbolKind::Function, | 21 | SyntaxKind::FUNCTION => SymbolKind::Function, |
22 | SyntaxKind::STRUCT => SymbolKind::Struct, | 22 | SyntaxKind::STRUCT => SymbolKind::Struct, |
23 | SyntaxKind::ENUM => SymbolKind::Enum, | 23 | SyntaxKind::ENUM => SymbolKind::Enum, |
@@ -35,7 +35,7 @@ impl ConvWith for Position { | |||
35 | type Ctx = LineIndex; | 35 | type Ctx = LineIndex; |
36 | type Output = TextUnit; | 36 | type Output = TextUnit; |
37 | 37 | ||
38 | fn conv_with(&self, line_index: &LineIndex) -> TextUnit { | 38 | fn conv_with(self, line_index: &LineIndex) -> TextUnit { |
39 | // TODO: UTF-16 | 39 | // TODO: UTF-16 |
40 | let line_col = LineCol { | 40 | let line_col = LineCol { |
41 | line: self.line as u32, | 41 | line: self.line as u32, |
@@ -49,8 +49,8 @@ impl ConvWith for TextUnit { | |||
49 | type Ctx = LineIndex; | 49 | type Ctx = LineIndex; |
50 | type Output = Position; | 50 | type Output = Position; |
51 | 51 | ||
52 | fn conv_with(&self, line_index: &LineIndex) -> Position { | 52 | fn conv_with(self, line_index: &LineIndex) -> Position { |
53 | let line_col = line_index.line_col(*self); | 53 | let line_col = line_index.line_col(self); |
54 | // TODO: UTF-16 | 54 | // TODO: UTF-16 |
55 | Position::new(line_col.line as u64, u32::from(line_col.col) as u64) | 55 | Position::new(line_col.line as u64, u32::from(line_col.col) as u64) |
56 | } | 56 | } |
@@ -60,7 +60,7 @@ impl ConvWith for TextRange { | |||
60 | type Ctx = LineIndex; | 60 | type Ctx = LineIndex; |
61 | type Output = Range; | 61 | type Output = Range; |
62 | 62 | ||
63 | fn conv_with(&self, line_index: &LineIndex) -> Range { | 63 | fn conv_with(self, line_index: &LineIndex) -> Range { |
64 | Range::new( | 64 | Range::new( |
65 | self.start().conv_with(line_index), | 65 | self.start().conv_with(line_index), |
66 | self.end().conv_with(line_index), | 66 | self.end().conv_with(line_index), |
@@ -72,10 +72,70 @@ impl ConvWith for Range { | |||
72 | type Ctx = LineIndex; | 72 | type Ctx = LineIndex; |
73 | type Output = TextRange; | 73 | type Output = TextRange; |
74 | 74 | ||
75 | fn conv_with(&self, line_index: &LineIndex) -> TextRange { | 75 | fn conv_with(self, line_index: &LineIndex) -> TextRange { |
76 | TextRange::from_to( | 76 | TextRange::from_to( |
77 | self.start.conv_with(line_index), | 77 | self.start.conv_with(line_index), |
78 | self.end.conv_with(line_index), | 78 | self.end.conv_with(line_index), |
79 | ) | 79 | ) |
80 | } | 80 | } |
81 | } | 81 | } |
82 | |||
83 | impl ConvWith for Edit { | ||
84 | type Ctx = LineIndex; | ||
85 | type Output = Vec<TextEdit>; | ||
86 | |||
87 | fn conv_with(self, line_index: &LineIndex) -> Vec<TextEdit> { | ||
88 | self.into_atoms() | ||
89 | .into_iter() | ||
90 | .map_conv_with(line_index) | ||
91 | .collect() | ||
92 | } | ||
93 | } | ||
94 | |||
95 | impl ConvWith for AtomEdit { | ||
96 | type Ctx = LineIndex; | ||
97 | type Output = TextEdit; | ||
98 | |||
99 | fn conv_with(self, line_index: &LineIndex) -> TextEdit { | ||
100 | TextEdit { | ||
101 | range: self.delete.conv_with(line_index), | ||
102 | new_text: self.insert, | ||
103 | } | ||
104 | } | ||
105 | } | ||
106 | |||
107 | |||
108 | pub trait MapConvWith<'a>: Sized { | ||
109 | type Ctx; | ||
110 | type Output; | ||
111 | |||
112 | fn map_conv_with(self, ctx: &'a Self::Ctx) -> ConvWithIter<'a, Self, Self::Ctx> { | ||
113 | ConvWithIter { iter: self, ctx } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | impl<'a, I> MapConvWith<'a> for I | ||
118 | where I: Iterator, | ||
119 | I::Item: ConvWith | ||
120 | { | ||
121 | type Ctx = <I::Item as ConvWith>::Ctx; | ||
122 | type Output = <I::Item as ConvWith>::Output; | ||
123 | } | ||
124 | |||
125 | pub struct ConvWithIter<'a, I, Ctx: 'a> { | ||
126 | iter: I, | ||
127 | ctx: &'a Ctx, | ||
128 | } | ||
129 | |||
130 | impl<'a, I, Ctx> Iterator for ConvWithIter<'a, I, Ctx> | ||
131 | where | ||
132 | I: Iterator, | ||
133 | I::Item: ConvWith<Ctx=Ctx>, | ||
134 | { | ||
135 | type Item = <I::Item as ConvWith>::Output; | ||
136 | |||
137 | fn next(&mut self) -> Option<Self::Item> { | ||
138 | self.iter.next().map(|item| item.conv_with(self.ctx)) | ||
139 | } | ||
140 | } | ||
141 | |||