mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
fix join lines selection
This commit is contained in:
parent
09ea0ca7e5
commit
7d95d38ecb
4 changed files with 54 additions and 58 deletions
|
@ -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"),
|
||||||
]));
|
]));
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
|
||||||
}");
|
}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue