Skip to content

Commit 6b47d04

Browse files
committed
feat: document store
1 parent 1275fd0 commit 6b47d04

File tree

14 files changed

+460
-80
lines changed

14 files changed

+460
-80
lines changed

Cargo.lock

Lines changed: 3 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ async-lsp = { version = "0.2", default-features = false, features = [
154154
"client-monitor",
155155
"stdio",
156156
"tokio",
157+
"tracing",
157158
] }
158159
# See <https://github.com/gluon-lang/lsp-types/issues/284>
159160
lsp-types = "0.95.0"
@@ -176,6 +177,7 @@ inturn = "0.1.0"
176177
libc = "0.2"
177178
md-5 = "0.10"
178179
memchr = "2.7"
180+
normalize-path = "0.2.1"
179181
once_map = { version = "0.4.20", default-features = false, features = ["std"] }
180182
paste = "1.0"
181183
petgraph = "0.8"

crates/interface/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ hex.workspace = true
3737
itertools.workspace = true
3838
itoa.workspace = true
3939
inturn.workspace = true
40-
normalize-path = "0.2.1"
40+
normalize-path.workspace = true
4141
rayon.workspace = true
4242
scoped-tls.workspace = true
4343
tracing.workspace = true

crates/lsp/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ solar-interface.workspace = true
2929

3030
async-lsp.workspace = true
3131
lsp-types.workspace = true
32+
normalize-path.workspace = true
3233
tower.workspace = true
34+
tracing.workspace = true
3335

3436
# This is needed because Windows does not support truly asynchronous pipes.
3537
[target.'cfg(not(unix))'.dependencies]

crates/lsp/src/global_state.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use std::{ops::ControlFlow, sync::Arc};
2+
3+
use async_lsp::{ClientSocket, ResponseError};
4+
use lsp_types::{
5+
InitializeParams, InitializeResult, InitializedParams, LogMessageParams, MessageType,
6+
ServerInfo, notification as notif,
7+
};
8+
use solar_config::version::SHORT_VERSION;
9+
use solar_interface::data_structures::sync::RwLock;
10+
11+
use crate::{NotifyResult, vfs::Vfs};
12+
13+
pub(crate) struct GlobalState {
14+
client: ClientSocket,
15+
pub(crate) vfs: Arc<RwLock<Vfs>>,
16+
}
17+
18+
impl GlobalState {
19+
pub(crate) fn new(client: ClientSocket) -> Self {
20+
Self { client, vfs: Arc::new(Default::default()) }
21+
}
22+
23+
pub(crate) fn on_initialize(
24+
&mut self,
25+
_: InitializeParams,
26+
) -> impl Future<Output = Result<InitializeResult, ResponseError>> + use<> {
27+
std::future::ready(Ok(InitializeResult {
28+
server_info: Some(ServerInfo {
29+
name: "solar".into(),
30+
version: Some(SHORT_VERSION.into()),
31+
}),
32+
..Default::default()
33+
}))
34+
}
35+
36+
pub(crate) fn on_initialized(&mut self, _: InitializedParams) -> NotifyResult {
37+
self.info_msg("solar initialized".into());
38+
ControlFlow::Continue(())
39+
}
40+
}
41+
42+
impl GlobalState {
43+
fn warn_msg(&self, message: String) {
44+
let _ = self
45+
.client
46+
.notify::<notif::LogMessage>(LogMessageParams { typ: MessageType::WARNING, message });
47+
}
48+
49+
fn error_msg(&self, message: String) {
50+
let _ = self
51+
.client
52+
.notify::<notif::LogMessage>(LogMessageParams { typ: MessageType::ERROR, message });
53+
}
54+
55+
fn info_msg(&self, message: String) {
56+
let _ = self
57+
.client
58+
.notify::<notif::LogMessage>(LogMessageParams { typ: MessageType::INFO, message });
59+
}
60+
}

crates/lsp/src/handlers/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod notifs;
2+
mod reqs;
3+
4+
pub(crate) use notifs::*;
5+
pub(crate) use reqs::*;

