From 7344d28768c43d8955bf23c183d606be08f27c64 Mon Sep 17 00:00:00 2001 From: Bernardo Date: Mon, 10 Dec 2018 22:09:12 +0100 Subject: extract AtomEdit and Edit into new ra_text_edit crate --- Cargo.lock | 12 ++++ crates/ra_analysis/Cargo.toml | 1 + crates/ra_analysis/src/completion.rs | 3 +- crates/ra_analysis/src/lib.rs | 3 +- crates/ra_editor/Cargo.toml | 1 + crates/ra_editor/src/edit.rs | 83 ------------------------- crates/ra_editor/src/lib.rs | 4 +- crates/ra_editor/src/typing.rs | 3 +- crates/ra_lsp_server/Cargo.toml | 1 + crates/ra_lsp_server/src/conv.rs | 3 +- crates/ra_lsp_server/src/main_loop/handlers.rs | 3 +- crates/ra_syntax/Cargo.toml | 1 + crates/ra_syntax/src/lib.rs | 2 +- crates/ra_syntax/src/reparsing.rs | 24 +------- crates/ra_syntax/src/text_utils.rs | 6 +- crates/ra_syntax/src/yellow/syntax_text.rs | 3 +- crates/ra_text_edit/Cargo.toml | 12 ++++ crates/ra_text_edit/src/edit.rs | 84 ++++++++++++++++++++++++++ crates/ra_text_edit/src/lib.rs | 29 +++++++++ crates/ra_text_edit/src/text_utils.rs | 5 ++ 20 files changed, 162 insertions(+), 121 deletions(-) delete mode 100644 crates/ra_editor/src/edit.rs create mode 100644 crates/ra_text_edit/Cargo.toml create mode 100644 crates/ra_text_edit/src/edit.rs create mode 100644 crates/ra_text_edit/src/lib.rs create mode 100644 crates/ra_text_edit/src/text_utils.rs diff --git a/Cargo.lock b/Cargo.lock index 1f69a91b2..56d5c65b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,6 +610,7 @@ dependencies = [ "ra_editor 0.1.0", "ra_hir 0.1.0", "ra_syntax 0.1.0", + "ra_text_edit 0.1.0", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -649,6 +650,7 @@ dependencies = [ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "join_to_string 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ra_syntax 0.1.0", + "ra_text_edit 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "superslice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", @@ -687,6 +689,7 @@ dependencies = [ "ra_analysis 0.1.0", "ra_editor 0.1.0", "ra_syntax 0.1.0", + "ra_text_edit 0.1.0", "rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -710,6 +713,7 @@ dependencies = [ "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ra_text_edit 0.1.0", "rowan 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -717,6 +721,14 @@ dependencies = [ "walkdir 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ra_text_edit" +version = "0.1.0" +dependencies = [ + "test_utils 0.1.0", + "text_unit 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.3" 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" parking_lot = "0.6.4" ra_syntax = { path = "../ra_syntax" } ra_editor = { path = "../ra_editor" } +ra_text_edit = { path = "../ra_text_edit" } ra_db = { path = "../ra_db" } hir = { path = "../ra_hir", package = "ra_hir" } test_utils = { path = "../test_utils" } diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs index 0f154112a..e83330966 100644 --- a/crates/ra_analysis/src/completion.rs +++ b/crates/ra_analysis/src/completion.rs @@ -1,10 +1,11 @@ mod reference_completion; use ra_editor::find_node_at_offset; +use ra_text_edit::AtomEdit; use ra_syntax::{ algo::visit::{visitor_ctx, VisitorCtx}, ast, - AstNode, AtomEdit, + AstNode, SyntaxNodeRef, }; use ra_db::SyntaxDatabase; diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index eaf24cb36..2f8f1dab5 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -18,7 +18,8 @@ pub mod mock_analysis; use std::{fmt, sync::Arc}; -use ra_syntax::{AtomEdit, SourceFileNode, TextRange, TextUnit}; +use ra_syntax::{SourceFileNode, TextRange, TextUnit}; +use ra_text_edit::AtomEdit; use ra_db::FileResolverImp; use rayon::prelude::*; use relative_path::RelativePathBuf; 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" rustc-hash = "1.0" ra_syntax = { path = "../ra_syntax" } +ra_text_edit = { path = "../ra_text_edit" } [dev-dependencies] test_utils = { path = "../test_utils" } diff --git a/crates/ra_editor/src/edit.rs b/crates/ra_editor/src/edit.rs deleted file mode 100644 index 372b8d14c..000000000 --- a/crates/ra_editor/src/edit.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::{TextRange, TextUnit}; -use ra_syntax::{text_utils::contains_offset_nonstrict, AtomEdit}; - -#[derive(Debug, Clone)] -pub struct Edit { - atoms: Vec, -} - -#[derive(Debug)] -pub struct EditBuilder { - atoms: Vec, -} - -impl EditBuilder { - pub fn new() -> EditBuilder { - EditBuilder { atoms: Vec::new() } - } - pub fn replace(&mut self, range: TextRange, replace_with: String) { - self.atoms.push(AtomEdit::replace(range, replace_with)) - } - pub fn delete(&mut self, range: TextRange) { - self.atoms.push(AtomEdit::delete(range)) - } - pub fn insert(&mut self, offset: TextUnit, text: String) { - self.atoms.push(AtomEdit::insert(offset, text)) - } - pub fn finish(self) -> Edit { - let mut atoms = self.atoms; - atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); - for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { - assert!(a1.delete.end() <= a2.delete.start()) - } - Edit { atoms } - } - pub fn invalidates_offset(&self, offset: TextUnit) -> bool { - self.atoms - .iter() - .any(|atom| contains_offset_nonstrict(atom.delete, offset)) - } -} - -impl Edit { - pub fn into_atoms(self) -> Vec { - self.atoms - } - - pub fn apply(&self, text: &str) -> String { - let mut total_len = text.len(); - for atom in self.atoms.iter() { - total_len += atom.insert.len(); - total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; - } - let mut buf = String::with_capacity(total_len); - let mut prev = 0; - for atom in self.atoms.iter() { - let start = u32::from(atom.delete.start()) as usize; - let end = u32::from(atom.delete.end()) as usize; - if start > prev { - buf.push_str(&text[prev..start]); - } - buf.push_str(&atom.insert); - prev = end; - } - buf.push_str(&text[prev..text.len()]); - assert_eq!(buf.len(), total_len); - buf - } - - pub fn apply_to_offset(&self, offset: TextUnit) -> Option { - let mut res = offset; - for atom in self.atoms.iter() { - if atom.delete.start() >= offset { - break; - } - if offset < atom.delete.end() { - return None; - } - res += TextUnit::of_str(&atom.insert); - res -= atom.delete.len(); - } - Some(res) - } -} diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index ce080ee97..ddc44c778 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -1,5 +1,4 @@ mod code_actions; -mod edit; mod extend_selection; mod folding_ranges; mod line_index; @@ -10,14 +9,13 @@ mod typing; pub use self::{ code_actions::{add_derive, add_impl, flip_comma, introduce_variable, LocalEdit}, - edit::{Edit, EditBuilder}, extend_selection::extend_selection, folding_ranges::{folding_ranges, Fold, FoldKind}, line_index::{LineCol, LineIndex}, symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, typing::{join_lines, on_enter, on_eq_typed}, }; -pub use ra_syntax::AtomEdit; +use ra_text_edit::{Edit, EditBuilder}; use ra_syntax::{ algo::find_leaf_at_offset, ast::{self, AstNode, NameOwner}, diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 01acdda7c..cf9af001b 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs @@ -3,11 +3,12 @@ use std::mem; use ra_syntax::{ algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset}, ast, - text_utils::{contains_offset_nonstrict, intersect}, + text_utils::intersect, AstNode, SourceFileNode, SyntaxKind, SyntaxKind::*, SyntaxNodeRef, TextRange, TextUnit, }; +use ra_text_edit::text_utils::contains_offset_nonstrict; use crate::{find_node_at_offset, EditBuilder, LocalEdit}; 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" ra_syntax = { path = "../ra_syntax" } ra_editor = { path = "../ra_editor" } +ra_text_edit = { path = "../ra_text_edit" } ra_analysis = { path = "../ra_analysis" } gen_lsp_server = { path = "../gen_lsp_server" } diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 28368787c..8bf8576be 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -3,7 +3,8 @@ use languageserver_types::{ TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, }; use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; -use ra_editor::{AtomEdit, Edit, LineCol, LineIndex}; +use ra_editor::{LineCol, LineIndex}; +use ra_text_edit::{AtomEdit, Edit}; use ra_syntax::{SyntaxKind, TextRange, TextUnit}; use crate::{req, server_world::ServerWorld, Result}; 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::{ WorkspaceEdit, ParameterInformation, SignatureInformation, Hover, HoverContents, }; use ra_analysis::{FileId, FoldKind, Query, RunnableKind, FilePosition}; -use ra_syntax::{TextUnit, text_utils::{contains_offset_nonstrict, intersect}}; +use ra_syntax::{TextUnit, text_utils::intersect}; +use ra_text_edit::text_utils::contains_offset_nonstrict; use rustc_hash::FxHashMap; use serde_json::to_value; 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" parking_lot = "0.6.0" rowan = "0.1.2" text_unit = "0.1.5" +ra_text_edit = { path = "../ra_text_edit" } [dev-dependencies] test_utils = { path = "../test_utils" } diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 0e5c9baad..7295fb237 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}; pub use crate::{ ast::AstNode, lexer::{tokenize, Token}, - reparsing::AtomEdit, syntax_kinds::SyntaxKind, yellow::{ Direction, OwnedRoot, RefRoot, SyntaxError, SyntaxNode, SyntaxNodeRef, TreeRoot, WalkEvent, Location, }, }; +use ra_text_edit::AtomEdit; use crate::yellow::GreenNode; /// `SourceFileNode` represents a parse tree for a single Rust file. diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index 732fb0e4a..873809a5a 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -6,29 +6,7 @@ use crate::parser_impl; use crate::text_utils::replace_range; use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; use crate::{SyntaxKind::*, TextRange, TextUnit}; - -#[derive(Debug, Clone)] -pub struct AtomEdit { - pub delete: TextRange, - pub insert: String, -} - -impl AtomEdit { - pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { - AtomEdit { - delete: range, - insert: replace_with, - } - } - - pub fn delete(range: TextRange) -> AtomEdit { - AtomEdit::replace(range, String::new()) - } - - pub fn insert(offset: TextUnit, text: String) -> AtomEdit { - AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) - } -} +use ra_text_edit::AtomEdit; pub(crate) fn incremental_reparse( node: SyntaxNodeRef, 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 @@ -use crate::{TextRange, TextUnit}; - -pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { - range.start() <= offset && offset <= range.end() -} +use crate::TextRange; pub fn intersect(r1: TextRange, r2: TextRange) -> Option { 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 @@ use std::{fmt, ops}; +use ra_text_edit::text_utils::contains_offset_nonstrict; use crate::{ - text_utils::{contains_offset_nonstrict, intersect}, + text_utils::intersect, SyntaxNodeRef, TextRange, TextUnit, }; 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 @@ +[package] +edition = "2018" +name = "ra_text_edit" +version = "0.1.0" +authors = ["Aleksey Kladov "] +publish = false + +[dependencies] +text_unit = "0.1.5" + +[dev-dependencies] +test_utils = { path = "../test_utils" } diff --git a/crates/ra_text_edit/src/edit.rs b/crates/ra_text_edit/src/edit.rs new file mode 100644 index 000000000..560cf2bbc --- /dev/null +++ b/crates/ra_text_edit/src/edit.rs @@ -0,0 +1,84 @@ +use crate::AtomEdit; +use crate::text_utils::contains_offset_nonstrict; +use text_unit::{TextRange, TextUnit}; + +#[derive(Debug, Clone)] +pub struct Edit { + atoms: Vec, +} + +#[derive(Debug)] +pub struct EditBuilder { + atoms: Vec, +} + +impl EditBuilder { + pub fn new() -> EditBuilder { + EditBuilder { atoms: Vec::new() } + } + pub fn replace(&mut self, range: TextRange, replace_with: String) { + self.atoms.push(AtomEdit::replace(range, replace_with)) + } + pub fn delete(&mut self, range: TextRange) { + self.atoms.push(AtomEdit::delete(range)) + } + pub fn insert(&mut self, offset: TextUnit, text: String) { + self.atoms.push(AtomEdit::insert(offset, text)) + } + pub fn finish(self) -> Edit { + let mut atoms = self.atoms; + atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); + for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { + assert!(a1.delete.end() <= a2.delete.start()) + } + Edit { atoms } + } + pub fn invalidates_offset(&self, offset: TextUnit) -> bool { + self.atoms + .iter() + .any(|atom| contains_offset_nonstrict(atom.delete, offset)) + } +} + +impl Edit { + pub fn into_atoms(self) -> Vec { + self.atoms + } + + pub fn apply(&self, text: &str) -> String { + let mut total_len = text.len(); + for atom in self.atoms.iter() { + total_len += atom.insert.len(); + total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; + } + let mut buf = String::with_capacity(total_len); + let mut prev = 0; + for atom in self.atoms.iter() { + let start = u32::from(atom.delete.start()) as usize; + let end = u32::from(atom.delete.end()) as usize; + if start > prev { + buf.push_str(&text[prev..start]); + } + buf.push_str(&atom.insert); + prev = end; + } + buf.push_str(&text[prev..text.len()]); + assert_eq!(buf.len(), total_len); + buf + } + + pub fn apply_to_offset(&self, offset: TextUnit) -> Option { + let mut res = offset; + for atom in self.atoms.iter() { + if atom.delete.start() >= offset { + break; + } + if offset < atom.delete.end() { + return None; + } + res += TextUnit::of_str(&atom.insert); + res -= atom.delete.len(); + } + Some(res) + } +} diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs new file mode 100644 index 000000000..789471e8a --- /dev/null +++ b/crates/ra_text_edit/src/lib.rs @@ -0,0 +1,29 @@ +mod edit; +pub mod text_utils; + +pub use crate::edit::{Edit, EditBuilder}; + +use text_unit::{TextRange, TextUnit}; + +#[derive(Debug, Clone)] +pub struct AtomEdit { + pub delete: TextRange, + pub insert: String, +} + +impl AtomEdit { + pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { + AtomEdit { + delete: range, + insert: replace_with, + } + } + + pub fn delete(range: TextRange) -> AtomEdit { + AtomEdit::replace(range, String::new()) + } + + pub fn insert(offset: TextUnit, text: String) -> AtomEdit { + AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) + } +} 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 @@ +use text_unit::{TextRange, TextUnit}; + +pub fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { + range.start() <= offset && offset <= range.end() +} -- cgit v1.2.3 From 0527e3b283af0153cf13fa64fe73862a5b7655c8 Mon Sep 17 00:00:00 2001 From: Bernardo Date: Tue, 11 Dec 2018 19:07:17 +0100 Subject: rename Edit to TextEdit and AtomEdit to AtomTextEdit --- crates/ra_analysis/src/completion.rs | 4 +- crates/ra_analysis/src/lib.rs | 4 +- crates/ra_editor/src/code_actions.rs | 12 ++-- crates/ra_editor/src/lib.rs | 2 +- crates/ra_editor/src/typing.rs | 23 +++--- crates/ra_lsp_server/src/conv.rs | 22 +++--- crates/ra_syntax/src/lib.rs | 8 +-- crates/ra_syntax/src/reparsing.rs | 16 ++--- .../tests/data/parser/fuzz-failures/0000.rs | 38 +++++----- crates/ra_text_edit/src/edit.rs | 84 ---------------------- crates/ra_text_edit/src/lib.rs | 20 +++--- crates/ra_text_edit/src/text_edit.rs | 84 ++++++++++++++++++++++ 12 files changed, 161 insertions(+), 156 deletions(-) delete mode 100644 crates/ra_text_edit/src/edit.rs create mode 100644 crates/ra_text_edit/src/text_edit.rs diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs index e83330966..f480af611 100644 --- a/crates/ra_analysis/src/completion.rs +++ b/crates/ra_analysis/src/completion.rs @@ -1,7 +1,7 @@ mod reference_completion; use ra_editor::find_node_at_offset; -use ra_text_edit::AtomEdit; +use ra_text_edit::AtomTextEdit; use ra_syntax::{ algo::visit::{visitor_ctx, VisitorCtx}, ast, @@ -34,7 +34,7 @@ pub(crate) fn completions( let original_file = db.source_file(position.file_id); // Insert a fake ident to get a valid parse tree let file = { - let edit = AtomEdit::insert(position.offset, "intellijRulezz".to_string()); + let edit = AtomTextEdit::insert(position.offset, "intellijRulezz".to_string()); original_file.reparse(&edit) }; diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 2f8f1dab5..22fff71ab 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -19,7 +19,7 @@ pub mod mock_analysis; use std::{fmt, sync::Arc}; use ra_syntax::{SourceFileNode, TextRange, TextUnit}; -use ra_text_edit::AtomEdit; +use ra_text_edit::AtomTextEdit; use ra_db::FileResolverImp; use rayon::prelude::*; use relative_path::RelativePathBuf; @@ -121,7 +121,7 @@ pub struct SourceChange { #[derive(Debug)] pub struct SourceFileNodeEdit { pub file_id: FileId, - pub edits: Vec, + pub edits: Vec, } #[derive(Debug)] 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::{ SyntaxNodeRef, TextRange, TextUnit, }; -use crate::{find_node_at_offset, Edit, EditBuilder}; +use crate::{find_node_at_offset, TextEdit, TextEditBuilder}; #[derive(Debug)] pub struct LocalEdit { - pub edit: Edit, + pub edit: TextEdit, pub cursor_position: Option, } @@ -26,7 +26,7 @@ pub fn flip_comma<'a>( let prev = non_trivia_sibling(comma, Direction::Prev)?; let next = non_trivia_sibling(comma, Direction::Next)?; Some(move || { - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); edit.replace(prev.range(), next.text().to_string()); edit.replace(next.range(), prev.text().to_string()); LocalEdit { @@ -49,7 +49,7 @@ pub fn add_derive<'a>( .filter(|(name, _arg)| name == "derive") .map(|(_name, arg)| arg) .next(); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); let offset = match derive_attr { None => { edit.insert(node_start, "#[derive()]\n".to_string()); @@ -82,7 +82,7 @@ pub fn add_impl<'a>( Some(move || { let type_params = nominal.type_param_list(); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); let start_offset = nominal.syntax().range().end(); let mut buf = String::new(); buf.push_str("\n\nimpl"); @@ -129,7 +129,7 @@ pub fn introduce_variable<'a>( } return Some(move || { let mut buf = String::new(); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); buf.push_str("let var_name = "); expr.syntax().text().push_to(&mut buf); diff --git a/crates/ra_editor/src/lib.rs b/crates/ra_editor/src/lib.rs index ddc44c778..36cabed25 100644 --- a/crates/ra_editor/src/lib.rs +++ b/crates/ra_editor/src/lib.rs @@ -15,7 +15,7 @@ pub use self::{ symbols::{file_structure, file_symbols, FileSymbol, StructureNode}, typing::{join_lines, on_enter, on_eq_typed}, }; -use ra_text_edit::{Edit, EditBuilder}; +use ra_text_edit::{TextEdit, TextEditBuilder}; use ra_syntax::{ algo::find_leaf_at_offset, ast::{self, AstNode, NameOwner}, diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index cf9af001b..46a6e2d62 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs @@ -10,7 +10,7 @@ use ra_syntax::{ }; use ra_text_edit::text_utils::contains_offset_nonstrict; -use crate::{find_node_at_offset, EditBuilder, LocalEdit}; +use crate::{find_node_at_offset, TextEditBuilder, LocalEdit}; pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { let range = if range.is_empty() { @@ -19,7 +19,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { let pos = match text.find('\n') { None => { return LocalEdit { - edit: EditBuilder::new().finish(), + edit: TextEditBuilder::new().finish(), cursor_position: None, }; } @@ -31,7 +31,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { }; let node = find_covering_node(file.syntax(), range); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); for node in node.descendants() { let text = match node.leaf_text() { Some(text) => text, @@ -73,7 +73,7 @@ pub fn on_enter(file: &SourceFileNode, offset: TextUnit) -> Option { let indent = node_indent(file, comment.syntax())?; let inserted = format!("\n{}{} ", indent, prefix); let cursor_position = offset + TextUnit::of_str(&inserted); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); edit.insert(offset, inserted); Some(LocalEdit { edit: edit.finish(), @@ -123,7 +123,7 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option return None; } let offset = let_stmt.syntax().range().end(); - let mut edit = EditBuilder::new(); + let mut edit = TextEditBuilder::new(); edit.insert(offset, ";".to_string()); Some(LocalEdit { edit: edit.finish(), @@ -131,7 +131,12 @@ pub fn on_eq_typed(file: &SourceFileNode, offset: TextUnit) -> Option }) } -fn remove_newline(edit: &mut EditBuilder, node: SyntaxNodeRef, node_text: &str, offset: TextUnit) { +fn remove_newline( + edit: &mut TextEditBuilder, + node: SyntaxNodeRef, + node_text: &str, + offset: TextUnit, +) { if node.kind() != WHITESPACE || node_text.bytes().filter(|&b| b == b'\n').count() != 1 { // The node is either the first or the last in the file let suff = &node_text[TextRange::from_to( @@ -192,7 +197,7 @@ fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { } } -fn join_single_expr_block(edit: &mut EditBuilder, node: SyntaxNodeRef) -> Option<()> { +fn join_single_expr_block(edit: &mut TextEditBuilder, node: SyntaxNodeRef) -> Option<()> { let block = ast::Block::cast(node.parent()?)?; let block_expr = ast::BlockExpr::cast(block.syntax().parent()?)?; let expr = single_expr(block)?; @@ -270,14 +275,14 @@ fn foo() { fn test_join_lines_lambda_block() { check_join_lines( r" -pub fn reparse(&self, edit: &AtomEdit) -> File { +pub fn reparse(&self, edit: &AtomTextEdit) -> File { <|>self.incremental_reparse(edit).unwrap_or_else(|| { self.full_reparse(edit) }) } ", r" -pub fn reparse(&self, edit: &AtomEdit) -> File { +pub fn reparse(&self, edit: &AtomTextEdit) -> File { <|>self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) } ", diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 8bf8576be..7467f472c 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -1,10 +1,10 @@ use languageserver_types::{ - Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, - TextDocumentItem, TextDocumentPositionParams, TextEdit, Url, VersionedTextDocumentIdentifier, + self, Location, Position, Range, SymbolKind, TextDocumentEdit, TextDocumentIdentifier, + TextDocumentItem, TextDocumentPositionParams, Url, VersionedTextDocumentIdentifier, }; use ra_analysis::{FileId, FileSystemEdit, SourceChange, SourceFileNodeEdit, FilePosition}; use ra_editor::{LineCol, LineIndex}; -use ra_text_edit::{AtomEdit, Edit}; +use ra_text_edit::{AtomTextEdit, TextEdit}; use ra_syntax::{SyntaxKind, TextRange, TextUnit}; use crate::{req, server_world::ServerWorld, Result}; @@ -92,11 +92,11 @@ impl ConvWith for Range { } } -impl ConvWith for Edit { +impl ConvWith for TextEdit { type Ctx = LineIndex; - type Output = Vec; + type Output = Vec; - fn conv_with(self, line_index: &LineIndex) -> Vec { + fn conv_with(self, line_index: &LineIndex) -> Vec { self.into_atoms() .into_iter() .map_conv_with(line_index) @@ -104,12 +104,12 @@ impl ConvWith for Edit { } } -impl ConvWith for AtomEdit { +impl ConvWith for AtomTextEdit { type Ctx = LineIndex; - type Output = TextEdit; + type Output = languageserver_types::TextEdit; - fn conv_with(self, line_index: &LineIndex) -> TextEdit { - TextEdit { + fn conv_with(self, line_index: &LineIndex) -> languageserver_types::TextEdit { + languageserver_types::TextEdit { range: self.delete.conv_with(line_index), new_text: self.insert, } @@ -229,7 +229,7 @@ impl TryConvWith for SourceChange { fn translate_offset_with_edit( pre_edit_index: &LineIndex, offset: TextUnit, - edits: &[AtomEdit], + edits: &[AtomTextEdit], ) -> LineCol { let fallback = pre_edit_index.line_col(offset); let edit = match edits.first() { diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index 7295fb237..34a3aabef 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs @@ -47,7 +47,7 @@ pub use crate::{ }, }; -use ra_text_edit::AtomEdit; +use ra_text_edit::AtomTextEdit; use crate::yellow::GreenNode; /// `SourceFileNode` represents a parse tree for a single Rust file. @@ -68,15 +68,15 @@ impl SourceFileNode { parser_impl::parse_with(yellow::GreenBuilder::new(), text, &tokens, grammar::root); SourceFileNode::new(green, errors) } - pub fn reparse(&self, edit: &AtomEdit) -> SourceFileNode { + pub fn reparse(&self, edit: &AtomTextEdit) -> SourceFileNode { self.incremental_reparse(edit) .unwrap_or_else(|| self.full_reparse(edit)) } - pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option { + pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option { reparsing::incremental_reparse(self.syntax(), edit, self.errors()) .map(|(green_node, errors)| SourceFileNode::new(green_node, errors)) } - fn full_reparse(&self, edit: &AtomEdit) -> SourceFileNode { + fn full_reparse(&self, edit: &AtomTextEdit) -> SourceFileNode { let text = text_utils::replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); SourceFileNode::parse(&text) diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs index 873809a5a..208cae5c8 100644 --- a/crates/ra_syntax/src/reparsing.rs +++ b/crates/ra_syntax/src/reparsing.rs @@ -6,11 +6,11 @@ use crate::parser_impl; use crate::text_utils::replace_range; use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef}; use crate::{SyntaxKind::*, TextRange, TextUnit}; -use ra_text_edit::AtomEdit; +use ra_text_edit::AtomTextEdit; pub(crate) fn incremental_reparse( node: SyntaxNodeRef, - edit: &AtomEdit, + edit: &AtomTextEdit, errors: Vec, ) -> Option<(GreenNode, Vec)> { let (node, green, new_errors) = @@ -22,7 +22,7 @@ pub(crate) fn incremental_reparse( fn reparse_leaf<'node>( node: SyntaxNodeRef<'node>, - edit: &AtomEdit, + edit: &AtomTextEdit, ) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec)> { let node = algo::find_covering_node(node, edit.delete); match node.kind() { @@ -48,7 +48,7 @@ fn reparse_leaf<'node>( fn reparse_block<'node>( node: SyntaxNodeRef<'node>, - edit: &AtomEdit, + edit: &AtomTextEdit, ) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec)> { let (node, reparser) = find_reparsable_node(node, edit.delete)?; let text = get_text_after_edit(node, &edit); @@ -61,7 +61,7 @@ fn reparse_block<'node>( Some((node, green, new_errors)) } -fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String { +fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomTextEdit) -> String { replace_range( node.text().to_string(), edit.delete - node.range().start(), @@ -139,7 +139,7 @@ fn merge_errors( old_errors: Vec, new_errors: Vec, old_node: SyntaxNodeRef, - edit: &AtomEdit, + edit: &AtomTextEdit, ) -> Vec { let mut res = Vec::new(); for e in old_errors { @@ -166,7 +166,7 @@ mod tests { where for<'a> F: Fn( SyntaxNodeRef<'a>, - &AtomEdit, + &AtomTextEdit, ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec)>, { let (range, before) = extract_range(before); @@ -175,7 +175,7 @@ mod tests { let fully_reparsed = SourceFileNode::parse(&after); let incrementally_reparsed = { let f = SourceFileNode::parse(&before); - let edit = AtomEdit { + let edit = AtomTextEdit { delete: range, insert: replace_with.to_string(), }; 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 @@ ); File::new(green, errors) } - pub fn reparse(&self, edit: &AtomEdit) -> File { + pub fn reparse(&self, edit: &AtomTextEdit) -> File { self.incremental_reparse(edit).unwrap_or_else(|| self.full_reparse(edit)) } - pub fn incremental_reparse(&self, edit: &AtomEdit) -> Option { + pub fn incremental_reparse(&self, edit: &AtomTextEdit) -> Option { let (node, reparser) = find_reparsable_node(self.syntax(), edit.delete)?; let text = replace_range( node.text().to_string(), @@ -31,7 +31,7 @@ let errors = merge_errors(self.errors(), new_errors, node, edit); Some(File::new(green_root, errors)) } - fn full_reparse(&self, edit: &AtomEdit) -> File { + fn full_reparse(&self, edit: &AtomTextEdit) -> File { let text = replace_range(self.syntax().text().to_string(), edit.delete, &edit.insert); File::parse(&text) } @@ -58,22 +58,22 @@ } #[derive(Debug, Clone)] -pub struct AtomEdit { +pub struct AtomTextEdit { pub delete: TextRange, pub insert: String, } -impl AtomEdit { - pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { - AtomEdit { delete: range, insert: replace_with } +impl AtomTextEdit { + pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { + AtomTextEdit { delete: range, insert: replace_with } } - pub fn delete(range: TextRange) -> AtomEdit { - AtomEdit::replace(range, String::new()) + pub fn delete(range: TextRange) -> AtomTextEdit { + AtomTextEdit::replace(range, String::new()) } - pub fn insert(offset: TextUnit, text: String) -> AtomEdit { - AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) + pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit { + AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text) } } @@ -114,17 +114,17 @@ fn is_balanced(tokens: &[Token]) -> bool { pub insert: String, } -impl AtomEdit { - pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { - AtomEdit { delete: range, insert: replace_with } +impl AtomTextEdit { + pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { + AtomTextEdit { delete: range, insert: replace_with } } - pub fn delete(range: TextRange) -> AtomEdit { - AtomEdit::replace(range, String::new()) + pub fn delete(range: TextRange) -> AtomTextEdit { + AtomTextEdit::replace(range, String::new()) } - pub fn insert(offset: TextUnit, text: String) -> AtomEdit { - AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) + pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit { + AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text) } } @@ -176,7 +176,7 @@ fn merge_errors( old_errors: Vec, new_errors: Vec, old_node: SyntaxNodeRef, - edit: &AtomEdit, + edit: &AtomTextEdit, ) -> Vec { let mut res = Vec::new(); for e in old_errors { diff --git a/crates/ra_text_edit/src/edit.rs b/crates/ra_text_edit/src/edit.rs deleted file mode 100644 index 560cf2bbc..000000000 --- a/crates/ra_text_edit/src/edit.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::AtomEdit; -use crate::text_utils::contains_offset_nonstrict; -use text_unit::{TextRange, TextUnit}; - -#[derive(Debug, Clone)] -pub struct Edit { - atoms: Vec, -} - -#[derive(Debug)] -pub struct EditBuilder { - atoms: Vec, -} - -impl EditBuilder { - pub fn new() -> EditBuilder { - EditBuilder { atoms: Vec::new() } - } - pub fn replace(&mut self, range: TextRange, replace_with: String) { - self.atoms.push(AtomEdit::replace(range, replace_with)) - } - pub fn delete(&mut self, range: TextRange) { - self.atoms.push(AtomEdit::delete(range)) - } - pub fn insert(&mut self, offset: TextUnit, text: String) { - self.atoms.push(AtomEdit::insert(offset, text)) - } - pub fn finish(self) -> Edit { - let mut atoms = self.atoms; - atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); - for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { - assert!(a1.delete.end() <= a2.delete.start()) - } - Edit { atoms } - } - pub fn invalidates_offset(&self, offset: TextUnit) -> bool { - self.atoms - .iter() - .any(|atom| contains_offset_nonstrict(atom.delete, offset)) - } -} - -impl Edit { - pub fn into_atoms(self) -> Vec { - self.atoms - } - - pub fn apply(&self, text: &str) -> String { - let mut total_len = text.len(); - for atom in self.atoms.iter() { - total_len += atom.insert.len(); - total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; - } - let mut buf = String::with_capacity(total_len); - let mut prev = 0; - for atom in self.atoms.iter() { - let start = u32::from(atom.delete.start()) as usize; - let end = u32::from(atom.delete.end()) as usize; - if start > prev { - buf.push_str(&text[prev..start]); - } - buf.push_str(&atom.insert); - prev = end; - } - buf.push_str(&text[prev..text.len()]); - assert_eq!(buf.len(), total_len); - buf - } - - pub fn apply_to_offset(&self, offset: TextUnit) -> Option { - let mut res = offset; - for atom in self.atoms.iter() { - if atom.delete.start() >= offset { - break; - } - if offset < atom.delete.end() { - return None; - } - res += TextUnit::of_str(&atom.insert); - res -= atom.delete.len(); - } - Some(res) - } -} diff --git a/crates/ra_text_edit/src/lib.rs b/crates/ra_text_edit/src/lib.rs index 789471e8a..13e20f6fb 100644 --- a/crates/ra_text_edit/src/lib.rs +++ b/crates/ra_text_edit/src/lib.rs @@ -1,29 +1,29 @@ -mod edit; +mod text_edit; pub mod text_utils; -pub use crate::edit::{Edit, EditBuilder}; +pub use crate::text_edit::{TextEdit, TextEditBuilder}; use text_unit::{TextRange, TextUnit}; #[derive(Debug, Clone)] -pub struct AtomEdit { +pub struct AtomTextEdit { pub delete: TextRange, pub insert: String, } -impl AtomEdit { - pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { - AtomEdit { +impl AtomTextEdit { + pub fn replace(range: TextRange, replace_with: String) -> AtomTextEdit { + AtomTextEdit { delete: range, insert: replace_with, } } - pub fn delete(range: TextRange) -> AtomEdit { - AtomEdit::replace(range, String::new()) + pub fn delete(range: TextRange) -> AtomTextEdit { + AtomTextEdit::replace(range, String::new()) } - pub fn insert(offset: TextUnit, text: String) -> AtomEdit { - AtomEdit::replace(TextRange::offset_len(offset, 0.into()), text) + pub fn insert(offset: TextUnit, text: String) -> AtomTextEdit { + AtomTextEdit::replace(TextRange::offset_len(offset, 0.into()), text) } } diff --git a/crates/ra_text_edit/src/text_edit.rs b/crates/ra_text_edit/src/text_edit.rs new file mode 100644 index 000000000..fb46f046d --- /dev/null +++ b/crates/ra_text_edit/src/text_edit.rs @@ -0,0 +1,84 @@ +use crate::AtomTextEdit; +use crate::text_utils::contains_offset_nonstrict; +use text_unit::{TextRange, TextUnit}; + +#[derive(Debug, Clone)] +pub struct TextEdit { + atoms: Vec, +} + +#[derive(Debug)] +pub struct TextEditBuilder { + atoms: Vec, +} + +impl TextEditBuilder { + pub fn new() -> TextEditBuilder { + TextEditBuilder { atoms: Vec::new() } + } + pub fn replace(&mut self, range: TextRange, replace_with: String) { + self.atoms.push(AtomTextEdit::replace(range, replace_with)) + } + pub fn delete(&mut self, range: TextRange) { + self.atoms.push(AtomTextEdit::delete(range)) + } + pub fn insert(&mut self, offset: TextUnit, text: String) { + self.atoms.push(AtomTextEdit::insert(offset, text)) + } + pub fn finish(self) -> TextEdit { + let mut atoms = self.atoms; + atoms.sort_by_key(|a| (a.delete.start(), a.delete.end())); + for (a1, a2) in atoms.iter().zip(atoms.iter().skip(1)) { + assert!(a1.delete.end() <= a2.delete.start()) + } + TextEdit { atoms } + } + pub fn invalidates_offset(&self, offset: TextUnit) -> bool { + self.atoms + .iter() + .any(|atom| contains_offset_nonstrict(atom.delete, offset)) + } +} + +impl TextEdit { + pub fn into_atoms(self) -> Vec { + self.atoms + } + + pub fn apply(&self, text: &str) -> String { + let mut total_len = text.len(); + for atom in self.atoms.iter() { + total_len += atom.insert.len(); + total_len -= u32::from(atom.delete.end() - atom.delete.start()) as usize; + } + let mut buf = String::with_capacity(total_len); + let mut prev = 0; + for atom in self.atoms.iter() { + let start = u32::from(atom.delete.start()) as usize; + let end = u32::from(atom.delete.end()) as usize; + if start > prev { + buf.push_str(&text[prev..start]); + } + buf.push_str(&atom.insert); + prev = end; + } + buf.push_str(&text[prev..text.len()]); + assert_eq!(buf.len(), total_len); + buf + } + + pub fn apply_to_offset(&self, offset: TextUnit) -> Option { + let mut res = offset; + for atom in self.atoms.iter() { + if atom.delete.start() >= offset { + break; + } + if offset < atom.delete.end() { + return None; + } + res += TextUnit::of_str(&atom.insert); + res -= atom.delete.len(); + } + Some(res) + } +} -- cgit v1.2.3