Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 37 additions & 18 deletions src/debugger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ impl Debugger {
configuration,
find_latest_local_debugger(),
DEBUGGER_INSTALL_PATH,
)? {
)
.map_err(|err| format!("Failed to resolve debugger installation: {err}"))?
{
self.plugin_path = Some(path.clone());
return Ok(path);
}
Expand All @@ -153,11 +155,13 @@ impl Debugger {
return Ok(path.clone());
}

create_path_if_not_exists(prefix)?;
create_path_if_not_exists(prefix)
.map_err(|err| format!("Failed to create debugger directory '{prefix}': {err}"))?;

download_file(
JAVA_DEBUG_PLUGIN_FORK_URL,
&path_to_string(jar_path.clone())?,
&path_to_string(jar_path.clone())
.map_err(|err| format!("Invalid debugger jar path {jar_path:?}: {err}"))?,
DownloadedFileType::Uncompressed,
)
.map_err(|err| {
Expand Down Expand Up @@ -230,7 +234,7 @@ impl Debugger {
}

let xml = String::from_utf8(res?.body).map_err(|err| {
format!("could not get string from maven metadata response body: {err}")
format!("Failed to get string from Maven metadata response body: {err}")
})?;

let start_tag = "<latest>";
Expand All @@ -240,7 +244,9 @@ impl Debugger {
.split_once(start_tag)
.and_then(|(_, rest)| rest.split_once(end_tag))
.map(|(content, _)| content.trim())
.ok_or(format!("Failed to parse maven-metadata.xml response {xml}"))?;
.ok_or(format!(
"Failed to parse maven-metadata.xml response: {xml}"
))?;

let artifact = "com.microsoft.java.debug.plugin";

Expand All @@ -267,7 +273,7 @@ impl Debugger {
&path_to_string(&jar_path)?,
DownloadedFileType::Uncompressed,
)
.map_err(|err| format!("Failed to download {url} {err}"))?;
.map_err(|err| format!("Failed to download {url}: {err}"))?;

// Mark the downloaded version for "Once" mode tracking
let _ = mark_checked_once(DEBUGGER_INSTALL_PATH, latest_version);
Expand All @@ -278,10 +284,15 @@ impl Debugger {
}

pub fn start_session(&self) -> zed::Result<TcpArgumentsTemplate> {
let port = self.lsp.get()?.request::<u16>(
"workspace/executeCommand",
json!({ "command": "vscode.java.startDebugSession" }),
)?;
let port = self
.lsp
.get()
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
.request::<u16>(
"workspace/executeCommand",
json!({ "command": "vscode.java.startDebugSession" }),
)
.map_err(|err| format!("Failed to start debug session via LSP: {err}"))?;

Ok(TcpArgumentsTemplate {
host: None,
Expand All @@ -292,7 +303,7 @@ impl Debugger {

pub fn inject_config(&self, worktree: &Worktree, config_string: String) -> zed::Result<String> {
let config: Value = serde_json::from_str(&config_string)
.map_err(|err| format!("Failed to parse debug config {err}"))?;
.map_err(|err| format!("Failed to parse debug config: {err}"))?;

if config
.get("request")
Expand All @@ -303,7 +314,7 @@ impl Debugger {
}

let mut config = serde_json::from_value::<JavaDebugLaunchConfig>(config)
.map_err(|err| format!("Failed to parse java debug config {err}"))?;
.map_err(|err| format!("Failed to parse Java debug config: {err}"))?;

let workspace_folder = worktree.root_path();

Expand All @@ -316,8 +327,10 @@ impl Debugger {

let entries = self
.lsp
.get()?
.resolve_main_class(arguments)?
.get()
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
.resolve_main_class(arguments)
.map_err(|err| format!("Failed to resolve main class: {err}"))?
.into_iter()
.filter(|entry| {
config
Expand Down Expand Up @@ -369,7 +382,12 @@ impl Debugger {

let arguments = vec![main_class.clone(), project_name.clone(), scope.clone()];

let result = self.lsp.get()?.resolve_class_path(arguments)?;
let result = self
.lsp
.get()
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
.resolve_class_path(arguments)
.map_err(|err| format!("Failed to resolve classpath: {err}"))?;

for resolved in result {
classpaths.extend(resolved);
Expand All @@ -387,7 +405,7 @@ impl Debugger {
config.cwd = config.cwd.or(Some(workspace_folder.to_string()));

let config = serde_json::to_string(&config)
.map_err(|err| format!("Failed to stringify debug config {err}"))?
.map_err(|err| format!("Failed to stringify debug config: {err}"))?
.replace("${workspaceFolder}", &workspace_folder);

Ok(config)
Expand All @@ -397,14 +415,15 @@ impl Debugger {
&self,
initialization_options: Option<Value>,
) -> zed::Result<Value> {
let current_dir = get_curr_dir()?;
let current_dir = get_curr_dir()
.map_err(|err| format!("Failed to get current directory for debugger plugin: {err}"))?;

let canonical_path = Value::String(
current_dir
.join(
self.plugin_path
.as_ref()
.ok_or("Debugger is not loaded yet")?,
.ok_or("Debugger plugin path not set")?,
)
.to_string_lossy()
.to_string(),
Expand Down
89 changes: 63 additions & 26 deletions src/java.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,11 @@ impl Extension for Java {
}

if self.integrations.is_some() {
self.lsp()?.switch_workspace(worktree.root_path())?;
self.lsp()?
.switch_workspace(worktree.root_path())
.map_err(|err| {
format!("Failed to switch LSP workspace for debug adapter: {err}")
})?;
}

Ok(DebugAdapterBinary {
Expand All @@ -182,15 +186,22 @@ impl Extension for Java {
cwd: Some(worktree.root_path()),
envs: vec![],
request_args: StartDebuggingRequestArguments {
request: self.dap_request_kind(
adapter_name,
Value::from_str(config.config.as_str())
.map_err(|e| format!("Invalid JSON configuration: {e}"))?,
)?,
configuration: self.debugger()?.inject_config(worktree, config.config)?,
request: self
.dap_request_kind(
adapter_name,
Value::from_str(config.config.as_str())
.map_err(|err| format!("Invalid JSON configuration: {err}"))?,
)
.map_err(|err| format!("Failed to determine debug request kind: {err}"))?,
configuration: self
.debugger()?
.inject_config(worktree, config.config)
.map_err(|err| format!("Failed to inject debug configuration: {err}"))?,
},
connection: Some(zed::resolve_tcp_template(
self.debugger()?.start_session()?,
self.debugger()?
.start_session()
.map_err(|err| format!("Failed to start debug session: {err}"))?,
)?),
})
}
Expand Down Expand Up @@ -245,7 +256,11 @@ impl Extension for Java {
Ok(zed::DebugScenario {
adapter: config.adapter,
build: None,
tcp_connection: Some(self.debugger()?.start_session()?),
tcp_connection: Some(
self.debugger()?
.start_session()
.map_err(|err| format!("Failed to start debug session: {err}"))?,
),
label: "Attach to Java process".to_string(),
config: debug_config.to_string(),
})
Expand All @@ -263,7 +278,7 @@ impl Extension for Java {
worktree: &Worktree,
) -> zed::Result<zed::Command> {
let current_dir =
env::current_dir().map_err(|err| format!("could not get current dir: {err}"))?;
env::current_dir().map_err(|err| format!("Failed to get current directory: {err}"))?;

let configuration =
self.language_server_workspace_configuration(language_server_id, worktree)?;
Expand All @@ -279,14 +294,17 @@ impl Extension for Java {
"--input-type=module".to_string(),
"-e".to_string(),
PROXY_FILE.to_string(),
path_to_string(current_dir.clone())?,
path_to_string(current_dir.clone())
.map_err(|err| format!("Failed to convert current directory to string: {err}"))?,
];

// Add lombok as javaagent if settings.java.jdt.ls.lombokSupport.enabled is true
let lombok_jvm_arg = if is_lombok_enabled(&configuration) {
let lombok_jar_path =
self.lombok_jar_path(language_server_id, &configuration, worktree)?;
let canonical_lombok_jar_path = path_to_string(current_dir.join(lombok_jar_path))?;
let lombok_jar_path = self
.lombok_jar_path(language_server_id, &configuration, worktree)
.map_err(|err| format!("Failed to get Lombok jar path: {err}"))?;
let canonical_lombok_jar_path = path_to_string(current_dir.join(lombok_jar_path))
.map_err(|err| format!("Failed to convert Lombok jar path to string: {err}"))?;

Some(format!("-javaagent:{canonical_lombok_jar_path}"))
} else {
Expand All @@ -309,13 +327,18 @@ impl Extension for Java {
}
} else {
// otherwise we launch ourselves
args.extend(build_jdtls_launch_args(
&self.language_server_binary_path(language_server_id, &configuration)?,
&configuration,
worktree,
lombok_jvm_arg.into_iter().collect(),
language_server_id,
)?);
args.extend(
build_jdtls_launch_args(
&self
.language_server_binary_path(language_server_id, &configuration)
.map_err(|err| format!("Failed to get JDTLS binary path: {err}"))?,
&configuration,
worktree,
lombok_jvm_arg.into_iter().collect(),
language_server_id,
)
.map_err(|err| format!("Failed to build JDTLS launch arguments: {err}"))?,
);
}

// download debugger if not exists
Expand All @@ -326,10 +349,13 @@ impl Extension for Java {
println!("Failed to download debugger: {err}");
};

self.lsp()?.switch_workspace(worktree.root_path())?;
self.lsp()?
.switch_workspace(worktree.root_path())
.map_err(|err| format!("Failed to switch LSP workspace: {err}"))?;

Ok(zed::Command {
command: zed::node_binary_path()?,
command: zed::node_binary_path()
.map_err(|err| format!("Failed to get Node.js binary path: {err}"))?,
args,
env,
})
Expand All @@ -341,14 +367,25 @@ impl Extension for Java {
worktree: &Worktree,
) -> zed::Result<Option<Value>> {
if self.integrations.is_some() {
self.lsp()?.switch_workspace(worktree.root_path())?;
self.lsp()?
.switch_workspace(worktree.root_path())
.map_err(|err| {
format!("Failed to switch LSP workspace for initialization: {err}")
})?;
}

let options = LspSettings::for_worktree(language_server_id.as_ref(), worktree)
.map(|lsp_settings| lsp_settings.initialization_options)?;
.map(|lsp_settings| lsp_settings.initialization_options)
.map_err(|err| format!("Failed to get LSP settings for worktree: {err}"))?;

if self.debugger().is_ok_and(|v| v.loaded()) {
return Ok(Some(self.debugger()?.inject_plugin_into_options(options)?));
return Ok(Some(
self.debugger()?
.inject_plugin_into_options(options)
.map_err(|err| {
format!("Failed to inject debugger plugin into options: {err}")
})?,
));
}

Ok(options)
Expand Down
29 changes: 20 additions & 9 deletions src/jdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,14 @@ pub fn try_to_fetch_and_install_latest_jdk(
language_server_id: &LanguageServerId,
configuration: &Option<Value>,
) -> zed::Result<PathBuf> {
let jdk_path = get_curr_dir()?.join(JDK_INSTALL_PATH);
let jdk_path = get_curr_dir()
.map_err(|err| format!("Failed to get current directory for JDK installation: {err}"))?
.join(JDK_INSTALL_PATH);

// Check if we should use local installation based on update mode
if let Some(path) =
should_use_local_or_download(configuration, find_latest_local_jdk(), JDK_INSTALL_PATH)?
should_use_local_or_download(configuration, find_latest_local_jdk(), JDK_INSTALL_PATH)
.map_err(|err| format!("Failed to resolve JDK installation: {err}"))?
{
return get_jdk_bin_path(&path);
}
Expand All @@ -92,7 +95,8 @@ pub fn try_to_fetch_and_install_latest_jdk(
require_assets: false,
pre_release: false,
},
)?
)
.map_err(|err| format!("Failed to fetch latest Corretto release from {CORRETTO_REPO}: {err}"))?
.version;

let install_path = jdk_path.join(&version);
Expand All @@ -103,17 +107,23 @@ pub fn try_to_fetch_and_install_latest_jdk(
&LanguageServerInstallationStatus::Downloading,
);

let platform = get_platform()?;
let arch = get_architecture()?;
let platform = get_platform()
.map_err(|err| format!("Failed to detect platform for JDK download: {err}"))?;
let arch = get_architecture()
.map_err(|err| format!("Failed to detect architecture for JDK download: {err}"))?;

let download_url = build_corretto_url(&version, &platform, &arch);
download_file(
build_corretto_url(&version, &platform, &arch).as_str(),
path_to_string(install_path.clone())?.as_str(),
download_url.as_str(),
path_to_string(install_path.clone())
.map_err(|err| format!("Invalid JDK install path {install_path:?}: {err}"))?
.as_str(),
match zed::current_platform().0 {
Os::Windows => DownloadedFileType::Zip,
_ => DownloadedFileType::GzipTar,
},
)?;
)
.map_err(|err| format!("Failed to download Corretto JDK from {download_url}: {err}"))?;

// Remove older versions
let _ = remove_all_files_except(&jdk_path, version.as_str());
Expand All @@ -128,7 +138,8 @@ pub fn try_to_fetch_and_install_latest_jdk(
fn get_jdk_bin_path(install_path: &Path) -> zed::Result<PathBuf> {
// Depending on the platform the name of the extracted dir might differ
// Rather than hard coding, extract it dynamically
let extracted_dir = get_extracted_dir(install_path)?;
let extracted_dir = get_extracted_dir(install_path)
.map_err(|err| format!("Failed to find JDK directory in {install_path:?}: {err}"))?;

Ok(install_path
.join(extracted_dir)
Expand Down
Loading