From ef1139be9290846ccd197c4bbeeddca48ffcff50 Mon Sep 17 00:00:00 2001 From: Dominik Nakamura Date: Tue, 5 Dec 2023 13:31:05 +0900 Subject: [PATCH] refactor(lsp): move logging logic into its own module --- crates/stef-lsp/src/logging.rs | 104 +++++++++++++++++++++++++++++++++ crates/stef-lsp/src/main.rs | 78 ++----------------------- 2 files changed, 109 insertions(+), 73 deletions(-) create mode 100644 crates/stef-lsp/src/logging.rs diff --git a/crates/stef-lsp/src/logging.rs b/crates/stef-lsp/src/logging.rs new file mode 100644 index 0000000..dc1778c --- /dev/null +++ b/crates/stef-lsp/src/logging.rs @@ -0,0 +1,104 @@ +use std::io::Write; + +use anyhow::{Context, Result}; +use directories::ProjectDirs; +use time::{format_description::FormatItem, macros::format_description, UtcOffset}; +use tower_lsp::{lsp_types::MessageType, Client}; +use tracing::Level; +use tracing_appender::non_blocking::NonBlocking; +use tracing_subscriber::{ + filter::Targets, + fmt::{time::OffsetTime, MakeWriter}, + prelude::*, +}; + +pub fn prepare() -> Result<(Options, Guard)> { + let timer = OffsetTime::new( + UtcOffset::current_local_offset().context("failed retrieving local UTC offset")?, + format_description!("[hour]:[minute]:[second]"), + ); + + let dirs = ProjectDirs::from("rocks", "dnaka91", env!("CARGO_PKG_NAME")) + .context("failed locating project directories")?; + + let file_appender = tracing_appender::rolling::daily(dirs.cache_dir(), "log"); + let (file_appender, guard) = tracing_appender::non_blocking(file_appender); + + Ok(( + Options { + timer, + file_appender, + }, + Guard(guard), + )) +} + +pub fn init( + Options { + timer, + file_appender, + }: Options, + client: Client, +) { + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_ansi(false) + .with_timer(timer.clone()) + .with_writer(ClientLogWriter::new(client)), + ) + .with( + tracing_subscriber::fmt::layer() + .with_timer(timer) + .with_writer(file_appender), + ) + .with(Targets::new().with_default(Level::WARN).with_targets([ + (env!("CARGO_CRATE_NAME"), Level::TRACE), + ("stef_compiler", Level::TRACE), + ("stef_parser", Level::TRACE), + ("tower_lsp", Level::DEBUG), + ])) + .init(); +} + +pub struct Options { + timer: OffsetTime<&'static [FormatItem<'static>]>, + file_appender: NonBlocking, +} + +pub struct Guard(tracing_appender::non_blocking::WorkerGuard); + +struct ClientLogWriter { + client: Client, +} + +impl ClientLogWriter { + fn new(client: Client) -> Self { + Self { client } + } +} + +impl Write for ClientLogWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + let client = self.client.clone(); + let message = String::from_utf8_lossy(buf).trim().to_owned(); + + tokio::spawn(async move { client.log_message(MessageType::LOG, message).await }); + + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +impl MakeWriter<'_> for ClientLogWriter { + type Writer = Self; + + fn make_writer(&self) -> Self::Writer { + Self { + client: self.client.clone(), + } + } +} diff --git a/crates/stef-lsp/src/main.rs b/crates/stef-lsp/src/main.rs index cacd378..f94aece 100644 --- a/crates/stef-lsp/src/main.rs +++ b/crates/stef-lsp/src/main.rs @@ -4,10 +4,8 @@ use std::collections::HashMap; use anyhow::{ensure, Context, Result}; -use directories::ProjectDirs; use ouroboros::self_referencing; use stef_parser::Schema; -use time::{macros::format_description, UtcOffset}; use tokio::sync::{Mutex, RwLock}; use tower_lsp::{ async_trait, @@ -15,7 +13,7 @@ use tower_lsp::{ lsp_types::{ ConfigurationItem, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, InitializeParams, InitializeResult, - InitializedParams, MessageType, Registration, SemanticTokenModifier, SemanticTokenType, + InitializedParams, Registration, SemanticTokenModifier, SemanticTokenType, SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions, SemanticTokensParams, SemanticTokensResult, SemanticTokensServerCapabilities, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind, Url, @@ -23,18 +21,14 @@ use tower_lsp::{ }, Client, LanguageServer, LspService, Server, }; -use tracing::{debug, error, Level}; -use tracing_subscriber::{ - filter::Targets, - fmt::{time::OffsetTime, MakeWriter}, - prelude::*, -}; +use tracing::{debug, error}; use self::cli::Cli; mod cli; mod compile; mod config; +mod logging; mod utf16; #[derive(Debug)] @@ -250,37 +244,10 @@ impl LanguageServer for Backend { fn main() -> Result<()> { let cli = Cli::parse(); - let timer = OffsetTime::new( - UtcOffset::current_local_offset().context("failed retrieving local UTC offset")?, - format_description!("[hour]:[minute]:[second]"), - ); - - let dirs = ProjectDirs::from("rocks", "dnaka91", env!("CARGO_PKG_NAME")) - .context("failed locating project directories")?; - - let file_appender = tracing_appender::rolling::daily(dirs.cache_dir(), "log"); - let (file_appender, _guard) = tracing_appender::non_blocking(file_appender); + let (log_options, _guard) = logging::prepare()?; let (service, socket) = LspService::new(|client| { - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .with_ansi(false) - .with_timer(timer.clone()) - .with_writer(ClientLogWriter::new(client.clone())), - ) - .with( - tracing_subscriber::fmt::layer() - .with_timer(timer) - .with_writer(file_appender), - ) - .with(Targets::new().with_default(Level::WARN).with_targets([ - (env!("CARGO_CRATE_NAME"), Level::TRACE), - ("stef_compiler", Level::TRACE), - ("stef_parser", Level::TRACE), - ("tower_lsp", Level::DEBUG), - ])) - .init(); + logging::init(log_options, client.clone()); Backend { client, @@ -313,38 +280,3 @@ fn main() -> Result<()> { anyhow::Ok(()) }) } - -struct ClientLogWriter { - client: Client, -} - -impl ClientLogWriter { - fn new(client: Client) -> Self { - Self { client } - } -} - -impl std::io::Write for ClientLogWriter { - fn write(&mut self, buf: &[u8]) -> std::io::Result { - let client = self.client.clone(); - let message = String::from_utf8_lossy(buf).trim().to_owned(); - - tokio::spawn(async move { client.log_message(MessageType::LOG, message).await }); - - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} - -impl MakeWriter<'_> for ClientLogWriter { - type Writer = Self; - - fn make_writer(&self) -> Self::Writer { - Self { - client: self.client.clone(), - } - } -}