editor: add Node.js debugger

pull/574/head
Dmitry Sharshakov 3 years ago
parent 0e51e5fbaf
commit d943a51e3e
No known key found for this signature in database
GPG Key ID: 471FD32E15FD8473

@ -5,6 +5,7 @@ use crate::{
Rope, RopeSlice, Tendril, Rope, RopeSlice, Tendril,
}; };
use helix_dap::DebuggerQuirks;
pub use helix_syntax::get_language; pub use helix_syntax::get_language;
use arc_swap::ArcSwap; use arc_swap::ArcSwap;
@ -107,11 +108,14 @@ pub struct DebugTemplate {
pub struct DebugAdapterConfig { pub struct DebugAdapterConfig {
pub name: String, pub name: String,
pub transport: String, pub transport: String,
#[serde(default)]
pub command: String, pub command: String,
#[serde(default)] #[serde(default)]
pub args: Vec<String>, pub args: Vec<String>,
pub port_arg: Option<String>, pub port_arg: Option<String>,
pub templates: Vec<DebugTemplate>, pub templates: Vec<DebugTemplate>,
#[serde(default)]
pub quirks: DebuggerQuirks,
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

@ -5,6 +5,7 @@ use crate::{
}; };
use anyhow::anyhow; use anyhow::anyhow;
pub use log::{error, info}; pub use log::{error, info};
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::HashMap, collections::HashMap,
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
@ -20,6 +21,13 @@ use tokio::{
time, time,
}; };
// Different workarounds for adapters' differences
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
pub struct DebuggerQuirks {
#[serde(default)]
pub absolute_paths: bool,
}
#[derive(Debug)] #[derive(Debug)]
pub struct Client { pub struct Client {
id: usize, id: usize,
@ -34,6 +42,7 @@ pub struct Client {
/// Currently active frame for the current thread. /// Currently active frame for the current thread.
pub active_frame: Option<usize>, pub active_frame: Option<usize>,
pub breakpoints: Vec<Breakpoint>, pub breakpoints: Vec<Breakpoint>,
pub quirks: DebuggerQuirks,
} }
impl Client { impl Client {
@ -45,6 +54,9 @@ impl Client {
port_arg: Option<String>, port_arg: Option<String>,
id: usize, id: usize,
) -> Result<(Self, UnboundedReceiver<Payload>)> { ) -> Result<(Self, UnboundedReceiver<Payload>)> {
if command == "" {
return Result::Err(Error::Other(anyhow!("Command not provided")));
}
if transport == "tcp" && port_arg.is_some() { if transport == "tcp" && port_arg.is_some() {
Self::tcp_process( Self::tcp_process(
&command, &command,
@ -82,6 +94,7 @@ impl Client {
thread_id: None, thread_id: None,
active_frame: None, active_frame: None,
breakpoints: vec![], breakpoints: vec![],
quirks: DebuggerQuirks::default(),
}; };
tokio::spawn(Self::recv(server_rx, client_rx)); tokio::spawn(Self::recv(server_rx, client_rx));

@ -2,7 +2,7 @@ mod client;
mod transport; mod transport;
mod types; mod types;
pub use client::Client; pub use client::{Client, DebuggerQuirks};
pub use events::Event; pub use events::Event;
pub use transport::{Payload, Response, Transport}; pub use transport::{Payload, Response, Transport};
pub use types::*; pub use types::*;

@ -5,7 +5,7 @@ use crate::{
job::Callback, job::Callback,
ui::{FilePicker, Prompt, PromptEvent}, ui::{FilePicker, Prompt, PromptEvent},
}; };
use helix_core::Selection; use helix_core::{syntax::DebugConfigCompletion, Selection};
use helix_dap::{self as dap, Client}; use helix_dap::{self as dap, Client};
use helix_lsp::block_on; use helix_lsp::block_on;
@ -206,6 +206,8 @@ pub fn dap_start_impl(
return; return;
} }
debugger.quirks = config.quirks;
let start_config = match name { let start_config = match name {
Some(name) => config.templates.iter().find(|t| t.name == name), Some(name) => config.templates.iter().find(|t| t.name == name),
None => config.templates.get(0), None => config.templates.get(0),
@ -225,8 +227,18 @@ pub fn dap_start_impl(
for (k, t) in template { for (k, t) in template {
let mut value = t; let mut value = t;
for (i, x) in params.iter().enumerate() { for (i, x) in params.iter().enumerate() {
let mut param = x.to_string();
if let Some(DebugConfigCompletion::Advanced(cfg)) = start_config.completion.get(i) {
if cfg.completion == Some("filename".to_owned())
|| cfg.completion == Some("directory".to_owned())
{
param = std::fs::canonicalize(x).ok()
.and_then(|pb| pb.into_os_string().into_string().ok())
.unwrap_or(x.to_string());
}
}
// For param #0 replace {0} in args // For param #0 replace {0} in args
value = value.replace(format!("{{{}}}", i).as_str(), x); value = value.replace(format!("{{{}}}", i).as_str(), &param);
} }
if let Ok(integer) = value.parse::<usize>() { if let Ok(integer) = value.parse::<usize>() {

@ -188,6 +188,18 @@ comment-token = "//"
indent = { tab-width = 2, unit = " " } indent = { tab-width = 2, unit = " " }
[language.debugger]
name = "node-debug2"
transport = "stdio"
# args consisting of cmd (node) and path to adapter should be added to user's configuration
quirks = { absolute-paths = true }
[[language.debugger.templates]]
name = "source"
request = "launch"
completion = [ { name = "main", completion = "filename", default = "index.js" } ]
args = { program = "{0}" }
[[language]] [[language]]
name = "typescript" name = "typescript"
scope = "source.ts" scope = "source.ts"

Loading…
Cancel
Save