дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(java): resolve compiled Kotlin APIs in Maven Java editors (#669)
Java files in mixed Maven projects could not resolve Kotlin types from the same module or upstream reactor modules, because Kotlin compiler output never reached JDT's Java model. A per-project bridge compiles saved Kotlin sources with the project's own Maven setup into private staging output (a bundled Maven extension redirects outputs and records each module's Kotlin compile result) and mounts the Kotlin classes as marked libraries through a bundled JDT command, leaving m2e/JRE containers and other entries untouched. The last successful snapshot stays mounted while rebuilding; a new one is published when every Kotlin target compiles, even if javac fails, so Java callers of a renamed or removed Kotlin API show their errors in the editor. Kotlin compile failures keep the previous API and are reported under the kotlin-bridge Problems source. Removing the last Kotlin file withdraws the libraries. Changes under build outputs and excluded directories never trigger a rebuild. Part of #428
Цей коміт міститься в:
1 джерело
8d38aa4a9c
коміт
9bb44cbeb3
23 files changed
+1874
-10
No files matched your search
@@ -948,6 +948,49 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// The same jar supplies the JDT command and the private Maven output redirector.
|
||||
pub fn kotlin_bridge_bundle(data_dir: &Path) -> Option<PathBuf> {
|
||||
let extension = data_dir.join("kotlin-bridge-1.0.0.jar");
|
||||
let bytes = include_bytes!("../../../plugins/kotlin-bridge/openidea-kotlin-bridge.jar");
|
||||
if std::fs::read(&extension).is_ok_and(|old| old == bytes) {
|
||||
return Some(extension);
|
||||
}
|
||||
let temporary = data_dir.join(format!(
|
||||
"kotlin-bridge-{}-{}.tmp",
|
||||
std::process::id(),
|
||||
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).ok()?.as_nanos()
|
||||
));
|
||||
let result = std::fs::create_dir_all(data_dir)
|
||||
.and_then(|_| std::fs::write(&temporary, bytes))
|
||||
.and_then(|_| std::fs::rename(&temporary, &extension));
|
||||
if let Err(error) = result {
|
||||
let _ = std::fs::remove_file(temporary);
|
||||
tracing::warn!("Kotlin bridge extension unavailable: {error}");
|
||||
return std::fs::read(&extension).is_ok_and(|old| old == bytes).then_some(extension);
|
||||
}
|
||||
Some(extension)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod kotlin_bridge_bundle_tests {
|
||||
#[test]
|
||||
fn embeds_both_runtime_targets_and_repairs_a_damaged_installation() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let path = super::kotlin_bridge_bundle(directory.path()).unwrap();
|
||||
let expected = std::fs::read(&path).unwrap();
|
||||
let mut archive = zip::ZipArchive::new(std::io::Cursor::new(&expected)).unwrap();
|
||||
for (class, major) in [("KotlinLibraries", 65), ("IsolatedOutput", 52)] {
|
||||
use std::io::Read;
|
||||
let mut bytes = Vec::new();
|
||||
archive.by_name(&format!("ai/openidea/kotlin/{class}.class")).unwrap().read_to_end(&mut bytes).unwrap();
|
||||
assert_eq!(u16::from_be_bytes([bytes[6], bytes[7]]), major);
|
||||
}
|
||||
std::fs::write(&path, "incomplete").unwrap();
|
||||
assert_eq!(super::kotlin_bridge_bundle(directory.path()), Some(path.clone()));
|
||||
assert_eq!(std::fs::read(path).unwrap(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
/// Installs the app-owned JDT LS command bundle, falling back to ordinary LSP on IO failure.
|
||||
pub fn usages_bundle(data_dir: &Path) -> Option<PathBuf> {
|
||||
let extension = data_dir.join("java-usages-1.1.1.jar");
|
||||
|
||||
Reference in new issue
Заблокувати користувача