Skip to content

Commit 2defa5f

Browse files
authored
Add debug context to error messages across codebase (#186)
Improve error handling by adding contextual information to error messages instead of forwarding raw errors. This helps with debugging by providing details about what operation failed and relevant parameters like file paths, URLs, and component names. All error messages now follow a consistent pattern: - Start with "Failed to..." - Use colon separator before error details - Use "err" as the error variable name
1 parent 9b8e5ac commit 2defa5f

6 files changed

Lines changed: 190 additions & 91 deletions

File tree

src/debugger.rs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ impl Debugger {
128128
configuration,
129129
find_latest_local_debugger(),
130130
DEBUGGER_INSTALL_PATH,
131-
)? {
131+
)
132+
.map_err(|err| format!("Failed to resolve debugger installation: {err}"))?
133+
{
132134
self.plugin_path = Some(path.clone());
133135
return Ok(path);
134136
}
@@ -153,11 +155,13 @@ impl Debugger {
153155
return Ok(path.clone());
154156
}
155157

156-
create_path_if_not_exists(prefix)?;
158+
create_path_if_not_exists(prefix)
159+
.map_err(|err| format!("Failed to create debugger directory '{prefix}': {err}"))?;
157160

158161
download_file(
159162
JAVA_DEBUG_PLUGIN_FORK_URL,
160-
&path_to_string(jar_path.clone())?,
163+
&path_to_string(jar_path.clone())
164+
.map_err(|err| format!("Invalid debugger jar path {jar_path:?}: {err}"))?,
161165
DownloadedFileType::Uncompressed,
162166
)
163167
.map_err(|err| {
@@ -230,7 +234,7 @@ impl Debugger {
230234
}
231235

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

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

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

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

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

280286
pub fn start_session(&self) -> zed::Result<TcpArgumentsTemplate> {
281-
let port = self.lsp.get()?.request::<u16>(
282-
"workspace/executeCommand",
283-
json!({ "command": "vscode.java.startDebugSession" }),
284-
)?;
287+
let port = self
288+
.lsp
289+
.get()
290+
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
291+
.request::<u16>(
292+
"workspace/executeCommand",
293+
json!({ "command": "vscode.java.startDebugSession" }),
294+
)
295+
.map_err(|err| format!("Failed to start debug session via LSP: {err}"))?;
285296

286297
Ok(TcpArgumentsTemplate {
287298
host: None,
@@ -292,7 +303,7 @@ impl Debugger {
292303

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

297308
if config
298309
.get("request")
@@ -303,7 +314,7 @@ impl Debugger {
303314
}
304315

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

308319
let workspace_folder = worktree.root_path();
309320

@@ -316,8 +327,10 @@ impl Debugger {
316327

317328
let entries = self
318329
.lsp
319-
.get()?
320-
.resolve_main_class(arguments)?
330+
.get()
331+
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
332+
.resolve_main_class(arguments)
333+
.map_err(|err| format!("Failed to resolve main class: {err}"))?
321334
.into_iter()
322335
.filter(|entry| {
323336
config
@@ -369,7 +382,12 @@ impl Debugger {
369382

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

372-
let result = self.lsp.get()?.resolve_class_path(arguments)?;
385+
let result = self
386+
.lsp
387+
.get()
388+
.map_err(|err| format!("Failed to acquire LSP client lock: {err}"))?
389+
.resolve_class_path(arguments)
390+
.map_err(|err| format!("Failed to resolve classpath: {err}"))?;
373391

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

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

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

402421
let canonical_path = Value::String(
403422
current_dir
404423
.join(
405424
self.plugin_path
406425
.as_ref()
407-
.ok_or("Debugger is not loaded yet")?,
426+
.ok_or("Debugger plugin path not set")?,
408427
)
409428
.to_string_lossy()
410429
.to_string(),

src/java.rs

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ impl Extension for Java {
173173
}
174174

175175
if self.integrations.is_some() {
176-
self.lsp()?.switch_workspace(worktree.root_path())?;
176+
self.lsp()?
177+
.switch_workspace(worktree.root_path())
178+
.map_err(|err| {
179+
format!("Failed to switch LSP workspace for debug adapter: {err}")
180+
})?;
177181
}
178182

179183
Ok(DebugAdapterBinary {
@@ -182,15 +186,22 @@ impl Extension for Java {
182186
cwd: Some(worktree.root_path()),
183187
envs: vec![],
184188
request_args: StartDebuggingRequestArguments {
185-
request: self.dap_request_kind(
186-
adapter_name,
187-
Value::from_str(config.config.as_str())
188-
.map_err(|e| format!("Invalid JSON configuration: {e}"))?,
189-
)?,
190-
configuration: self.debugger()?.inject_config(worktree, config.config)?,
189+
request: self
190+
.dap_request_kind(
191+
adapter_name,
192+
Value::from_str(config.config.as_str())
193+
.map_err(|err| format!("Invalid JSON configuration: {err}"))?,
194+
)
195+
.map_err(|err| format!("Failed to determine debug request kind: {err}"))?,
196+
configuration: self
197+
.debugger()?
198+
.inject_config(worktree, config.config)
199+
.map_err(|err| format!("Failed to inject debug configuration: {err}"))?,
191200
},
192201
connection: Some(zed::resolve_tcp_template(
193-
self.debugger()?.start_session()?,
202+
self.debugger()?
203+
.start_session()
204+
.map_err(|err| format!("Failed to start debug session: {err}"))?,
194205
)?),
195206
})
196207
}
@@ -245,7 +256,11 @@ impl Extension for Java {
245256
Ok(zed::DebugScenario {
246257
adapter: config.adapter,
247258
build: None,
248-
tcp_connection: Some(self.debugger()?.start_session()?),
259+
tcp_connection: Some(
260+
self.debugger()?
261+
.start_session()
262+
.map_err(|err| format!("Failed to start debug session: {err}"))?,
263+
),
249264
label: "Attach to Java process".to_string(),
250265
config: debug_config.to_string(),
251266
})
@@ -263,7 +278,7 @@ impl Extension for Java {
263278
worktree: &Worktree,
264279
) -> zed::Result<zed::Command> {
265280
let current_dir =
266-
env::current_dir().map_err(|err| format!("could not get current dir: {err}"))?;
281+
env::current_dir().map_err(|err| format!("Failed to get current directory: {err}"))?;
267282

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

285301
// Add lombok as javaagent if settings.java.jdt.ls.lombokSupport.enabled is true
286302
let lombok_jvm_arg = if is_lombok_enabled(&configuration) {
287-
let lombok_jar_path =
288-
self.lombok_jar_path(language_server_id, &configuration, worktree)?;
289-
let canonical_lombok_jar_path = path_to_string(current_dir.join(lombok_jar_path))?;
303+
let lombok_jar_path = self
304+
.lombok_jar_path(language_server_id, &configuration, worktree)
305+
.map_err(|err| format!("Failed to get Lombok jar path: {err}"))?;
306+
let canonical_lombok_jar_path = path_to_string(current_dir.join(lombok_jar_path))
307+
.map_err(|err| format!("Failed to convert Lombok jar path to string: {err}"))?;
290308

291309
Some(format!("-javaagent:{canonical_lombok_jar_path}"))
292310
} else {
@@ -309,13 +327,18 @@ impl Extension for Java {
309327
}
310328
} else {
311329
// otherwise we launch ourselves
312-
args.extend(build_jdtls_launch_args(
313-
&self.language_server_binary_path(language_server_id, &configuration)?,
314-
&configuration,
315-
worktree,
316-
lombok_jvm_arg.into_iter().collect(),
317-
language_server_id,
318-
)?);
330+
args.extend(
331+
build_jdtls_launch_args(
332+
&self
333+
.language_server_binary_path(language_server_id, &configuration)
334+
.map_err(|err| format!("Failed to get JDTLS binary path: {err}"))?,
335+
&configuration,
336+
worktree,
337+
lombok_jvm_arg.into_iter().collect(),
338+
language_server_id,
339+
)
340+
.map_err(|err| format!("Failed to build JDTLS launch arguments: {err}"))?,
341+
);
319342
}
320343

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

329-
self.lsp()?.switch_workspace(worktree.root_path())?;
352+
self.lsp()?
353+
.switch_workspace(worktree.root_path())
354+
.map_err(|err| format!("Failed to switch LSP workspace: {err}"))?;
330355

331356
Ok(zed::Command {
332-
command: zed::node_binary_path()?,
357+
command: zed::node_binary_path()
358+
.map_err(|err| format!("Failed to get Node.js binary path: {err}"))?,
333359
args,
334360
env,
335361
})
@@ -341,14 +367,25 @@ impl Extension for Java {
341367
worktree: &Worktree,
342368
) -> zed::Result<Option<Value>> {
343369
if self.integrations.is_some() {
344-
self.lsp()?.switch_workspace(worktree.root_path())?;
370+
self.lsp()?
371+
.switch_workspace(worktree.root_path())
372+
.map_err(|err| {
373+
format!("Failed to switch LSP workspace for initialization: {err}")
374+
})?;
345375
}
346376

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

350381
if self.debugger().is_ok_and(|v| v.loaded()) {
351-
return Ok(Some(self.debugger()?.inject_plugin_into_options(options)?));
382+
return Ok(Some(
383+
self.debugger()?
384+
.inject_plugin_into_options(options)
385+
.map_err(|err| {
386+
format!("Failed to inject debugger plugin into options: {err}")
387+
})?,
388+
));
352389
}
353390

354391
Ok(options)

src/jdk.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,14 @@ pub fn try_to_fetch_and_install_latest_jdk(
7171
language_server_id: &LanguageServerId,
7272
configuration: &Option<Value>,
7373
) -> zed::Result<PathBuf> {
74-
let jdk_path = get_curr_dir()?.join(JDK_INSTALL_PATH);
74+
let jdk_path = get_curr_dir()
75+
.map_err(|err| format!("Failed to get current directory for JDK installation: {err}"))?
76+
.join(JDK_INSTALL_PATH);
7577

7678
// Check if we should use local installation based on update mode
7779
if let Some(path) =
78-
should_use_local_or_download(configuration, find_latest_local_jdk(), JDK_INSTALL_PATH)?
80+
should_use_local_or_download(configuration, find_latest_local_jdk(), JDK_INSTALL_PATH)
81+
.map_err(|err| format!("Failed to resolve JDK installation: {err}"))?
7982
{
8083
return get_jdk_bin_path(&path);
8184
}
@@ -92,7 +95,8 @@ pub fn try_to_fetch_and_install_latest_jdk(
9295
require_assets: false,
9396
pre_release: false,
9497
},
95-
)?
98+
)
99+
.map_err(|err| format!("Failed to fetch latest Corretto release from {CORRETTO_REPO}: {err}"))?
96100
.version;
97101

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

106-
let platform = get_platform()?;
107-
let arch = get_architecture()?;
110+
let platform = get_platform()
111+
.map_err(|err| format!("Failed to detect platform for JDK download: {err}"))?;
112+
let arch = get_architecture()
113+
.map_err(|err| format!("Failed to detect architecture for JDK download: {err}"))?;
108114

115+
let download_url = build_corretto_url(&version, &platform, &arch);
109116
download_file(
110-
build_corretto_url(&version, &platform, &arch).as_str(),
111-
path_to_string(install_path.clone())?.as_str(),
117+
download_url.as_str(),
118+
path_to_string(install_path.clone())
119+
.map_err(|err| format!("Invalid JDK install path {install_path:?}: {err}"))?
120+
.as_str(),
112121
match zed::current_platform().0 {
113122
Os::Windows => DownloadedFileType::Zip,
114123
_ => DownloadedFileType::GzipTar,
115124
},
116-
)?;
125+
)
126+
.map_err(|err| format!("Failed to download Corretto JDK from {download_url}: {err}"))?;
117127

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

133144
Ok(install_path
134145
.join(extracted_dir)

0 commit comments

Comments
 (0)