Conversation
src/actions/mod.rs
Outdated
| }; | ||
| let input = match self.vfs.load_file(path) { | ||
| Ok(FileContents::Text(s)) => FmtInput::Text(s), | ||
| Ok(FileContents::Text(_)) => FmtInput::File(path.clone()), |
There was a problem hiding this comment.
This is an incorrect change - it will mean any changes in memory are ignored in favour of the old version on disk
src/actions/mod.rs
Outdated
| "file": "{}", | ||
| "range": [{}, {}] | ||
| }}]"#, path.to_str().unwrap(), range.start.line + 1, range.end.line + 1); | ||
| config.set().file_lines(file_lines.parse().unwrap()); |
There was a problem hiding this comment.
I guess we need a new API for rustfmt to take an optional range over a text input, rather than using this file/range approach
src/actions/mod.rs
Outdated
| let file_lines = format!(r#"[{{ | ||
| "file": "{}", | ||
| "range": [{}, {}] | ||
| }}]"#, path.to_str().unwrap(), range.start.line + 1, range.end.line + 1); |
There was a problem hiding this comment.
If this range is from rls-span, then you should use the to_one_indexed/to_zero_indexed API rather than manually adding 1. If it is not, then you should convert the range to an rls-span range in server.rs
src/actions/mod.rs
Outdated
|
|
||
| // If Rustfmt returns range of text that changed, | ||
| // we will be able to pass only range of changed text to the client. | ||
| let range = ls_util::range_from_vfs_file(&self.vfs, path); |
There was a problem hiding this comment.
Could move and rename this variable and only make one call to range_from_vfs_file
|
Thank you for reviewing! and I fixed up some codes. |
nrc
left a comment
There was a problem hiding this comment.
Thanks for the changes, I have a few more comments from re-review.
src/actions/mod.rs
Outdated
| "file": "stdin", | ||
| "range": [{}, {}] | ||
| }}]"#, range_rls.row_start.0, range_rls.row_end.0); | ||
| config.set().file_lines(file_lines.parse().unwrap()); |
There was a problem hiding this comment.
COuld we move all of this stuff inside the match/Some branch (and the decl of config before the match)? I'd like to avoid using the file_lines change if no range was given.
| } | ||
|
|
||
| #[test] | ||
| fn test_reformat_with_range() { |
There was a problem hiding this comment.
You'll need to duplicate the test_data directory so each test is pointing at its own directory (since tests run concurrently, they'll otherwise race)
src/test/mod.rs
Outdated
|
|
||
| assert_eq!(ls_server::LsService::handle_message(server.clone()), | ||
| ls_server::ServerStateChange::Continue); | ||
| expect_messages(results.clone(), &[ExpectedMessage::new(Some(42)).expect_contains(r#"{"start":{"line":0,"character":0},"end":{"line":11,"character":69}}"#) |
There was a problem hiding this comment.
Does the test ensure that code outside of the range (or at least the AST node that encloses the range) is not reformatted?
src/test/mod.rs
Outdated
| assert_eq!(ls_server::LsService::handle_message(server.clone()), | ||
| ls_server::ServerStateChange::Continue); | ||
| expect_messages(results.clone(), &[ExpectedMessage::new(Some(42)).expect_contains(r#"{"start":{"line":0,"character":0},"end":{"line":14,"character":5}}"#) | ||
| .expect_contains(r#"newText":"// Copyright 2017 The Rust Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distribution and at\n// http://rust-lang.org/COPYRIGHT.\n//\n// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or\n// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license\n// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your\n// option. This file may not be copied, modified, or distributed\n// except according to those terms.\n\npub fn main() {\n let world1 = \"world\";\n println!(\"Hello, {}!\", world1);\nlet world2 = \"world\"; println!(\"Hello, {}!\", world2);\n}"#)]); |
There was a problem hiding this comment.
Passing the range to rustfmt, it format the line feed correctly only within the range,
but the indent seems to be modified across the entire text.
Is it intended behavior of rustfmt (or, am I doing something wrong)❓
There was a problem hiding this comment.
It is not intended. However... what Rustfmt does with the range is that it rounds it up to the nearest Item ast node (a function or module, etc) and reformats the entire item. I'm not sure if that is happening here, but it might explain why stuff outside the range is formatted.
Could you copy the before and after for what Rustfmt is doing please?
There was a problem hiding this comment.
Yes, here is copy of what Rustfmt do.
For simplicity, i execute rustfmt command like follows, instead of call from rls.
cargo fmt -- --file-lines '[{"file": "path/to/file", "range": [2,3]}]'
before
pub fn main()
{
let world1 = "world"; println!("Hello, {}!", world1);
let world2 = "world"; println!("Hello, {}!", world2);
}after
pub fn main() {
let world1 = "world";
println!("Hello, {}!", world1);
let world2 = "world"; println!("Hello, {}!", world2);
}
There was a problem hiding this comment.
This looks like the first 3 lines have been formatted and so has the last line, but the forth line has not. This seems like rustfmt is being a bit buggy, but that your stuff (the RLS end) is working fine. I can't actually explain why the forth line has been skipped.
There was a problem hiding this comment.
I understood. And then, I modified a test to avoid that part. 965cd33
|
Thank you a lot for reviewing ❗️ |
aec86f8 to
965cd33
Compare
| assert_eq!(ls_server::LsService::handle_message(server.clone()), | ||
| ls_server::ServerStateChange::Continue); | ||
| expect_messages(results.clone(), &[ExpectedMessage::new(Some(42)).expect_contains(r#"{"start":{"line":0,"character":0},"end":{"line":11,"character":69}}"#) | ||
| expect_messages(results.clone(), &[ExpectedMessage::new(Some(42)).expect_contains(r#"{"start":{"line":0,"character":0},"end":{"line":12,"character":0}}"#) |
There was a problem hiding this comment.
Fixed that test failed when rebasing current master.
It seems to be able to fix #350.
nrc
left a comment
There was a problem hiding this comment.
Thanks for the changes, and sorry to make you rebase. I just had two minor things left to address.
src/actions/mod.rs
Outdated
| pub fn reformat(&self, id: usize, doc: TextDocumentIdentifier, out: &Output, opts: &FormattingOptions) { | ||
| trace!("Reformat: {} {:?} {} {}", id, doc, opts.tab_size, opts.insert_spaces); | ||
| pub fn reformat(&self, id: usize, doc: TextDocumentIdentifier, selection: Option<Range>, out: &Output, opts: &FormattingOptions) { | ||
| trace!("Reformat: {} {:?}", id, doc); |
There was a problem hiding this comment.
Please could you keep the options in this trace!
There was a problem hiding this comment.
Oh..., I apologize for failing to rebase 🙇
src/actions/mod.rs
Outdated
| let file_lines = format!(r#"[{{ | ||
| "file": "stdin", | ||
| "range": [{}, {}] | ||
| }}]"#, range.row_start.0, range.row_end.0); |
There was a problem hiding this comment.
Could you use a struct and serialise it, rather than using format! here please? (Ideally, you could use a struct from Rustfmt, but it's ok to create your own here if that is not possible).
There was a problem hiding this comment.
I create Adopter of Rustfmt::FileLines and avoid to serialize FileLines in reformat method directory, daaac8e but if it does not reflect what you pointed out, please tell me 🙏
I think that to create the |
|
I am sorry if I misunderstood something, but it doesn't seem to be able to create FileLines directly because |
|
Ah, you are right, I fixed it - rust-lang/rustfmt@34fa428 I'll make a release of Rustfmt with that change later today. |
|
Thank you so much for responding. |
Yes please! |
|
I have created a PR. |
| ranges.insert("stdin".to_owned(), vec![range]); | ||
| let file_lines = FileLines::from_ranges(ranges); | ||
| config.set().file_lines(file_lines); | ||
| }; |
There was a problem hiding this comment.
Fix up to create FileLines directly instead of using format!.
At present, it destroys the build, until this patch is released 🙏
There was a problem hiding this comment.
I think you'll need to cargo update and commit the Cargo.lock to get the latest rustfmt version
There was a problem hiding this comment.
Updated Cargo.lock, and pushed it ❗️
|
Thank you! |
Implements #333
This PR request Rustfmt to format a range of text.
However, with the return value from Rustfmt as a factor, in response to LanguageClient, the text of the whole file is sent.