Skip to content

Commit

Permalink
feat: lsp range fmt. Support range format in lsp
Browse files Browse the repository at this point in the history
  • Loading branch information
He1pa committed Aug 24, 2023
1 parent 59539d8 commit b4ac14b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 17 deletions.
1 change: 1 addition & 0 deletions kclvm/tools/src/LSP/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
}),
),
document_formatting_provider: Some(OneOf::Left(true)),
document_range_formatting_provider: Some(OneOf::Left(true)),
..Default::default()
}
}
10 changes: 7 additions & 3 deletions kclvm/tools/src/LSP/src/formatting.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use kclvm_tools::format::{format_source, FormatOptions};
use lsp_types::{Position, Range, TextEdit};

pub(crate) fn format_single_file(
pub(crate) fn format(
file: String,
src: String,
range: Option<Range>,
) -> anyhow::Result<Option<Vec<TextEdit>>> {
let (source, is_formatted) = format_source(
&file,
Expand All @@ -13,10 +14,13 @@ pub(crate) fn format_single_file(
..Default::default()
},
)
.map_err(|err| anyhow::anyhow!("Formmatting failed: {}", err))?;
.map_err(|err| anyhow::anyhow!("Formatting failed: {}", err))?;
if is_formatted {
Ok(Some(vec![TextEdit {
range: Range::new(Position::new(0, 0), Position::new(u32::MAX, u32::MAX)),
range: range.unwrap_or(Range::new(
Position::new(0, 0),
Position::new(u32::MAX, u32::MAX),
)),
new_text: source,
}]))
} else {
Expand Down
35 changes: 29 additions & 6 deletions kclvm/tools/src/LSP/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use crossbeam_channel::Sender;

use lsp_types::{CodeAction, CodeActionKind, CodeActionOrCommand, Position, Range, TextEdit};
use ra_ap_vfs::VfsPath;
use std::{collections::HashMap, time::Instant};
use std::{collections::HashMap, ops::Index, time::Instant};

use crate::{
completion::completion,
db::AnalysisDatabase,
dispatcher::RequestDispatcher,
document_symbol::document_symbol,
formatting::format_single_file,
formatting::format,
from_lsp::{self, file_path_from_url, kcl_pos},
goto_def::goto_definition,
hover, quick_fix,
Expand Down Expand Up @@ -48,6 +48,7 @@ impl LanguageServerState {
.on::<lsp_types::request::DocumentSymbolRequest>(handle_document_symbol)?
.on::<lsp_types::request::CodeActionRequest>(handle_code_action)?
.on::<lsp_types::request::Formatting>(handle_formatting)?
.on::<lsp_types::request::RangeFormatting>(handle_range_formatting)?
.finish();

Ok(())
Expand All @@ -69,18 +70,40 @@ impl LanguageServerSnapshot {
}

pub(crate) fn handle_formatting(
_snap: LanguageServerSnapshot,
_snapshot: LanguageServerSnapshot,
params: lsp_types::DocumentFormattingParams,
sender: Sender<Task>,
_sender: Sender<Task>,
) -> anyhow::Result<Option<Vec<TextEdit>>> {
let file = file_path_from_url(&params.text_document.uri)?;
let src = std::fs::read_to_string(file.clone())?;
format_single_file(file, src)
format(file, src, None)
}

pub(crate) fn handle_range_formatting(
snapshot: LanguageServerSnapshot,
params: lsp_types::DocumentRangeFormattingParams,
_sender: Sender<Task>,
) -> anyhow::Result<Option<Vec<TextEdit>>> {
let file = file_path_from_url(&params.text_document.uri)?;
let path = from_lsp::abs_path(&params.text_document.uri)?;
let vfs = &*snapshot.vfs.read();

let file_id = vfs
.file_id(&path.clone().into())
.ok_or(anyhow::anyhow!("Already checked that the file_id exists!"))?;

let text = String::from_utf8(vfs.file_contents(file_id).to_vec())?;
let range = from_lsp::text_range(&text, params.range);
if let Some(src) = text.get(range) {
format(file, src.to_owned(), Some(params.range))
} else {
Ok(None)
}
}

/// Called when a `GotoDefinition` request was received.
pub(crate) fn handle_code_action(
_snap: LanguageServerSnapshot,
_snapshot: LanguageServerSnapshot,
params: lsp_types::CodeActionParams,
_sender: Sender<Task>,
) -> anyhow::Result<Option<lsp_types::CodeActionResponse>> {
Expand Down
12 changes: 12 additions & 0 deletions kclvm/tools/src/LSP/src/test_data/format/format_range.k
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

a=1


b= 2


c =3



d = 4
39 changes: 31 additions & 8 deletions kclvm/tools/src/LSP/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::env;
use std::ops::Index;
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;
Expand Down Expand Up @@ -29,11 +30,13 @@ use lsp_types::Url;
use lsp_types::WorkspaceEdit;
use lsp_types::{Position, Range, TextDocumentContentChangeEvent};
use parking_lot::RwLock;
use ra_ap_vfs::AbsPathBuf;
use ra_ap_vfs::Vfs;

use crate::completion::KCLCompletionItem;
use crate::document_symbol::document_symbol;
use crate::formatting::format_single_file;
use crate::from_lsp::file_path_from_url;
use crate::formatting::format;
use crate::from_lsp::{abs_path, file_path_from_url, text_range};
use crate::hover::hover;
use crate::quick_fix::quick_fix;
use crate::to_lsp::kcl_diag_to_lsp_diags;
Expand Down Expand Up @@ -149,7 +152,7 @@ fn diagnostics_test() {
Param {
file: file.to_string(),
},
None,
Some(Arc::new(RwLock::new(Default::default()))),
)
.unwrap();

Expand Down Expand Up @@ -237,7 +240,7 @@ fn quick_fix_test() {
Param {
file: file.to_string(),
},
None,
Some(Arc::new(RwLock::new(Default::default()))),
)
.unwrap();

Expand Down Expand Up @@ -1226,7 +1229,7 @@ fn goto_import_external_file_test() {
Param {
file: path.to_string(),
},
None,
Some(Arc::new(RwLock::new(Default::default()))),
)
.unwrap();

Expand All @@ -1243,7 +1246,7 @@ fn goto_import_external_file_test() {
}

#[test]
fn formmat_signle_file_test() {
fn format_signle_file_test() {
const FILE_INPUT_SUFFIX: &str = ".input";
const FILE_OUTPUT_SUFFIX: &str = ".golden";
const TEST_CASES: &[&str; 17] = &[
Expand Down Expand Up @@ -1282,7 +1285,7 @@ fn formmat_signle_file_test() {
.unwrap()
.to_string();
let test_src = std::fs::read_to_string(&test_file).unwrap();
let got = format_single_file(test_file, test_src).unwrap().unwrap();
let got = format(test_file, test_src, None).unwrap().unwrap();
let data_output = std::fs::read_to_string(
&test_dir
.join(format!("{}{}", case, FILE_OUTPUT_SUFFIX))
Expand Down Expand Up @@ -1310,6 +1313,26 @@ fn formmat_signle_file_test() {
.unwrap()
.to_string();
let test_src = std::fs::read_to_string(&test_file).unwrap();
let got = format_single_file(test_file, test_src).unwrap();
let got = format(test_file, test_src, None).unwrap();
assert_eq!(got, None)
}

#[test]
fn format_range_test() {
let (file, program, prog_scope, _) = compile_test_file("src/test_data/format/format_range.k");
let lsp_range = Range::new(Position::new(0, 0), Position::new(11, 0));
let text = std::fs::read_to_string(file.clone()).unwrap();

let range = text_range(&text, lsp_range);
let src = text.index(range);

let got = format(file, src.to_owned(), Some(lsp_range))
.unwrap()
.unwrap();

let expected = vec![TextEdit {
range: lsp_range,
new_text: "a = 1\nb = 2\nc = 3\n".to_string(),
}];
assert_eq!(got, expected)
}

0 comments on commit b4ac14b

Please sign in to comment.