fix join lines selection

This commit is contained in:
Aleksey Kladov 2018-08-29 18:35:28 +03:00
parent 09ea0ca7e5
commit 7d95d38ecb
4 changed files with 54 additions and 58 deletions

View file

@ -41,23 +41,21 @@ fn test_resolve_module() {
world.change_file(FileId(1), Some("mod foo;".to_string())); world.change_file(FileId(1), Some("mod foo;".to_string()));
world.change_file(FileId(2), Some("".to_string())); world.change_file(FileId(2), Some("".to_string()));
let snap = world.snapshot(FileMap(&[ let snap = world.analysis(FileMap(&[
(1, "/lib.rs"), (1, "/lib.rs"),
(2, "/foo.rs"), (2, "/foo.rs"),
])); ]));
let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into()) let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into());
.unwrap();
assert_eq_dbg( assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
&symbols, &symbols,
); );
let snap = world.snapshot(FileMap(&[ let snap = world.analysis(FileMap(&[
(1, "/lib.rs"), (1, "/lib.rs"),
(2, "/foo/mod.rs") (2, "/foo/mod.rs")
])); ]));
let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into()) let symbols = snap.approximately_resolve_symbol(FileId(1), 4.into());
.unwrap();
assert_eq_dbg( assert_eq_dbg(
r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#, r#"[(FileId(2), FileSymbol { name: "foo", node_range: [0; 0), kind: MODULE })]"#,
&symbols, &symbols,
@ -69,11 +67,17 @@ fn test_unresolved_module_diagnostic() {
let mut world = WorldState::new(); let mut world = WorldState::new();
world.change_file(FileId(1), Some("mod foo;".to_string())); world.change_file(FileId(1), Some("mod foo;".to_string()));
let snap = world.snapshot(FileMap(&[(1, "/lib.rs")])); let snap = world.analysis(FileMap(&[(1, "/lib.rs")]));
let diagnostics = snap.diagnostics(FileId(1)).unwrap(); let diagnostics = snap.diagnostics(FileId(1));
assert_eq_dbg( assert_eq_dbg(
r#"[(Diagnostic { range: [4; 7), msg: "unresolved module" }, r#"[Diagnostic {
Some(QuickFix { fs_ops: [CreateFile { anchor: FileId(1), path: "../foo.rs" }] }))]"#, message: "unresolved module",
range: [4; 7),
fix: Some(SourceChange {
label: "create module",
source_file_edits: [],
file_system_edits: [CreateFile { anchor: FileId(1), path: "../foo.rs" }],
cursor_position: None }) }]"#,
&diagnostics, &diagnostics,
); );
} }
@ -83,8 +87,8 @@ fn test_unresolved_module_diagnostic_no_diag_for_inline_mode() {
let mut world = WorldState::new(); let mut world = WorldState::new();
world.change_file(FileId(1), Some("mod foo {}".to_string())); world.change_file(FileId(1), Some("mod foo {}".to_string()));
let snap = world.snapshot(FileMap(&[(1, "/lib.rs")])); let snap = world.analysis(FileMap(&[(1, "/lib.rs")]));
let diagnostics = snap.diagnostics(FileId(1)).unwrap(); let diagnostics = snap.diagnostics(FileId(1));
assert_eq_dbg( assert_eq_dbg(
r#"[]"#, r#"[]"#,
&diagnostics, &diagnostics,
@ -97,7 +101,7 @@ fn test_resolve_parent_module() {
world.change_file(FileId(1), Some("mod foo;".to_string())); world.change_file(FileId(1), Some("mod foo;".to_string()));
world.change_file(FileId(2), Some("".to_string())); world.change_file(FileId(2), Some("".to_string()));
let snap = world.snapshot(FileMap(&[ let snap = world.analysis(FileMap(&[
(1, "/lib.rs"), (1, "/lib.rs"),
(2, "/foo.rs"), (2, "/foo.rs"),
])); ]));

View file

@ -13,7 +13,6 @@ use libsyntax2::{
use {EditBuilder, Edit, find_node_at_offset}; use {EditBuilder, Edit, find_node_at_offset};
// TODO: rename to FileEdit
#[derive(Debug)] #[derive(Debug)]
pub struct LocalEdit { pub struct LocalEdit {
pub edit: Edit, pub edit: Edit,

View file

@ -1,5 +1,8 @@
use {TextRange, TextUnit}; use {TextRange, TextUnit};
use libsyntax2::AtomEdit; use libsyntax2::{
AtomEdit,
text_utils::contains_offset_nonstrict,
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Edit { pub struct Edit {
@ -15,19 +18,15 @@ impl EditBuilder {
pub fn new() -> EditBuilder { pub fn new() -> EditBuilder {
EditBuilder { atoms: Vec::new() } EditBuilder { atoms: Vec::new() }
} }
pub fn replace(&mut self, range: TextRange, replace_with: String) { pub fn replace(&mut self, range: TextRange, replace_with: String) {
self.atoms.push(AtomEdit::replace(range, replace_with)) self.atoms.push(AtomEdit::replace(range, replace_with))
} }
pub fn delete(&mut self, range: TextRange) { pub fn delete(&mut self, range: TextRange) {
self.atoms.push(AtomEdit::delete(range)) self.atoms.push(AtomEdit::delete(range))
} }
pub fn insert(&mut self, offset: TextUnit, text: String) { pub fn insert(&mut self, offset: TextUnit, text: String) {
self.atoms.push(AtomEdit::insert(offset, text)) self.atoms.push(AtomEdit::insert(offset, text))
} }
pub fn finish(self) -> Edit { pub fn finish(self) -> Edit {
let mut atoms = self.atoms; let mut atoms = self.atoms;
atoms.sort_by_key(|a| a.delete.start()); atoms.sort_by_key(|a| a.delete.start());
@ -36,6 +35,9 @@ impl EditBuilder {
} }
Edit { atoms } Edit { atoms }
} }
pub fn invalidates_offset(&self, offset: TextUnit) -> bool {
self.atoms.iter().any(|atom| contains_offset_nonstrict(atom.delete, offset))
}
} }
impl Edit { impl Edit {

View file

@ -45,10 +45,11 @@ pub fn join_lines(file: &File, range: TextRange) -> LocalEdit {
for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') { for (pos, _) in text[range].bytes().enumerate().filter(|&(_, b)| b == b'\n') {
let pos: TextUnit = (pos as u32).into(); let pos: TextUnit = (pos as u32).into();
let off = node.range().start() + range.start() + pos; let off = node.range().start() + range.start() + pos;
if !edit.invalidates_offset(off) {
remove_newline(&mut edit, node, text.as_str(), off); remove_newline(&mut edit, node, text.as_str(), off);
} }
} }
eprintln!("{:?}", edit); }
LocalEdit { LocalEdit {
edit: edit.finish(), edit: edit.finish(),
@ -239,9 +240,7 @@ fn foo() {
}"); }");
} }
#[test] fn check_join_lines_sel(before: &str, after: &str) {
fn test_join_lines_selection() {
fn do_check(before: &str, after: &str) {
let (sel, before) = extract_range(before); let (sel, before) = extract_range(before);
let file = File::parse(&before); let file = File::parse(&before);
let result = join_lines(&file, sel); let result = join_lines(&file, sel);
@ -249,7 +248,9 @@ fn foo() {
assert_eq_text!(after, &actual); assert_eq_text!(after, &actual);
} }
do_check(r" #[test]
fn test_join_lines_selection_fn_args() {
check_join_lines_sel(r"
fn foo() { fn foo() {
<|>foo(1, <|>foo(1,
2, 2,
@ -261,15 +262,22 @@ fn foo() {
foo(1, 2, 3) foo(1, 2, 3)
} }
"); ");
}
do_check(r" #[test]
fn test_join_lines_selection_struct() {
check_join_lines_sel(r"
struct Foo <|>{ struct Foo <|>{
f: u32, f: u32,
}<|> }<|>
", r" ", r"
struct Foo { f: u32 } struct Foo { f: u32 }
"); ");
do_check(r" }
#[test]
fn test_join_lines_selection_dot_chain() {
check_join_lines_sel(r"
fn foo() { fn foo() {
join(<|>type_params.type_params() join(<|>type_params.type_params()
.filter_map(|it| it.name()) .filter_map(|it| it.name())
@ -278,39 +286,22 @@ fn foo() {
fn foo() { fn foo() {
join(type_params.type_params().filter_map(|it| it.name()).map(|it| it.text())) join(type_params.type_params().filter_map(|it| it.name()).map(|it| it.text()))
}"); }");
}
do_check(r" #[test]
pub fn handle_find_matching_brace( fn test_join_lines_selection_lambda_block_body() {
world: ServerWorld, check_join_lines_sel(r"
params: req::FindMatchingBraceParams, pub fn handle_find_matching_brace() {
) -> Result<Vec<Position>> { params.offsets
let file_id = params.text_document.try_conv_with(&world)?;
let file = world.analysis().file_syntax(file_id);
let line_index = world.analysis().file_line_index(file_id);
let res = params.offsets
.into_iter()
.map_conv_with(&line_index)
.map(|offset| <|>{ .map(|offset| <|>{
world.analysis().matching_brace(&file, offset).unwrap_or(offset) world.analysis().matching_brace(&file, offset).unwrap_or(offset)
}<|>) }<|>)
.map_conv_with(&line_index)
.collect(); .collect();
Ok(res)
}", r" }", r"
pub fn handle_find_matching_brace( pub fn handle_find_matching_brace() {
world: ServerWorld, params.offsets
params: req::FindMatchingBraceParams,
) -> Result<Vec<Position>> {
let file_id = params.text_document.try_conv_with(&world)?;
let file = world.analysis().file_syntax(file_id);
let line_index = world.analysis().file_line_index(file_id);
let res = params.offsets
.into_iter()
.map_conv_with(&line_index)
.map(|offset| world.analysis().matching_brace(&file, offset).unwrap_or(offset)) .map(|offset| world.analysis().matching_brace(&file, offset).unwrap_or(offset))
.map_conv_with(&line_index)
.collect(); .collect();
Ok(res)
}"); }");
} }