package de.neitzel.fxdesigner.intellij; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.WriteIntentReadAction; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.LocalFileSystem; import de.neitzel.fxdesigner.host.*; import java.nio.file.Path; import java.util.concurrent.*; /** * IDE composition; shared build execution exposes output/cancellation to IDE presentation * callbacks. */ public final class IntellijHost implements AutoCloseable { private final SessionScope scope = new SessionScope(); private final HostServices services; public IntellijHost( Project project, HostServices.Runtimes runtimes, HostServices.Diagnostics diagnostics) { var docs = scope.own(new IntellijDocuments(project)); var builds = new ProcessBuilds(); services = new HostServices( docs, (request, output) -> scope.own(builds.start(request, output)), runtimes, location -> { var result = new CompletableFuture(); ApplicationManager.getApplication() .invokeLater( () -> WriteIntentReadAction.run( () -> { try { if (project.isDisposed()) throw new IllegalStateException("Project disposed"); var file = LocalFileSystem.getInstance() .refreshAndFindFileByNioFile( Path.of(location.document())); if (file == null) throw new IllegalArgumentException( "Navigation file unavailable"); new OpenFileDescriptor(project, file, location.offset()) .navigate(true); result.complete(null); } catch (Throwable e) { result.completeExceptionally(e); } })); return result; }, diagnostics, scope); Disposer.register(project, this::close); } public HostServices services() { return services; } public void close() { scope.close(); } }