mirror of
https://github.com/denoland/deno.git
synced 2024-11-23 15:16:54 -05:00
feat(lsp): debug log file (#21500)
This commit is contained in:
parent
ddfbe71ced
commit
123d9ea047
4 changed files with 97 additions and 4 deletions
|
@ -454,6 +454,10 @@ pub struct WorkspaceSettings {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub internal_debug: bool,
|
pub internal_debug: bool,
|
||||||
|
|
||||||
|
/// Write logs to a file in a project-local directory.
|
||||||
|
#[serde(default)]
|
||||||
|
pub log_file: bool,
|
||||||
|
|
||||||
/// A flag that indicates if linting is enabled for the workspace.
|
/// A flag that indicates if linting is enabled for the workspace.
|
||||||
#[serde(default = "default_to_true")]
|
#[serde(default = "default_to_true")]
|
||||||
pub lint: bool,
|
pub lint: bool,
|
||||||
|
@ -502,6 +506,7 @@ impl Default for WorkspaceSettings {
|
||||||
import_map: None,
|
import_map: None,
|
||||||
code_lens: Default::default(),
|
code_lens: Default::default(),
|
||||||
internal_debug: false,
|
internal_debug: false,
|
||||||
|
log_file: false,
|
||||||
lint: true,
|
lint: true,
|
||||||
document_preload_limit: default_document_preload_limit(),
|
document_preload_limit: default_document_preload_limit(),
|
||||||
suggest: Default::default(),
|
suggest: Default::default(),
|
||||||
|
@ -1071,6 +1076,10 @@ impl Config {
|
||||||
paths
|
paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn log_file(&self) -> bool {
|
||||||
|
self.settings.unscoped.log_file
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_capabilities(
|
pub fn update_capabilities(
|
||||||
&mut self,
|
&mut self,
|
||||||
capabilities: &lsp::ClientCapabilities,
|
capabilities: &lsp::ClientCapabilities,
|
||||||
|
@ -1321,6 +1330,7 @@ mod tests {
|
||||||
test: true,
|
test: true,
|
||||||
},
|
},
|
||||||
internal_debug: false,
|
internal_debug: false,
|
||||||
|
log_file: false,
|
||||||
lint: true,
|
lint: true,
|
||||||
document_preload_limit: 1_000,
|
document_preload_limit: 1_000,
|
||||||
suggest: DenoCompletionSettings {
|
suggest: DenoCompletionSettings {
|
||||||
|
|
|
@ -102,6 +102,7 @@ use crate::factory::CliFactory;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
use crate::graph_util;
|
use crate::graph_util;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
|
use crate::lsp::logging::init_log_file;
|
||||||
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
|
use crate::lsp::tsc::file_text_changes_to_workspace_edit;
|
||||||
use crate::lsp::urls::LspUrlKind;
|
use crate::lsp::urls::LspUrlKind;
|
||||||
use crate::npm::create_cli_npm_resolver_for_lsp;
|
use crate::npm::create_cli_npm_resolver_for_lsp;
|
||||||
|
@ -3242,6 +3243,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ls = self.0.write().await;
|
let mut ls = self.0.write().await;
|
||||||
|
init_log_file(ls.config.log_file());
|
||||||
if let Err(err) = ls.update_tsconfig().await {
|
if let Err(err) = ls.update_tsconfig().await {
|
||||||
ls.client.show_message(MessageType::WARNING, err);
|
ls.client.show_message(MessageType::WARNING, err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,85 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
|
use chrono::Utc;
|
||||||
|
use deno_core::parking_lot::Mutex;
|
||||||
|
use std::fs;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::atomic::AtomicUsize;
|
use std::sync::atomic::AtomicUsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::thread;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
static LSP_DEBUG_FLAG: AtomicBool = AtomicBool::new(false);
|
static LSP_DEBUG_FLAG: AtomicBool = AtomicBool::new(false);
|
||||||
static LSP_LOG_LEVEL: AtomicUsize = AtomicUsize::new(log::Level::Info as usize);
|
static LSP_LOG_LEVEL: AtomicUsize = AtomicUsize::new(log::Level::Info as usize);
|
||||||
static LSP_WARN_LEVEL: AtomicUsize =
|
static LSP_WARN_LEVEL: AtomicUsize =
|
||||||
AtomicUsize::new(log::Level::Warn as usize);
|
AtomicUsize::new(log::Level::Warn as usize);
|
||||||
|
static LOG_FILE: LogFile = LogFile {
|
||||||
|
enabled: AtomicBool::new(true),
|
||||||
|
buffer: Mutex::new(String::new()),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct LogFile {
|
||||||
|
enabled: AtomicBool,
|
||||||
|
buffer: Mutex<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogFile {
|
||||||
|
pub fn write_line(&self, s: &str) {
|
||||||
|
if LOG_FILE.enabled.load(Ordering::Relaxed) {
|
||||||
|
let mut buffer = self.buffer.lock();
|
||||||
|
buffer.push_str(s);
|
||||||
|
buffer.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&self, path: &Path) {
|
||||||
|
let unbuffered = {
|
||||||
|
let mut buffer = self.buffer.lock();
|
||||||
|
if buffer.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// We clone here rather than take so the buffer can retain its capacity.
|
||||||
|
let unbuffered = buffer.clone();
|
||||||
|
buffer.clear();
|
||||||
|
unbuffered
|
||||||
|
};
|
||||||
|
if let Ok(file) = fs::OpenOptions::new().append(true).open(path) {
|
||||||
|
write!(&file, "{}", unbuffered).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_log_file(enabled: bool) {
|
||||||
|
let prepare_path = || {
|
||||||
|
if !enabled {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let cwd = std::env::current_dir().ok()?;
|
||||||
|
let now = SystemTime::now();
|
||||||
|
let now: DateTime<Utc> = now.into();
|
||||||
|
let now = now.to_rfc3339().replace(':', "_");
|
||||||
|
let path = cwd.join(format!(".deno_lsp/log_{}.txt", now));
|
||||||
|
fs::create_dir_all(path.parent()?).ok()?;
|
||||||
|
fs::write(&path, "").ok()?;
|
||||||
|
Some(path)
|
||||||
|
};
|
||||||
|
let Some(path) = prepare_path() else {
|
||||||
|
LOG_FILE.enabled.store(false, Ordering::Relaxed);
|
||||||
|
LOG_FILE.buffer.lock().clear();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
thread::spawn(move || loop {
|
||||||
|
LOG_FILE.commit(&path);
|
||||||
|
thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_line_to_log_file(s: &str) {
|
||||||
|
LOG_FILE.write_line(s);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_lsp_debug_flag(value: bool) {
|
pub fn set_lsp_debug_flag(value: bool) {
|
||||||
LSP_DEBUG_FLAG.store(value, Ordering::SeqCst)
|
LSP_DEBUG_FLAG.store(value, Ordering::SeqCst)
|
||||||
|
@ -53,7 +125,9 @@ macro_rules! lsp_log {
|
||||||
if lsp_log_level == log::Level::Debug {
|
if lsp_log_level == log::Level::Debug {
|
||||||
$crate::lsp::logging::lsp_debug!($($arg)+)
|
$crate::lsp::logging::lsp_debug!($($arg)+)
|
||||||
} else {
|
} else {
|
||||||
log::log!(lsp_log_level, $($arg)+)
|
let s = std::format!($($arg)+);
|
||||||
|
$crate::lsp::logging::write_line_to_log_file(&s);
|
||||||
|
log::log!(lsp_log_level, "{}", s)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +141,9 @@ macro_rules! lsp_warn {
|
||||||
if lsp_log_level == log::Level::Debug {
|
if lsp_log_level == log::Level::Debug {
|
||||||
$crate::lsp::logging::lsp_debug!($($arg)+)
|
$crate::lsp::logging::lsp_debug!($($arg)+)
|
||||||
} else {
|
} else {
|
||||||
log::log!(lsp_log_level, $($arg)+)
|
let s = std::format!($($arg)+);
|
||||||
|
$crate::lsp::logging::write_line_to_log_file(&s);
|
||||||
|
log::log!(lsp_log_level, "{}", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -75,8 +151,12 @@ macro_rules! lsp_warn {
|
||||||
|
|
||||||
macro_rules! lsp_debug {
|
macro_rules! lsp_debug {
|
||||||
($($arg:tt)+) => (
|
($($arg:tt)+) => (
|
||||||
if crate::lsp::logging::lsp_debug_enabled() {
|
{
|
||||||
log::debug!($($arg)+)
|
let s = std::format!($($arg)+);
|
||||||
|
$crate::lsp::logging::write_line_to_log_file(&s);
|
||||||
|
if $crate::lsp::logging::lsp_debug_enabled() {
|
||||||
|
log::debug!("{}", s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,7 @@ pub fn get_repl_workspace_settings() -> WorkspaceSettings {
|
||||||
import_map: None,
|
import_map: None,
|
||||||
code_lens: Default::default(),
|
code_lens: Default::default(),
|
||||||
internal_debug: false,
|
internal_debug: false,
|
||||||
|
log_file: false,
|
||||||
lint: false,
|
lint: false,
|
||||||
document_preload_limit: 0, // don't pre-load any modules as it's expensive and not useful for the repl
|
document_preload_limit: 0, // don't pre-load any modules as it's expensive and not useful for the repl
|
||||||
tls_certificate: None,
|
tls_certificate: None,
|
||||||
|
|
Loading…
Reference in a new issue