Skip to content

Commit dd0e4de

Browse files
committed
Started work on LSP server
1 parent 7889402 commit dd0e4de

File tree

5 files changed

+257
-1
lines changed

5 files changed

+257
-1
lines changed

Cargo.lock

Lines changed: 138 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[workspace]
2-
members = [ "harper-core", "harper-serve", "harper-wasm"]
2+
members = [ "harper-core", "harper-ls", "harper-serve", "harper-wasm"]
33
resolver = "2"

harper-ls/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "harper-ls"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
anyhow = "1.0.79"
10+
ctrlc = "3.4.2"
11+
lsp-server = "0.7.6"
12+
lsp-types = "0.95.0"
13+
serde = "1.0.195"
14+
serde_json = "1.0.111"
15+
tracing = "0.1.40"
16+
tracing-subscriber = "0.3.18"

harper-ls/src/main.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use lsp_types::{
2+
request::GotoDefinition, GotoDefinitionResponse, InitializeParams, ServerCapabilities,
3+
};
4+
use lsp_types::{Location, OneOf, Position};
5+
6+
use lsp_server::{Connection, ExtractError, Message, Request, RequestId, Response};
7+
use tracing::{info, Level};
8+
9+
fn main() -> anyhow::Result<()> {
10+
let subscriber = tracing_subscriber::FmtSubscriber::builder()
11+
.with_max_level(Level::DEBUG)
12+
.finish();
13+
14+
tracing::subscriber::set_global_default(subscriber)?;
15+
16+
let (connection, io_threads) = Connection::listen("127.0.0.1:4000")?;
17+
18+
let server_capabilities = serde_json::to_value(ServerCapabilities {
19+
definition_provider: Some(OneOf::Left(true)),
20+
..Default::default()
21+
})
22+
.unwrap();
23+
let initialization_params = match connection.initialize(server_capabilities) {
24+
Ok(it) => it,
25+
Err(e) => {
26+
if e.channel_is_disconnected() {
27+
io_threads.join()?;
28+
}
29+
return Err(e.into());
30+
}
31+
};
32+
main_loop(connection, initialization_params)?;
33+
io_threads.join()?;
34+
35+
info!("Shutting down server.c");
36+
Ok(())
37+
}
38+
39+
fn main_loop(connection: Connection, params: serde_json::Value) -> anyhow::Result<()> {
40+
let _params: InitializeParams = serde_json::from_value(params).unwrap();
41+
info!("Starting example main loop");
42+
for msg in &connection.receiver {
43+
info!("Got msg: {msg:?}");
44+
match msg {
45+
Message::Request(req) => {
46+
if connection.handle_shutdown(&req)? {
47+
return Ok(());
48+
}
49+
info!("Got request: {req:?}");
50+
match cast::<GotoDefinition>(req) {
51+
Ok((id, params)) => {
52+
info!("Got gotoDefinition request #{id}: {params:?}");
53+
let result = Some(GotoDefinitionResponse::Array(vec![Location {
54+
uri: params.text_document_position_params.text_document.uri,
55+
range: lsp_types::Range {
56+
start: Position {
57+
line: 0,
58+
character: 0,
59+
},
60+
end: Position {
61+
line: 0,
62+
character: 0,
63+
},
64+
},
65+
}]));
66+
let result = serde_json::to_value(&result).unwrap();
67+
let resp = Response {
68+
id,
69+
result: Some(result),
70+
error: None,
71+
};
72+
connection.sender.send(Message::Response(resp))?;
73+
continue;
74+
}
75+
Err(err @ ExtractError::JsonError { .. }) => panic!("{err:?}"),
76+
Err(ExtractError::MethodMismatch(req)) => req,
77+
};
78+
}
79+
Message::Response(resp) => {
80+
info!("Got response: {resp:?}");
81+
}
82+
Message::Notification(not) => {
83+
info!("Got notification: {not:?}");
84+
}
85+
}
86+
}
87+
88+
Ok(())
89+
}
90+
91+
fn cast<R>(req: Request) -> Result<(RequestId, R::Params), ExtractError<Request>>
92+
where
93+
R: lsp_types::request::Request,
94+
R::Params: serde::de::DeserializeOwned,
95+
{
96+
req.extract(R::METHOD)
97+
}

nvim.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
vim.lsp.start({
2+
name = "example",
3+
cmd = vim.lsp.rpc.connect("127.0.0.1", 4000),
4+
root_dir = "."
5+
})

0 commit comments

Comments
 (0)