Compare commits

...
Author SHA1 Message Date
l0ng-ai 05f84cc654 fix(java): pass jdtls the compiler defaults as a file URI
The generated compiler-defaults.prefs was passed to jdtls as a bare path in
java.settings.url. jdtls parses that setting as a URI whenever a watched file
changes, so a data directory with a space (macOS 'Application Support') logged a
URISyntaxException on every file event. Pass a file: URI instead; reading the
prefs back accepts both forms.
2026-11-12 04:54:30 +08:00
4 changed files with 26 additions and 9 deletions

No files matched your search

Generated
+1
View File
@@ -4796,6 +4796,7 @@ dependencies = [
"tempfile",
"toml 0.9.12+spec-1.1.0",
"tracing",
"url",
"zip",
]
+11 -4
View File
@@ -1314,15 +1314,22 @@ mod tests {
std::fs::write(&file, format!("{}=warning\n{}=ignore\nother=error\n", ACCESS_OPTIONS[0], ACCESS_OPTIONS[1]))
.unwrap();
let mut cfg: ide_language::LanguageServerConfig = toml::from_str("name = 'jdtls'\ncommand = 'jdtls'").unwrap();
cfg.initialization_options = Some(
toml::Value::try_from(json!({"settings": {"java": {"settings": {"url": file.to_string_lossy()}}}}))
.unwrap(),
);
let with_url = |cfg: &mut ide_language::LanguageServerConfig, url: String| {
cfg.initialization_options =
Some(toml::Value::try_from(json!({"settings": {"java": {"settings": {"url": url}}}})).unwrap());
};
with_url(&mut cfg, crate::uri::path_to_uri_string(&file));
assert_eq!(compiler_defaults(&cfg), json!({}));
for prefix in ["", "--jvm-arg="] {
cfg.args = vec![format!("{prefix}-Djava.import.generatesMetadataFilesAtProjectRoot=false")];
assert_eq!(compiler_defaults(&cfg), json!({ACCESS_OPTIONS[0]: "warning", ACCESS_OPTIONS[1]: "ignore"}));
}
with_url(&mut cfg, file.to_string_lossy().into_owned());
assert_eq!(
compiler_defaults(&cfg),
json!({ACCESS_OPTIONS[0]: "warning", ACCESS_OPTIONS[1]: "ignore"}),
"a path"
);
cfg.args.push("--jvm-arg=-Djava.import.generatesMetadataFilesAtProjectRoot=true".into());
assert_eq!(compiler_defaults(&cfg), json!({}), "the final JVM property wins");
cfg.args.pop();
+1
View File
@@ -19,4 +19,5 @@ specta.workspace = true
tempfile.workspace = true
toml.workspace = true
tracing.workspace = true
url = "2"
zip.workspace = true
+13 -5
View File
@@ -876,9 +876,10 @@ org.eclipse.jdt.core.compiler.codegen.targetPlatform={jdt_ver}\n"
tracing::warn!("jdtls: cannot write compiler defaults: {e}");
return;
}
// jdtls accepts absolute filesystem paths as well as URLs (including paths
// containing spaces and Windows backslashes). Explicit server settings win later.
let defaults = json!({"settings": {"java": {"settings": {"url": file.to_string_lossy()}}}});
// A `file:` URI: jdtls parses the setting as a URI when matching watched-file
// changes, which fails on a bare path with spaces. Explicit server settings win later.
let url = url::Url::from_file_path(&file).map_or_else(|()| file.to_string_lossy().into_owned(), String::from);
let defaults = json!({"settings": {"java": {"settings": {"url": url}}}});
let existing = cfg.initialization_options.clone();
merge_init_options(cfg, defaults);
if let Some(existing) = existing {
@@ -1824,13 +1825,18 @@ mod java_compiler_tests {
serde_json::to_value(cfg.initialization_options.as_ref().unwrap()).unwrap()
}
fn prefs_path(options: &Value) -> PathBuf {
let url = options.pointer("/settings/java/settings/url").unwrap().as_str().unwrap();
url::Url::parse(url).unwrap().to_file_path().unwrap()
}
#[test]
fn serial_version_inspection_sets_the_compiler_option() {
let tmp = tempfile::tempdir().unwrap();
let url = |inspections: &InspectionSettings| {
let mut cfg = custom_server("jdtls", &LanguageServerSettings::default());
configure_java_compiler(&mut cfg, tmp.path(), inspections);
options(&cfg).pointer("/settings/java/settings/url").unwrap().as_str().unwrap().to_owned()
prefs_path(&options(&cfg))
};
let set = |o: ide_core::settings::InspectionOverride| {
let mut s = InspectionSettings::default();
@@ -1869,7 +1875,9 @@ mod java_compiler_tests {
merge_init_options(&mut cfg, json!({"settings": {"java": {"format": {"tabSize": 4}}}}));
configure_java_compiler(&mut cfg, &cache, &InspectionSettings::default());
let options = options(&cfg);
let path = PathBuf::from(options.pointer("/settings/java/settings/url").unwrap().as_str().unwrap());
let url = options.pointer("/settings/java/settings/url").unwrap().as_str().unwrap();
assert!(url.starts_with("file://") && !url.contains(' '), "{url}");
let path = prefs_path(&options);
assert!(path.starts_with(&cache));
let prefs = std::fs::read_to_string(&path).unwrap();
assert_eq!(prefs.lines().count(), 2);