diff options
-rw-r--r-- | Cargo.lock | 12 | ||||
-rw-r--r-- | crates/ra_analysis/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion.rs | 5 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ra_editor/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_editor/src/code_actions.rs | 12 | ||||
-rw-r--r-- | crates/ra_editor/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_editor/src/typing.rs | 26 | ||||
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/conv.rs | 23 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_syntax/src/reparsing.rs | 38 | ||||
-rw-r--r-- | crates/ra_syntax/src/text_utils.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/yellow/syntax_text.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/fuzz-failures/0000.rs | 38 | ||||
-rw-r--r-- | crates/ra_text_edit/Cargo.toml | 12 | ||||
-rw-r--r-- | crates/ra_text_edit/src/lib.rs | 29 | ||||
-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.rs | 5 |
21 files changed, 156 insertions, 110 deletions
diff --git a/Cargo.lock b/Cargo.lock index 1f69a91b2..56d5c65b9 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -610,6 +610,7 @@ dependencies = [ | |||
610 | "ra_editor 0.1.0", | 610 | "ra_editor 0.1.0", |
611 | "ra_hir 0.1.0", | 611 | "ra_hir 0.1.0", |
612 | "ra_syntax 0.1.0", | 612 | "ra_syntax 0.1.0", |
613 | "ra_text_edit 0.1.0", | ||
613 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | 614 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", |
614 | "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 615 | "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
615 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 616 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -649,6 +650,7 @@ dependencies = [ | |||
649 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", | 650 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", |
650 | "join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | 651 | "join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", |
651 | "ra_syntax 0.1.0", | 652 | "ra_syntax 0.1.0", |
653 | "ra_text_edit 0.1.0", | ||
652 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 654 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
653 | "superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | 655 | "superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", |
654 | "test_utils 0.1.0", | 656 | "test_utils 0.1.0", |
@@ -687,6 +689,7 @@ dependencies = [ | |||
687 | "ra_analysis 0.1.0", | 689 | "ra_analysis 0.1.0", |
688 | "ra_editor 0.1.0", | 690 | "ra_editor 0.1.0", |
689 | "ra_syntax 0.1.0", | 691 | "ra_syntax 0.1.0", |
692 | "ra_text_edit 0.1.0", | ||
690 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | 693 | "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", |
691 | "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | 694 | "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", |
692 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | 695 | "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -710,6 +713,7 @@ dependencies = [ | |||
710 | "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", | 713 | "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", |
711 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", | 714 | "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", |
712 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", | 715 | "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", |
716 | "ra_text_edit 0.1.0", | ||
713 | "rowan 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | 717 | "rowan 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", |
714 | "test_utils 0.1.0", | 718 | "test_utils 0.1.0", |
715 | "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | 719 | "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", |
@@ -718,6 +722,14 @@ dependencies = [ | |||
718 | ] | 722 | ] |
719 | 723 | ||
720 | [[package]] | 724 | [[package]] |
725 | name = "ra_text_edit" | ||
726 | version = "0.1.0" | ||
727 | dependencies = [ | ||
728 | "test_utils 0.1.0", | ||
729 | "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||
730 | ] | ||
731 | |||
732 | [[package]] | ||
721 | name = "rand" | 733 | name = "rand" |
722 | version = "0.4.3" | 734 | version = "0.4.3" |
723 | source = "registry+https://github.com/rust-lang/crates.io-index" | 735 | source = "registry+https://github.com/rust-lang/crates.io-index" |
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" | |||
14 | parking_lot = "0.6.4" | 14 | parking_lot = "0.6.4" |
15 | ra_syntax = { path = "../ra_syntax" } | 15 | ra_syntax = { path = "../ra_syntax" } |
16 | ra_editor = { path = "../ra_editor" } | 16 | ra_editor = { path = "../ra_editor" } |
17 | ra_text_edit = { path = "../ra_text_edit" } | ||
17 | ra_db = { path = "../ra_db" } | 18 | ra_db = { path = "../ra_db" } |
18 | hir = { path = "../ra_hir", package = "ra_hir" } | 19 | hir = { path = "../ra_hir", package = "ra_hir" } |
19 | test_utils = { path = "../test_utils" } | 20 | test_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 @@ | |||
1 | mod reference_completion; | 1 | mod reference_completion; |
2 | 2 | ||
3 | use ra_editor::find_node_at_offset; | 3 | use ra_editor::find_node_at_offset; |
4 | use ra_text_edit::AtomTextEdit; | ||
4 | use ra_syntax::{ | 5 | use 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 | }; |
10 | use ra_db::SyntaxDatabase; | 11 | use 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 | ||
19 | use std::{fmt, sync::Arc}; | 19 | use std::{fmt, sync::Arc}; |
20 | 20 | ||
21 | use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit}; | 21 | use ra_syntax::{SourceFileNode, TextRange, TextUnit}; |
22 | use ra_text_edit::AtomTextEdit; | ||
22 | use ra_db::FileResolverImp; | 23 | use ra_db::FileResolverImp; |
23 | use rayon::prelude::*; | 24 | use rayon::prelude::*; |
24 | use relative_path::RelativePathBuf; | 25 | use relative_path::RelativePathBuf; |
@@ -120,7 +121,7 @@ pub struct SourceChange { | |||
120 | #[derive(Debug)] | 121 | #[derive(Debug)] |
121 | pub struct SourceFileNodeEdit { | 122 | pub 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" | |||
12 | rustc-hash = "1.0" | 12 | rustc-hash = "1.0" |
13 | 13 | ||
14 | ra_syntax = { path = "../ra_syntax" } | 14 | ra_syntax = { path = "../ra_syntax" } |
15 | ra_text_edit = { path = "../ra_text_edit" } | ||
15 | 16 | ||
16 | [dev-dependencies] | 17 | [dev-dependencies] |
17 | test_utils = { path = "../test_utils" } | 18 | test_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 | ||
11 | use crate::{find_node_at_offset, Edit, EditBuilder}; | 11 | use crate::{find_node_at_offset, TextEdit, TextEditBuilder}; |
12 | 12 | ||
13 | #[derive(Debug)] | 13 | #[derive(Debug)] |
14 | pub struct LocalEdit { | 14 | pub 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 @@ | |||
1 | mod code_actions; | 1 | mod code_actions; |
2 | mod edit; | ||
3 | mod extend_selection; | 2 | mod extend_selection; |
4 | mod folding_ranges; | 3 | mod folding_ranges; |
5 | mod line_index; | 4 | mod line_index; |
@@ -10,14 +9,13 @@ mod typing; | |||
10 | 9 | ||
11 | pub use self::{ | 10 | pub 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 | }; |
20 | pub use ra_syntax::AtomEdit; | 18 | use ra_text_edit::{TextEdit, TextEditBuilder}; |
21 | use ra_syntax::{ | 19 | use 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; | |||
3 | use ra_syntax::{ | 3 | use 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 | }; |
11 | use ra_text_edit::text_utils::contains_offset_nonstrict; | ||
11 | 12 | ||
12 | use crate::{find_node_at_offset, EditBuilder, LocalEdit}; | 13 | use crate::{find_node_at_offset, TextEditBuilder, LocalEdit}; |
13 | 14 | ||
14 | pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { | 15 | pub 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 | ||
133 | fn remove_newline(edit: &mut EditBuilder, node: SyntaxNodeRef, node_text: &str, offset: TextUnit) { | 134 | fn 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 | ||
194 | fn join_single_expr_block(edit: &mut EditBuilder, node: SyntaxNodeRef) -> Option<()> { | 200 | fn 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" |
272 | pub fn reparse(&self, edit: &AtomEdit) -> File { | 278 | pub 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" |
279 | pub fn reparse(&self, edit: &AtomEdit) -> File { | 285 | pub 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 | ||
29 | ra_syntax = { path = "../ra_syntax" } | 29 | ra_syntax = { path = "../ra_syntax" } |
30 | ra_editor = { path = "../ra_editor" } | 30 | ra_editor = { path = "../ra_editor" } |
31 | ra_text_edit = { path = "../ra_text_edit" } | ||
31 | ra_analysis = { path = "../ra_analysis" } | 32 | ra_analysis = { path = "../ra_analysis" } |
32 | gen_lsp_server = { path = "../gen_lsp_server" } | 33 | gen_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 @@ | |||
1 | use languageserver_types::{ | 1 | use 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 | }; |
5 | use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; | 5 | use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; |
6 | use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; | 6 | use ra_editor::{LineCol, LineIndex}; |
7 | use ra_text_edit::{AtomTextEdit, TextEdit}; | ||
7 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; | 8 | use ra_syntax::{SyntaxKind, TextRange, TextUnit}; |
8 | 9 | ||
9 | use crate::{req, server_world::ServerWorld, Result}; | 10 | use crate::{req, server_world::ServerWorld, Result}; |
@@ -91,11 +92,11 @@ impl ConvWith for Range { | |||
91 | } | 92 | } |
92 | } | 93 | } |
93 | 94 | ||
94 | impl ConvWith for Edit { | 95 | impl 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 | ||
106 | impl ConvWith for AtomEdit { | 107 | impl 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 { | |||
228 | fn translate_offset_with_edit( | 229 | fn 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 | }; |
11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; | 11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; |
12 | use ra_syntax::{TextUnit, text_utils::{contains_offset_nonstrict, intersect}}; | 12 | use ra_syntax::{TextUnit, text_utils::intersect}; |
13 | use ra_text_edit::text_utils::contains_offset_nonstrict; | ||
13 | use rustc_hash::FxHashMap; | 14 | use rustc_hash::FxHashMap; |
14 | use serde_json::to_value; | 15 | use 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" | |||
15 | parking_lot = "0.6.0" | 15 | parking_lot = "0.6.0" |
16 | rowan = "0.1.2" | 16 | rowan = "0.1.2" |
17 | text_unit = "0.1.5" | 17 | text_unit = "0.1.5" |
18 | ra_text_edit = { path = "../ra_text_edit" } | ||
18 | 19 | ||
19 | [dev-dependencies] | 20 | [dev-dependencies] |
20 | test_utils = { path = "../test_utils" } | 21 | test_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}; | |||
41 | pub use crate::{ | 41 | pub 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 | ||
50 | use ra_text_edit::AtomTextEdit; | ||
51 | use crate::yellow::GreenNode; | 51 | use 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; | |||
6 | use crate::text_utils::replace_range; | 6 | use crate::text_utils::replace_range; |
7 | use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; | 7 | use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; |
8 | use crate::{SyntaxKind::*, TextRange, TextUnit}; | 8 | use crate::{SyntaxKind::*, TextRange, TextUnit}; |
9 | 9 | use ra_text_edit::AtomTextEdit; | |
10 | #[derive(Debug, Clone)] | ||
11 | pub struct AtomEdit { | ||
12 | pub delete: TextRange, | ||
13 | pub insert: String, | ||
14 | } | ||
15 | |||
16 | impl 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 | ||
33 | pub(crate) fn incremental_reparse( | 11 | pub(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 | ||
45 | fn reparse_leaf<'node>( | 23 | fn 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 | ||
71 | fn reparse_block<'node>( | 49 | fn 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 | ||
86 | fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String { | 64 | fn 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 @@ | |||
1 | use crate::{TextRange, TextUnit}; | 1 | use crate::TextRange; |
2 | |||
3 | pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | ||
4 | range.start() <= offset && offset <= range.end() | ||
5 | } | ||
6 | 2 | ||
7 | pub fn intersect(r1: TextRange, r2: TextRange) -> Option<TextRange> { | 3 | pub 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 @@ | |||
1 | use std::{fmt, ops}; | 1 | use std::{fmt, ops}; |
2 | 2 | ||
3 | use ra_text_edit::text_utils::contains_offset_nonstrict; | ||
3 | use crate::{ | 4 | use 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)] |
61 | pub struct AtomEdit { | 61 | pub struct AtomTextEdit { |
62 | pub delete: TextRange, | 62 | pub delete: TextRange, |
63 | pub insert: String, | 63 | pub insert: String, |
64 | } | 64 | } |
65 | 65 | ||
66 | impl AtomEdit { | 66 | impl 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 | ||
117 | impl AtomEdit { | 117 | impl 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] | ||
2 | edition = "2018" | ||
3 | name = "ra_text_edit" | ||
4 | version = "0.1.0" | ||
5 | authors = ["Aleksey Kladov <[email protected]>"] | ||
6 | publish = false | ||
7 | |||
8 | [dependencies] | ||
9 | text_unit = "0.1.5" | ||
10 | |||
11 | [dev-dependencies] | ||
12 | test_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 @@ | |||
1 | mod text_edit; | ||
2 | pub mod text_utils; | ||
3 | |||
4 | pub use crate::text_edit::{TextEdit, TextEditBuilder}; | ||
5 | |||
6 | use text_unit::{TextRange, TextUnit}; | ||
7 | |||
8 | #[derive(Debug, Clone)] | ||
9 | pub struct AtomTextEdit { | ||
10 | pub delete: TextRange, | ||
11 | pub insert: String, | ||
12 | } | ||
13 | |||
14 | impl 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 @@ | |||
1 | use crate::{TextRange, TextUnit}; | 1 | use crate::AtomTextEdit; |
2 | use ra_syntax::{text_utils::contains_offset_nonstrict, AtomEdit}; | 2 | use crate::text_utils::contains_offset_nonstrict; |
3 | use text_unit::{TextRange, TextUnit}; | ||
3 | 4 | ||
4 | #[derive(Debug, Clone)] | 5 | #[derive(Debug, Clone)] |
5 | pub struct Edit { | 6 | pub struct TextEdit { |
6 | atoms: Vec<AtomEdit>, | 7 | atoms: Vec<AtomTextEdit>, |
7 | } | 8 | } |
8 | 9 | ||
9 | #[derive(Debug)] | 10 | #[derive(Debug)] |
10 | pub struct EditBuilder { | 11 | pub struct TextEditBuilder { |
11 | atoms: Vec<AtomEdit>, | 12 | atoms: Vec<AtomTextEdit>, |
12 | } | 13 | } |
13 | 14 | ||
14 | impl EditBuilder { | 15 | impl 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 | ||
42 | impl Edit { | 43 | impl 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 @@ | |||
1 | use text_unit::{TextRange, TextUnit}; | ||
2 | |||
3 | pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | ||
4 | range.start() <= offset && offset <= range.end() | ||
5 | } | ||