aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_analysis/Cargo.toml1
-rw-r--r--crates/ra_analysis/src/completion.rs5
-rw-r--r--crates/ra_analysis/src/lib.rs5
-rw-r--r--crates/ra_editor/Cargo.toml1
-rw-r--r--crates/ra_editor/src/code_actions.rs12
-rw-r--r--crates/ra_editor/src/lib.rs4
-rw-r--r--crates/ra_editor/src/typing.rs26
-rw-r--r--crates/ra_lsp_server/Cargo.toml1
-rw-r--r--crates/ra_lsp_server/src/conv.rs23
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs3
-rw-r--r--crates/ra_syntax/Cargo.toml1
-rw-r--r--crates/ra_syntax/src/lib.rs8
-rw-r--r--crates/ra_syntax/src/reparsing.rs38
-rw-r--r--crates/ra_syntax/src/text_utils.rs6
-rw-r--r--crates/ra_syntax/src/yellow/syntax_text.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs38
-rw-r--r--crates/ra_text_edit/Cargo.toml12
-rw-r--r--crates/ra_text_edit/src/lib.rs29
-rw-r--r--crates/ra_text_edit/src/text_edit.rs (renamed from crates/ra_editor/src/edit.rs)33
-rw-r--r--crates/ra_text_edit/src/text_utils.rs5
20 files changed, 144 insertions, 110 deletions
diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml
index fe9765a66..4a7b99947 100644
--- a/crates/ra_analysis/Cargo.toml
+++ b/crates/ra_analysis/Cargo.toml
@@ -14,6 +14,7 @@ rustc-hash = "1.0"
14parking_lot = "0.6.4" 14parking_lot = "0.6.4"
15ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
16ra_editor = { path = "../ra_editor" } 16ra_editor = { path = "../ra_editor" }
17ra_text_edit = { path = "../ra_text_edit" }
17ra_db = { path = "../ra_db" } 18ra_db = { path = "../ra_db" }
18hir = { path = "../ra_hir", package = "ra_hir" } 19hir = { path = "../ra_hir", package = "ra_hir" }
19test_utils = { path = "../test_utils" } 20test_utils = { path = "../test_utils" }
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs
index 0f154112a..f480af611 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion.rs
@@ -1,10 +1,11 @@
1mod reference_completion; 1mod reference_completion;
2 2
3use ra_editor::find_node_at_offset; 3use ra_editor::find_node_at_offset;
4use ra_text_edit::AtomTextEdit;
4use ra_syntax::{ 5use ra_syntax::{
5 algo::visit::{visitor_ctx, VisitorCtx}, 6 algo::visit::{visitor_ctx, VisitorCtx},
6 ast, 7 ast,
7 AstNode, AtomEdit, 8 AstNode,
8 SyntaxNodeRef, 9 SyntaxNodeRef,
9}; 10};
10use ra_db::SyntaxDatabase; 11use ra_db::SyntaxDatabase;
@@ -33,7 +34,7 @@ pub(crate) fn completions(
33 let original_file = db.source_file(position.file_id); 34 let original_file = db.source_file(position.file_id);
34 // Insert a fake ident to get a valid parse tree 35 // Insert a fake ident to get a valid parse tree
35 let file = { 36 let file = {
36 let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string()); 37 let edit = AtomTextEdit::insert(position.offset, "intellijRulezz".to_string());
37 original_file.reparse(&edit) 38 original_file.reparse(&edit)
38 }; 39 };
39 40
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs
index eaf24cb36..22fff71ab 100644
--- a/crates/ra_analysis/src/lib.rs
+++ b/crates/ra_analysis/src/lib.rs
@@ -18,7 +18,8 @@ pub mod mock_analysis;
18 18
19use std::{fmt, sync::Arc}; 19use std::{fmt, sync::Arc};
20 20
21use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit}; 21use ra_syntax::{SourceFileNode, TextRange, TextUnit};
22use ra_text_edit::AtomTextEdit;
22use ra_db::FileResolverImp; 23use ra_db::FileResolverImp;
23use rayon::prelude::*; 24use rayon::prelude::*;
24use relative_path::RelativePathBuf; 25use relative_path::RelativePathBuf;
@@ -120,7 +121,7 @@ pub struct SourceChange {
120#[derive(Debug)] 121#[derive(Debug)]
121pub struct SourceFileNodeEdit { 122pub struct SourceFileNodeEdit {
122 pub file_id: FileId, 123 pub file_id: FileId,
123 pub edits: Vec<AtomEdit>, 124 pub edits: Vec<AtomTextEdit>,
124} 125}
125 126
126#[derive(Debug)] 127#[derive(Debug)]
diff --git a/crates/ra_editor/Cargo.toml b/crates/ra_editor/Cargo.toml
index 7791da156..c29be1350 100644
--- a/crates/ra_editor/Cargo.toml
+++ b/crates/ra_editor/Cargo.toml
@@ -12,6 +12,7 @@ join_to_string = "0.1.1"
12rustc-hash = "1.0" 12rustc-hash = "1.0"
13 13
14ra_syntax = { path = "../ra_syntax" } 14ra_syntax = { path = "../ra_syntax" }
15ra_text_edit = { path = "../ra_text_edit" }
15 16
16[dev-dependencies] 17[dev-dependencies]
17test_utils = { path = "../test_utils" } 18test_utils = { path = "../test_utils" }
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
index 6979251d1..688a89c3d 100644
--- a/crates/ra_editor/src/code_actions.rs
+++ b/crates/ra_editor/src/code_actions.rs
@@ -8,11 +8,11 @@ use ra_syntax::{
8 SyntaxNodeRef, TextRange, TextUnit, 8 SyntaxNodeRef, TextRange, TextUnit,
9}; 9};
10 10
11use crate::{find_node_at_offset, Edit, EditBuilder}; 11use crate::{find_node_at_offset, TextEdit, TextEditBuilder};
12 12
13#[derive(Debug)] 13#[derive(Debug)]
14pub struct LocalEdit { 14pub struct LocalEdit {
15 pub edit: Edit, 15 pub edit: TextEdit,
16 pub cursor_position: Option<TextUnit>, 16 pub cursor_position: Option<TextUnit>,
17} 17}
18 18
@@ -26,7 +26,7 @@ pub fn flip_comma<'a>(
26 let prev = non_trivia_sibling(comma, Direction::Prev)?; 26 let prev = non_trivia_sibling(comma, Direction::Prev)?;
27 let next = non_trivia_sibling(comma, Direction::Next)?; 27 let next = non_trivia_sibling(comma, Direction::Next)?;
28 Some(move || { 28 Some(move || {
29 let mut edit = EditBuilder::new(); 29 let mut edit = TextEditBuilder::new();
30 edit.replace(prev.range(), next.text().to_string()); 30 edit.replace(prev.range(), next.text().to_string());
31 edit.replace(next.range(), prev.text().to_string()); 31 edit.replace(next.range(), prev.text().to_string());
32 LocalEdit { 32 LocalEdit {
@@ -49,7 +49,7 @@ pub fn add_derive<'a>(
49 .filter(|(name, _arg)| name == "derive") 49 .filter(|(name, _arg)| name == "derive")
50 .map(|(_name, arg)| arg) 50 .map(|(_name, arg)| arg)
51 .next(); 51 .next();
52 let mut edit = EditBuilder::new(); 52 let mut edit = TextEditBuilder::new();
53 let offset = match derive_attr { 53 let offset = match derive_attr {
54 None => { 54 None => {
55 edit.insert(node_start, "#[derive()]\n".to_string()); 55 edit.insert(node_start, "#[derive()]\n".to_string());
@@ -82,7 +82,7 @@ pub fn add_impl<'a>(
82 82
83 Some(move || { 83 Some(move || {
84 let type_params = nominal.type_param_list(); 84 let type_params = nominal.type_param_list();
85 let mut edit = EditBuilder::new(); 85 let mut edit = TextEditBuilder::new();
86 let start_offset = nominal.syntax().range().end(); 86 let start_offset = nominal.syntax().range().end();
87 let mut buf = String::new(); 87 let mut buf = String::new();
88 buf.push_str("\n\nimpl"); 88 buf.push_str("\n\nimpl");
@@ -129,7 +129,7 @@ pub fn introduce_variable<'a>(
129 } 129 }
130 return Some(move || { 130 return Some(move || {
131 let mut buf = String::new(); 131 let mut buf = String::new();
132 let mut edit = EditBuilder::new(); 132 let mut edit = TextEditBuilder::new();
133 133
134 buf.push_str("let var_name = "); 134 buf.push_str("let var_name = ");
135 expr.syntax().text().push_to(&mut buf); 135 expr.syntax().text().push_to(&mut buf);
diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs
index ce080ee97..36cabed25 100644
--- a/crates/ra_editor/src/lib.rs
+++ b/crates/ra_editor/src/lib.rs
@@ -1,5 +1,4 @@
1mod code_actions; 1mod code_actions;
2mod edit;
3mod extend_selection; 2mod extend_selection;
4mod folding_ranges; 3mod folding_ranges;
5mod line_index; 4mod line_index;
@@ -10,14 +9,13 @@ mod typing;
10 9
11pub use self::{ 10pub use self::{
12 code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit}, 11 code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit},
13 edit::{Edit, EditBuilder},
14 extend_selection::extend_selection, 12 extend_selection::extend_selection,
15 folding_ranges::{folding_ranges, Fold, FoldKind}, 13 folding_ranges::{folding_ranges, Fold, FoldKind},
16 line_index::{LineCol, LineIndex}, 14 line_index::{LineCol, LineIndex},
17 symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, 15 symbols::{file_structure, file_symbols, FileSymbol, StructureNode},
18 typing::{join_lines, on_enter, on_eq_typed}, 16 typing::{join_lines, on_enter, on_eq_typed},
19}; 17};
20pub use ra_syntax::AtomEdit; 18use ra_text_edit::{TextEdit, TextEditBuilder};
21use ra_syntax::{ 19use ra_syntax::{
22 algo::find_leaf_at_offset, 20 algo::find_leaf_at_offset,
23 ast::{self, AstNode, NameOwner}, 21 ast::{self, AstNode, NameOwner},
diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs
index 01acdda7c..46a6e2d62 100644
--- a/crates/ra_editor/src/typing.rs
+++ b/crates/ra_editor/src/typing.rs
@@ -3,13 +3,14 @@ use std::mem;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, 4 algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
5 ast, 5 ast,
6 text_utils::{contains_offset_nonstrict, intersect}, 6 text_utils::intersect,
7 AstNode, SourceFileNode, SyntaxKind, 7 AstNode, SourceFileNode, SyntaxKind,
8 SyntaxKind::*, 8 SyntaxKind::*,
9 SyntaxNodeRef, TextRange, TextUnit, 9 SyntaxNodeRef, TextRange, TextUnit,
10}; 10};
11use ra_text_edit::text_utils::contains_offset_nonstrict;
11 12
12use crate::{find_node_at_offset, EditBuilder, LocalEdit}; 13use crate::{find_node_at_offset, TextEditBuilder, LocalEdit};
13 14
14pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { 15pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
15 let range = if range.is_empty() { 16 let range = if range.is_empty() {
@@ -18,7 +19,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
18 let pos = match text.find('\n') { 19 let pos = match text.find('\n') {
19 None => { 20 None => {
20 return LocalEdit { 21 return LocalEdit {
21 edit: EditBuilder::new().finish(), 22 edit: TextEditBuilder::new().finish(),
22 cursor_position: None, 23 cursor_position: None,
23 }; 24 };
24 } 25 }
@@ -30,7 +31,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit {
30 }; 31 };
31 32
32 let node = find_covering_node(file.syntax(), range); 33 let node = find_covering_node(file.syntax(), range);
33 let mut edit = EditBuilder::new(); 34 let mut edit = TextEditBuilder::new();
34 for node in node.descendants() { 35 for node in node.descendants() {
35 let text = match node.leaf_text() { 36 let text = match node.leaf_text() {
36 Some(text) => text, 37 Some(text) => text,
@@ -72,7 +73,7 @@ pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit> {
72 let indent = node_indent(file, comment.syntax())?; 73 let indent = node_indent(file, comment.syntax())?;
73 let inserted = format!("\n{}{} ", indent, prefix); 74 let inserted = format!("\n{}{} ", indent, prefix);
74 let cursor_position = offset + TextUnit::of_str(&inserted); 75 let cursor_position = offset + TextUnit::of_str(&inserted);
75 let mut edit = EditBuilder::new(); 76 let mut edit = TextEditBuilder::new();
76 edit.insert(offset, inserted); 77 edit.insert(offset, inserted);
77 Some(LocalEdit { 78 Some(LocalEdit {
78 edit: edit.finish(), 79 edit: edit.finish(),
@@ -122,7 +123,7 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
122 return None; 123 return None;
123 } 124 }
124 let offset = let_stmt.syntax().range().end(); 125 let offset = let_stmt.syntax().range().end();
125 let mut edit = EditBuilder::new(); 126 let mut edit = TextEditBuilder::new();
126 edit.insert(offset, ";".to_string()); 127 edit.insert(offset, ";".to_string());
127 Some(LocalEdit { 128 Some(LocalEdit {
128 edit: edit.finish(), 129 edit: edit.finish(),
@@ -130,7 +131,12 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option<LocalEdit>
130 }) 131 })
131} 132}
132 133
133fn remove_newline(edit: &mut EditBuilder, node: SyntaxNodeRef, node_text: &str, offset: TextUnit) { 134fn remove_newline(
135 edit: &mut TextEditBuilder,
136 node: SyntaxNodeRef,
137 node_text: &str,
138 offset: TextUnit,
139) {
134 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 { 140 if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 {
135 // The node is either the first or the last in the file 141 // The node is either the first or the last in the file
136 let suff = &node_text[TextRange::from_to( 142 let suff = &node_text[TextRange::from_to(
@@ -191,7 +197,7 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
191 } 197 }
192} 198}
193 199
194fn join_single_expr_block(edit: &mut EditBuilder, node: SyntaxNodeRef) -> Option<()> { 200fn join_single_expr_block(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Option<()> {
195 let block = ast::Block::cast(node.parent()?)?; 201 let block = ast::Block::cast(node.parent()?)?;
196 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; 202 let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?;
197 let expr = single_expr(block)?; 203 let expr = single_expr(block)?;
@@ -269,14 +275,14 @@ fn foo() {
269 fn test_join_lines_lambda_block() { 275 fn test_join_lines_lambda_block() {
270 check_join_lines( 276 check_join_lines(
271 r" 277 r"
272pub fn reparse(&self, edit: &AtomEdit) -> File { 278pub fn reparse(&self, edit: &AtomTextEdit) -> File {
273 <|>self.incremental_reparse(edit).unwrap_or_else(|| { 279 <|>self.incremental_reparse(edit).unwrap_or_else(|| {
274 self.full_reparse(edit) 280 self.full_reparse(edit)
275 }) 281 })
276} 282}
277", 283",
278 r" 284 r"
279pub fn reparse(&self, edit: &AtomEdit) -> File { 285pub fn reparse(&self, edit: &AtomTextEdit) -> File {
280 <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 286 <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
281} 287}
282", 288",
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index 5ee218b6b..133decc52 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -28,6 +28,7 @@ rustc-hash = "1.0"
28 28
29ra_syntax = { path = "../ra_syntax" } 29ra_syntax = { path = "../ra_syntax" }
30ra_editor = { path = "../ra_editor" } 30ra_editor = { path = "../ra_editor" }
31ra_text_edit = { path = "../ra_text_edit" }
31ra_analysis = { path = "../ra_analysis" } 32ra_analysis = { path = "../ra_analysis" }
32gen_lsp_server = { path = "../gen_lsp_server" } 33gen_lsp_server = { path = "../gen_lsp_server" }
33 34
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 28368787c..7467f472c 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -1,9 +1,10 @@
1use languageserver_types::{ 1use languageserver_types::{
2 Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, 2 self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier,
3 TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, 3 TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier,
4}; 4};
5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; 5use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition};
6use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; 6use ra_editor::{LineCol, LineIndex};
7use ra_text_edit::{AtomTextEdit, TextEdit};
7use ra_syntax::{SyntaxKind, TextRange, TextUnit}; 8use ra_syntax::{SyntaxKind, TextRange, TextUnit};
8 9
9use crate::{req, server_world::ServerWorld, Result}; 10use crate::{req, server_world::ServerWorld, Result};
@@ -91,11 +92,11 @@ impl ConvWith for Range {
91 } 92 }
92} 93}
93 94
94impl ConvWith for Edit { 95impl ConvWith for TextEdit {
95 type Ctx = LineIndex; 96 type Ctx = LineIndex;
96 type Output = Vec<TextEdit>; 97 type Output = Vec<languageserver_types::TextEdit>;
97 98
98 fn conv_with(self, line_index: &LineIndex) -> Vec<TextEdit> { 99 fn conv_with(self, line_index: &LineIndex) -> Vec<languageserver_types::TextEdit> {
99 self.into_atoms() 100 self.into_atoms()
100 .into_iter() 101 .into_iter()
101 .map_conv_with(line_index) 102 .map_conv_with(line_index)
@@ -103,12 +104,12 @@ impl ConvWith for Edit {
103 } 104 }
104} 105}
105 106
106impl ConvWith for AtomEdit { 107impl ConvWith for AtomTextEdit {
107 type Ctx = LineIndex; 108 type Ctx = LineIndex;
108 type Output = TextEdit; 109 type Output = languageserver_types::TextEdit;
109 110
110 fn conv_with(self, line_index: &LineIndex) -> TextEdit { 111 fn conv_with(self, line_index: &LineIndex) -> languageserver_types::TextEdit {
111 TextEdit { 112 languageserver_types::TextEdit {
112 range: self.delete.conv_with(line_index), 113 range: self.delete.conv_with(line_index),
113 new_text: self.insert, 114 new_text: self.insert,
114 } 115 }
@@ -228,7 +229,7 @@ impl TryConvWith for SourceChange {
228fn translate_offset_with_edit( 229fn translate_offset_with_edit(
229 pre_edit_index: &LineIndex, 230 pre_edit_index: &LineIndex,
230 offset: TextUnit, 231 offset: TextUnit,
231 edits: &[AtomEdit], 232 edits: &[AtomTextEdit],
232) -> LineCol { 233) -> LineCol {
233 let fallback = pre_edit_index.line_col(offset); 234 let fallback = pre_edit_index.line_col(offset);
234 let edit = match edits.first() { 235 let edit = match edits.first() {
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 92e92f836..21ca22c5c 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -9,7 +9,8 @@ use languageserver_types::{
9 WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents, 9 WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents,
10}; 10};
11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; 11use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition};
12use ra_syntax::{TextUnit, text_utils::{contains_offset_nonstrict, intersect}}; 12use ra_syntax::{TextUnit, text_utils::intersect};
13use ra_text_edit::text_utils::contains_offset_nonstrict;
13use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
14use serde_json::to_value; 15use serde_json::to_value;
15 16
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml
index 8ad8ed196..8c9a7e238 100644
--- a/crates/ra_syntax/Cargo.toml
+++ b/crates/ra_syntax/Cargo.toml
@@ -15,6 +15,7 @@ drop_bomb = "0.1.4"
15parking_lot = "0.6.0" 15parking_lot = "0.6.0"
16rowan = "0.1.2" 16rowan = "0.1.2"
17text_unit = "0.1.5" 17text_unit = "0.1.5"
18ra_text_edit = { path = "../ra_text_edit" }
18 19
19[dev-dependencies] 20[dev-dependencies]
20test_utils = { path = "../test_utils" } 21test_utils = { path = "../test_utils" }
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index 0e5c9baad..34a3aabef 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -41,13 +41,13 @@ pub use rowan::{SmolStr, TextRange, TextUnit};
41pub use crate::{ 41pub use crate::{
42 ast::AstNode, 42 ast::AstNode,
43 lexer::{tokenize, Token}, 43 lexer::{tokenize, Token},
44 reparsing::AtomEdit,
45 syntax_kinds::SyntaxKind, 44 syntax_kinds::SyntaxKind,
46 yellow::{ 45 yellow::{
47 Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent, Location, 46 Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent, Location,
48 }, 47 },
49}; 48};
50 49
50use ra_text_edit::AtomTextEdit;
51use crate::yellow::GreenNode; 51use crate::yellow::GreenNode;
52 52
53/// `SourceFileNode` represents a parse tree for a single Rust file. 53/// `SourceFileNode` represents a parse tree for a single Rust file.
@@ -68,15 +68,15 @@ impl SourceFileNode {
68 parser_impl::parse_with(yellow::GreenBuilder::new(), text, &tokens, grammar::root); 68 parser_impl::parse_with(yellow::GreenBuilder::new(), text, &tokens, grammar::root);
69 SourceFileNode::new(green, errors) 69 SourceFileNode::new(green, errors)
70 } 70 }
71 pub fn reparse(&self, edit: &AtomEdit) -> SourceFileNode { 71 pub fn reparse(&self, edit: &AtomTextEdit) -> SourceFileNode {
72 self.incremental_reparse(edit) 72 self.incremental_reparse(edit)
73 .unwrap_or_else(|| self.full_reparse(edit)) 73 .unwrap_or_else(|| self.full_reparse(edit))
74 } 74 }
75 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<SourceFileNode> { 75 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<SourceFileNode> {
76 reparsing::incremental_reparse(self.syntax(), edit, self.errors()) 76 reparsing::incremental_reparse(self.syntax(), edit, self.errors())
77 .map(|(green_node, errors)| SourceFileNode::new(green_node, errors)) 77 .map(|(green_node, errors)| SourceFileNode::new(green_node, errors))
78 } 78 }
79 fn full_reparse(&self, edit: &AtomEdit) -> SourceFileNode { 79 fn full_reparse(&self, edit: &AtomTextEdit) -> SourceFileNode {
80 let text = 80 let text =
81 text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); 81 text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
82 SourceFileNode::parse(&text) 82 SourceFileNode::parse(&text)
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
index 732fb0e4a..208cae5c8 100644
--- a/crates/ra_syntax/src/reparsing.rs
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -6,33 +6,11 @@ use crate::parser_impl;
6use crate::text_utils::replace_range; 6use crate::text_utils::replace_range;
7use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; 7use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef};
8use crate::{SyntaxKind::*, TextRange, TextUnit}; 8use crate::{SyntaxKind::*, TextRange, TextUnit};
9 9use ra_text_edit::AtomTextEdit;
10#[derive(Debug, Clone)]
11pub struct AtomEdit {
12 pub delete: TextRange,
13 pub insert: String,
14}
15
16impl AtomEdit {
17 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit {
18 AtomEdit {
19 delete: range,
20 insert: replace_with,
21 }
22 }
23
24 pub fn delete(range: TextRange) -> AtomEdit {
25 AtomEdit::replace(range, String::new())
26 }
27
28 pub fn insert(offset: TextUnit, text: String) -> AtomEdit {
29 AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text)
30 }
31}
32 10
33pub(crate) fn incremental_reparse( 11pub(crate) fn incremental_reparse(
34 node: SyntaxNodeRef, 12 node: SyntaxNodeRef,
35 edit: &AtomEdit, 13 edit: &AtomTextEdit,
36 errors: Vec<SyntaxError>, 14 errors: Vec<SyntaxError>,
37) -> Option<(GreenNode, Vec<SyntaxError>)> { 15) -> Option<(GreenNode, Vec<SyntaxError>)> {
38 let (node, green, new_errors) = 16 let (node, green, new_errors) =
@@ -44,7 +22,7 @@ pub(crate) fn incremental_reparse(
44 22
45fn reparse_leaf<'node>( 23fn reparse_leaf<'node>(
46 node: SyntaxNodeRef<'node>, 24 node: SyntaxNodeRef<'node>,
47 edit: &AtomEdit, 25 edit: &AtomTextEdit,
48) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> { 26) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> {
49 let node = algo::find_covering_node(node, edit.delete); 27 let node = algo::find_covering_node(node, edit.delete);
50 match node.kind() { 28 match node.kind() {
@@ -70,7 +48,7 @@ fn reparse_leaf<'node>(
70 48
71fn reparse_block<'node>( 49fn reparse_block<'node>(
72 node: SyntaxNodeRef<'node>, 50 node: SyntaxNodeRef<'node>,
73 edit: &AtomEdit, 51 edit: &AtomTextEdit,
74) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> { 52) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> {
75 let (node, reparser) = find_reparsable_node(node, edit.delete)?; 53 let (node, reparser) = find_reparsable_node(node, edit.delete)?;
76 let text = get_text_after_edit(node, &edit); 54 let text = get_text_after_edit(node, &edit);
@@ -83,7 +61,7 @@ fn reparse_block<'node>(
83 Some((node, green, new_errors)) 61 Some((node, green, new_errors))
84} 62}
85 63
86fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String { 64fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomTextEdit) -> String {
87 replace_range( 65 replace_range(
88 node.text().to_string(), 66 node.text().to_string(),
89 edit.delete - node.range().start(), 67 edit.delete - node.range().start(),
@@ -161,7 +139,7 @@ fn merge_errors(
161 old_errors: Vec<SyntaxError>, 139 old_errors: Vec<SyntaxError>,
162 new_errors: Vec<SyntaxError>, 140 new_errors: Vec<SyntaxError>,
163 old_node: SyntaxNodeRef, 141 old_node: SyntaxNodeRef,
164 edit: &AtomEdit, 142 edit: &AtomTextEdit,
165) -> Vec<SyntaxError> { 143) -> Vec<SyntaxError> {
166 let mut res = Vec::new(); 144 let mut res = Vec::new();
167 for e in old_errors { 145 for e in old_errors {
@@ -188,7 +166,7 @@ mod tests {
188 where 166 where
189 for<'a> F: Fn( 167 for<'a> F: Fn(
190 SyntaxNodeRef<'a>, 168 SyntaxNodeRef<'a>,
191 &AtomEdit, 169 &AtomTextEdit,
192 ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec<SyntaxError>)>, 170 ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec<SyntaxError>)>,
193 { 171 {
194 let (range, before) = extract_range(before); 172 let (range, before) = extract_range(before);
@@ -197,7 +175,7 @@ mod tests {
197 let fully_reparsed = SourceFileNode::parse(&after); 175 let fully_reparsed = SourceFileNode::parse(&after);
198 let incrementally_reparsed = { 176 let incrementally_reparsed = {
199 let f = SourceFileNode::parse(&before); 177 let f = SourceFileNode::parse(&before);
200 let edit = AtomEdit { 178 let edit = AtomTextEdit {
201 delete: range, 179 delete: range,
202 insert: replace_with.to_string(), 180 insert: replace_with.to_string(),
203 }; 181 };
diff --git a/crates/ra_syntax/src/text_utils.rs b/crates/ra_syntax/src/text_utils.rs
index a90f8a083..417d43e1b 100644
--- a/crates/ra_syntax/src/text_utils.rs
+++ b/crates/ra_syntax/src/text_utils.rs
@@ -1,8 +1,4 @@
1use crate::{TextRange, TextUnit}; 1use crate::TextRange;
2
3pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool {
4 range.start() <= offset && offset <= range.end()
5}
6 2
7pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> { 3pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> {
8 let start = r1.start().max(r2.start()); 4 let start = r1.start().max(r2.start());
diff --git a/crates/ra_syntax/src/yellow/syntax_text.rs b/crates/ra_syntax/src/yellow/syntax_text.rs
index 5395ca90b..46bde9a08 100644
--- a/crates/ra_syntax/src/yellow/syntax_text.rs
+++ b/crates/ra_syntax/src/yellow/syntax_text.rs
@@ -1,7 +1,8 @@
1use std::{fmt, ops}; 1use std::{fmt, ops};
2 2
3use ra_text_edit::text_utils::contains_offset_nonstrict;
3use crate::{ 4use crate::{
4 text_utils::{contains_offset_nonstrict, intersect}, 5 text_utils::intersect,
5 SyntaxNodeRef, TextRange, TextUnit, 6 SyntaxNodeRef, TextRange, TextUnit,
6}; 7};
7 8
diff --git a/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs b/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs
index 53c93d9e9..59cd11495 100644
--- a/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs
+++ b/crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs
@@ -10,10 +10,10 @@
10 ); 10 );
11 File::new(green, errors) 11 File::new(green, errors)
12 } 12 }
13 pub fn reparse(&self, edit: &AtomEdit) -> File { 13 pub fn reparse(&self, edit: &AtomTextEdit) -> File {
14 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) 14 self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit))
15 } 15 }
16 pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option<File> { 16 pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option<File> {
17 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?; 17 let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?;
18 let text = replace_range( 18 let text = replace_range(
19 node.text().to_string(), 19 node.text().to_string(),
@@ -31,7 +31,7 @@
31 let errors = merge_errors(self.errors(), new_errors, node, edit); 31 let errors = merge_errors(self.errors(), new_errors, node, edit);
32 Some(File::new(green_root, errors)) 32 Some(File::new(green_root, errors))
33 } 33 }
34 fn full_reparse(&self, edit: &AtomEdit) -> File { 34 fn full_reparse(&self, edit: &AtomTextEdit) -> File {
35 let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); 35 let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert);
36 File::parse(&text) 36 File::parse(&text)
37 } 37 }
@@ -58,22 +58,22 @@
58} 58}
59 59
60#[derive(Debug, Clone)] 60#[derive(Debug, Clone)]
61pub struct AtomEdit { 61pub struct AtomTextEdit {
62 pub delete: TextRange, 62 pub delete: TextRange,
63 pub insert: String, 63 pub insert: String,
64} 64}
65 65
66impl AtomEdit { 66impl AtomTextEdit {
67 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { 67 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
68 AtomEdit { delete: range, insert: replace_with } 68 AtomTextEdit { delete: range, insert: replace_with }
69 } 69 }
70 70
71 pub fn delete(range: TextRange) -> AtomEdit { 71 pub fn delete(range: TextRange) -> AtomTextEdit {
72 AtomEdit::replace(range, String::new()) 72 AtomTextEdit::replace(range, String::new())
73 } 73 }
74 74
75 pub fn insert(offset: TextUnit, text: String) -> AtomEdit { 75 pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit {
76 AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) 76 AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text)
77 } 77 }
78} 78}
79 79
@@ -114,17 +114,17 @@ fn is_balanced(tokens: &[Token]) -> bool {
114 pub insert: String, 114 pub insert: String,
115} 115}
116 116
117impl AtomEdit { 117impl AtomTextEdit {
118 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { 118 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
119 AtomEdit { delete: range, insert: replace_with } 119 AtomTextEdit { delete: range, insert: replace_with }
120 } 120 }
121 121
122 pub fn delete(range: TextRange) -> AtomEdit { 122 pub fn delete(range: TextRange) -> AtomTextEdit {
123 AtomEdit::replace(range, String::new()) 123 AtomTextEdit::replace(range, String::new())
124 } 124 }
125 125
126 pub fn insert(offset: TextUnit, text: String) -> AtomEdit { 126 pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit {
127 AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) 127 AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text)
128 } 128 }
129} 129}
130 130
@@ -176,7 +176,7 @@ fn merge_errors(
176 old_errors: Vec<SyntaxError>, 176 old_errors: Vec<SyntaxError>,
177 new_errors: Vec<SyntaxError>, 177 new_errors: Vec<SyntaxError>,
178 old_node: SyntaxNodeRef, 178 old_node: SyntaxNodeRef,
179 edit: &AtomEdit, 179 edit: &AtomTextEdit,
180) -> Vec<SyntaxError> { 180) -> Vec<SyntaxError> {
181 let mut res = Vec::new(); 181 let mut res = Vec::new();
182 for e in old_errors { 182 for e in old_errors {
diff --git a/crates/ra_text_edit/Cargo.toml b/crates/ra_text_edit/Cargo.toml
new file mode 100644
index 000000000..3c4157a4e
--- /dev/null
+++ b/crates/ra_text_edit/Cargo.toml
@@ -0,0 +1,12 @@
1[package]
2edition = "2018"
3name = "ra_text_edit"
4version = "0.1.0"
5authors = ["Aleksey Kladov <[email protected]>"]
6publish = false
7
8[dependencies]
9text_unit = "0.1.5"
10
11[dev-dependencies]
12test_utils = { path = "../test_utils" }
diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs
new file mode 100644
index 000000000..13e20f6fb
--- /dev/null
+++ b/crates/ra_text_edit/src/lib.rs
@@ -0,0 +1,29 @@
1mod text_edit;
2pub mod text_utils;
3
4pub use crate::text_edit::{TextEdit, TextEditBuilder};
5
6use text_unit::{TextRange, TextUnit};
7
8#[derive(Debug, Clone)]
9pub struct AtomTextEdit {
10 pub delete: TextRange,
11 pub insert: String,
12}
13
14impl AtomTextEdit {
15 pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit {
16 AtomTextEdit {
17 delete: range,
18 insert: replace_with,
19 }
20 }
21
22 pub fn delete(range: TextRange) -> AtomTextEdit {
23 AtomTextEdit::replace(range, String::new())
24 }
25
26 pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit {
27 AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text)
28 }
29}
diff --git a/crates/ra_editor/src/edit.rs b/crates/ra_text_edit/src/text_edit.rs
index 372b8d14c..fb46f046d 100644
--- a/crates/ra_editor/src/edit.rs
+++ b/crates/ra_text_edit/src/text_edit.rs
@@ -1,36 +1,37 @@
1use crate::{TextRange, TextUnit}; 1use crate::AtomTextEdit;
2use ra_syntax::{text_utils::contains_offset_nonstrict, AtomEdit}; 2use crate::text_utils::contains_offset_nonstrict;
3use text_unit::{TextRange, TextUnit};
3 4
4#[derive(Debug, Clone)] 5#[derive(Debug, Clone)]
5pub struct Edit { 6pub struct TextEdit {
6 atoms: Vec<AtomEdit>, 7 atoms: Vec<AtomTextEdit>,
7} 8}
8 9
9#[derive(Debug)] 10#[derive(Debug)]
10pub struct EditBuilder { 11pub struct TextEditBuilder {
11 atoms: Vec<AtomEdit>, 12 atoms: Vec<AtomTextEdit>,
12} 13}
13 14
14impl EditBuilder { 15impl TextEditBuilder {
15 pub fn new() -> EditBuilder { 16 pub fn new() -> TextEditBuilder {
16 EditBuilder { atoms: Vec::new() } 17 TextEditBuilder { atoms: Vec::new() }
17 } 18 }
18 pub fn replace(&mut self, range: TextRange, replace_with: String) { 19 pub fn replace(&mut self, range: TextRange, replace_with: String) {
19 self.atoms.push(AtomEdit::replace(range, replace_with)) 20 self.atoms.push(AtomTextEdit::replace(range, replace_with))
20 } 21 }
21 pub fn delete(&mut self, range: TextRange) { 22 pub fn delete(&mut self, range: TextRange) {
22 self.atoms.push(AtomEdit::delete(range)) 23 self.atoms.push(AtomTextEdit::delete(range))
23 } 24 }
24 pub fn insert(&mut self, offset: TextUnit, text: String) { 25 pub fn insert(&mut self, offset: TextUnit, text: String) {
25 self.atoms.push(AtomEdit::insert(offset, text)) 26 self.atoms.push(AtomTextEdit::insert(offset, text))
26 } 27 }
27 pub fn finish(self) -> Edit { 28 pub fn finish(self) -> TextEdit {
28 let mut atoms = self.atoms; 29 let mut atoms = self.atoms;
29 atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); 30 atoms.sort_by_key(|a| (a.delete.start(), a.delete.end()));
30 for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { 31 for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) {
31 assert!(a1.delete.end() <= a2.delete.start()) 32 assert!(a1.delete.end() <= a2.delete.start())
32 } 33 }
33 Edit { atoms } 34 TextEdit { atoms }
34 } 35 }
35 pub fn invalidates_offset(&self, offset: TextUnit) -> bool { 36 pub fn invalidates_offset(&self, offset: TextUnit) -> bool {
36 self.atoms 37 self.atoms
@@ -39,8 +40,8 @@ impl EditBuilder {
39 } 40 }
40} 41}
41 42
42impl Edit { 43impl TextEdit {
43 pub fn into_atoms(self) -> Vec<AtomEdit> { 44 pub fn into_atoms(self) -> Vec<AtomTextEdit> {
44 self.atoms 45 self.atoms
45 } 46 }
46 47
diff --git a/crates/ra_text_edit/src/text_utils.rs b/crates/ra_text_edit/src/text_utils.rs
new file mode 100644
index 000000000..e3b4dc4fe
--- /dev/null
+++ b/crates/ra_text_edit/src/text_utils.rs
@@ -0,0 +1,5 @@
1use text_unit::{TextRange, TextUnit};
2
3pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool {
4 range.start() <= offset && offset <= range.end()
5}