Skip to content

Commit

Permalink
feat: enable lsp formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
f01dab1e committed Nov 6, 2023
1 parent ff96ba4 commit dc4a446
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tooling/lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ codespan-lsp.workspace = true
codespan-reporting.workspace = true
lsp-types.workspace = true
nargo.workspace = true
nargo_fmt.workspace = true
nargo_toml.workspace = true
noirc_driver.workspace = true
noirc_errors.workspace = true
Expand Down
13 changes: 11 additions & 2 deletions tooling/lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies, unused_extern_crates))]

use std::{
collections::HashMap,
future::Future,
ops::{self, ControlFlow},
path::{Path, PathBuf},
Expand All @@ -26,7 +27,8 @@ use notifications::{
on_did_open_text_document, on_did_save_text_document, on_exit, on_initialized,
};
use requests::{
on_code_lens_request, on_initialize, on_shutdown, on_test_run_request, on_tests_request,
on_code_lens_request, on_formatting, on_initialize, on_shutdown, on_test_run_request,
on_tests_request,
};
use serde_json::Value as JsonValue;
use tower::Service;
Expand All @@ -44,11 +46,17 @@ pub struct LspState {
root_path: Option<PathBuf>,
client: ClientSocket,
solver: WrapperSolver,
input_files: HashMap<String, String>,
}

impl LspState {
fn new(client: &ClientSocket, solver: impl BlackBoxFunctionSolver + 'static) -> Self {
Self { client: client.clone(), root_path: None, solver: WrapperSolver(Box::new(solver)) }
Self {
client: client.clone(),
root_path: None,
solver: WrapperSolver(Box::new(solver)),
input_files: HashMap::new(),
}
}
}

Expand All @@ -62,6 +70,7 @@ impl NargoLspService {
let mut router = Router::new(state);
router
.request::<request::Initialize, _>(on_initialize)
.request::<request::Formatting, _>(on_formatting)
.request::<request::Shutdown, _>(on_shutdown)
.request::<request::CodeLens, _>(on_code_lens_request)
.request::<request::NargoTests, _>(on_tests_request)
Expand Down
16 changes: 10 additions & 6 deletions tooling/lsp/src/notifications/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,27 @@ pub(super) fn on_did_change_configuration(
}

pub(super) fn on_did_open_text_document(
_state: &mut LspState,
_params: DidOpenTextDocumentParams,
state: &mut LspState,
params: DidOpenTextDocumentParams,
) -> ControlFlow<Result<(), async_lsp::Error>> {
state.input_files.insert(params.text_document.uri.to_string(), params.text_document.text);
ControlFlow::Continue(())
}

pub(super) fn on_did_change_text_document(
_state: &mut LspState,
_params: DidChangeTextDocumentParams,
state: &mut LspState,
params: DidChangeTextDocumentParams,
) -> ControlFlow<Result<(), async_lsp::Error>> {
let text = params.content_changes.into_iter().next().unwrap().text;
state.input_files.insert(params.text_document.uri.to_string(), text);
ControlFlow::Continue(())
}

pub(super) fn on_did_close_text_document(
_state: &mut LspState,
_params: DidCloseTextDocumentParams,
state: &mut LspState,
params: DidCloseTextDocumentParams,
) -> ControlFlow<Result<(), async_lsp::Error>> {
state.input_files.remove(&params.text_document.uri.to_string());
ControlFlow::Continue(())
}

Expand Down
46 changes: 42 additions & 4 deletions tooling/lsp/src/requests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::future::Future;

use crate::types::{CodeLensOptions, InitializeParams, TextDocumentSyncOptions};
use crate::types::{CodeLensOptions, InitializeParams};
use async_lsp::ResponseError;
use lsp_types::{Position, TextDocumentSyncCapability, TextDocumentSyncKind};
use nargo_fmt::Config;

use crate::{
types::{InitializeResult, NargoCapability, NargoTestsOptions, ServerCapabilities},
Expand Down Expand Up @@ -33,8 +35,7 @@ pub(crate) fn on_initialize(
state.root_path = params.root_uri.and_then(|root_uri| root_uri.to_file_path().ok());

async {
let text_document_sync =
TextDocumentSyncOptions { save: Some(true.into()), ..Default::default() };
let text_document_sync = TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL);

let code_lens = CodeLensOptions { resolve_provider: Some(false) };

Expand All @@ -48,15 +49,52 @@ pub(crate) fn on_initialize(

Ok(InitializeResult {
capabilities: ServerCapabilities {
text_document_sync: Some(text_document_sync.into()),
text_document_sync: Some(text_document_sync),
code_lens_provider: Some(code_lens),
document_formatting_provider: true,
nargo: Some(nargo),
},
server_info: None,
})
}
}

pub(crate) fn on_formatting(
state: &mut LspState,
params: lsp_types::DocumentFormattingParams,
) -> impl Future<Output = Result<Option<Vec<lsp_types::TextEdit>>, ResponseError>> {
std::future::ready(on_formatting_inner(state, params))
}

fn on_formatting_inner(
state: &LspState,
params: lsp_types::DocumentFormattingParams,
) -> Result<Option<Vec<lsp_types::TextEdit>>, ResponseError> {
let path = params.text_document.uri.to_string();

if let Some(source) = state.input_files.get(&path) {
let (module, errors) = noirc_frontend::parse_program(source);
if !errors.is_empty() {
return Ok(None);
}

let new_text = nargo_fmt::format(source, module, &Config::default());

let start_position = Position { line: 0, character: 0 };
let end_position = Position {
line: source.lines().count() as u32,
character: source.chars().count() as u32,
};

Ok(Some(vec![lsp_types::TextEdit {
range: lsp_types::Range::new(start_position, end_position),
new_text,
}]))
} else {
Ok(None)
}
}

pub(crate) fn on_shutdown(
_state: &mut LspState,
_params: (),
Expand Down
7 changes: 5 additions & 2 deletions tooling/lsp/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub(crate) use lsp_types::{
DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams,
DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializeParams, InitializedParams,
LogMessageParams, MessageType, Position, PublishDiagnosticsParams, Range, ServerInfo,
TextDocumentSyncCapability, TextDocumentSyncOptions, Url,
TextDocumentSyncCapability, Url,
};

pub(crate) mod request {
Expand All @@ -19,7 +19,7 @@ pub(crate) mod request {
};

// Re-providing lsp_types that we don't need to override
pub(crate) use lsp_types::request::{CodeLensRequest as CodeLens, Shutdown};
pub(crate) use lsp_types::request::{CodeLensRequest as CodeLens, Formatting, Shutdown};

#[derive(Debug)]
pub(crate) struct Initialize;
Expand Down Expand Up @@ -99,6 +99,9 @@ pub(crate) struct ServerCapabilities {
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) code_lens_provider: Option<CodeLensOptions>,

/// The server provides document formatting.
pub(crate) document_formatting_provider: bool,

/// The server handles and provides custom nargo messages.
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) nargo: Option<NargoCapability>,
Expand Down

0 comments on commit dc4a446

Please sign in to comment.