crates/lsp/src/handlers/notifs.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::ops::ControlFlow;
2+
3+
use lsp_types::{
4+
DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams,
5+
};
6+
use tracing::error;
7+
8+
use crate::{NotifyResult, global_state::GlobalState, proto};
9+
10+
pub(crate) fn did_open_text_document(
11+
state: &mut GlobalState,
12+
params: DidOpenTextDocumentParams,
13+
) -> NotifyResult {
14+
if let Some(path) = proto::vfs_path(&params.text_document.uri) {
15+
let already_exists = state.vfs.read().exists(&path);
16+
if already_exists {
17+
error!(?path, "duplicate DidOpenTextDocument");
18+
}
19+
20+
let contents = params.text_document.text.into_bytes();
21+
state.vfs.write().set_file_contents(path, Some(contents));
22+
}
23+
24+
ControlFlow::Continue(())
25+
}
26+
27+
pub(crate) fn did_change_text_document(
28+
state: &mut GlobalState,
29+
params: DidChangeTextDocumentParams,
30+
) -> NotifyResult {
31+
// todo
32+
ControlFlow::Continue(())
33+
}
34+
35+
pub(crate) fn did_close_text_document(
36+
state: &mut GlobalState,
37+
params: DidCloseTextDocumentParams,
38+
) -> NotifyResult {
39+
if let Some(path) = proto::vfs_path(&params.text_document.uri) {
40+
if !state.vfs.read().exists(&path) {
41+
error!(?path, "orphan DidCloseTextDocument");
42+
}
43+
44+
state.vfs.write().set_file_contents(path, None);
45+
}
46+
47+
ControlFlow::Continue(())
48+
}

crates/lsp/src/handlers/reqs.rs

Whitespace-only changes.

crates/lsp/src/lib.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,43 @@
55
)]
66
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
77

8+
use std::ops::ControlFlow;
9+
810
use async_lsp::{
9-
client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer,
10-
server::LifecycleLayer,
11+
ClientSocket, client_monitor::ClientProcessMonitorLayer, concurrency::ConcurrencyLayer,
12+
router::Router, server::LifecycleLayer, tracing::TracingLayer,
1113
};
14+
use lsp_types::{notification as notif, request as req};
1215
use tower::ServiceBuilder;
1316

14-
use crate::server::Server;
17+
use crate::global_state::GlobalState;
18+
19+
mod global_state;
20+
mod handlers;
21+
mod proto;
22+
mod vfs;
23+
24+
pub(crate) type NotifyResult = ControlFlow<async_lsp::Result<()>>;
25+
26+
fn new_router(client: ClientSocket) -> Router<GlobalState> {
27+
let this = GlobalState::new(client);
28+
let mut router = Router::new(this);
1529

16-
mod server;
30+
// Lifecycle
31+
router
32+
.request::<req::Initialize, _>(GlobalState::on_initialize)
33+
.notification::<notif::Initialized>(GlobalState::on_initialized)
34+
.request::<req::Shutdown, _>(|_, _| std::future::ready(Ok(())))
35+
.notification::<notif::Exit>(|_, _| ControlFlow::Break(Ok(())));
36+
37+
// Notifications
38+
router
39+
.notification::<notif::DidOpenTextDocument>(handlers::did_open_text_document)
40+
.notification::<notif::DidCloseTextDocument>(handlers::did_close_text_document)
41+
.notification::<notif::DidChangeTextDocument>(handlers::did_change_text_document);
42+
43+
router
44+
}
1745

1846
/// Start the LSP server over stdin/stdout.
1947
///
@@ -35,11 +63,12 @@ pub async fn run_server_stdio() -> solar_interface::Result<()> {
3563

3664
let (eloop, _) = async_lsp::MainLoop::new_server(|client| {
3765
ServiceBuilder::new()
66+
.layer(TracingLayer::default())
3867
.layer(LifecycleLayer::default())
3968
// TODO: infer concurrency
4069
.layer(ConcurrencyLayer::new(2.try_into().unwrap()))
4170
.layer(ClientProcessMonitorLayer::new(client.clone()))
42-
.service(Server::new_router(client))
71+
.service(new_router(client))
4372
});
4473

4574
eloop.run_buffered(stdin, stdout).await.unwrap();

crates/lsp/src/proto.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use crate::vfs::{self, VfsPath};
2+
3+
pub(crate) fn vfs_path(url: &lsp_types::Url) -> Option<vfs::VfsPath> {
4+
url.to_file_path().map(VfsPath::from).ok()
5+
}

0 commit comments

Comments
 (0)