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
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
name: ci

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

jobs:
java:
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, macos-15, windows-2025]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
with:
distribution: temurin
java-version: '21'
cache: maven
- run: mvn --batch-mode test
16 changes: 13 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
# zed-eclipse

Buildable Eclipse core candidate for Zed Package Manager state, diagnostics, and recommended actions.
Eclipse integration work for Zed Package Manager state, diagnostics, and confirmation-gated recommended actions.

The Java process adapter uses an argv vector, a bounded timeout, schema validation, failure redaction, and rejects command actions that do not require explicit confirmation. `mvn test` exercises the safety boundary.
The dedicated repository now contains:

A dedicated repository still needs the PDE/OSGi bundle, Zed Packages view, workspace markers, quick fixes, p2 update site, and clean Eclipse application tests.
- a Java 21 process adapter using argv execution, bounded timeout, schema validation, failure redaction, and unsafe-action rejection;
- a multi-root workspace model for the future **Zed Packages** view;
- Problems-marker projections with file-specific resources and `.zpkg.toml` fallback markers;
- confirmation-gated quick-fix command previews carrying exact executable, argv, and working directory;
- JUnit coverage and cross-platform Maven CI.

```sh
mvn test
```

Remaining native work is the PDE/OSGi bundle, resource listeners, view and quick-fix UI wiring, clean Eclipse application tests, and p2 feature/update-site packaging.
27 changes: 27 additions & 0 deletions conformance/ide-integration.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
{
"schema": "zed-pkg/ide-integration-conformance/v1",
"integration": "eclipse",
"repository": "zed-pkg/zed-eclipse",
"contractVersion": 1,
"level": {"core": "pass", "nativeShell": "workspace-marker-model", "distribution": "repository"},
"capabilities": {
"multiRootDiscovery": "workspace-model",
"manifestDiagnostics": true,
"lockDiagnostics": true,
"materializationDiagnostics": true,
"stagingRecovery": true,
"argvExecution": true,
"boundedExecution": true,
"outputRedaction": true,
"explicitMutationConfirmation": true,
"problemsMarkerProjection": true,
"versionedInspectAdapter": "pending-zed-cli-191",
"nativeUnitTests": true,
"repoLocalCI": true,
"immutableWorkflowInputs": true,
"fixedRunnerImages": true,
"checkoutCredentialsPersisted": false
},
"remaining": ["PDE/OSGi bundle", "Zed Packages view", "workspace resource listeners", "quick-fix UI wiring", "Eclipse application test", "p2 update site"],
"linearIssue": "DEN-2508"
}
50 changes: 50 additions & 0 deletions src/main/java/tech/zpkg/eclipse/ZedWorkspaceModel.java
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
package tech.zpkg.eclipse;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public final class ZedWorkspaceModel {
public record PackageNode(String root, long errors, long warnings, List<ZedInspector.Issue> issues) {}
public record Marker(String workspaceRoot, String resource, String severity, String issueId, String message) {}
public record ActionPreview(String executable, List<String> arguments, String workingDirectory, boolean requiresConfirmation) {}
public record Snapshot(List<PackageNode> packages, List<Marker> markers) {}

private ZedWorkspaceModel() {}

public static Snapshot project(List<ZedInspector.Report> reports) {
var packages = new ArrayList<PackageNode>();
var markers = new ArrayList<Marker>();
for (var report : reports == null ? List.<ZedInspector.Report>of() : reports) {
var root = Path.of(report.workspaceRoot()).toAbsolutePath().normalize();
var issues = report.issues() == null ? List.<ZedInspector.Issue>of() : report.issues();
long errors = issues.stream().filter(issue -> "error".equalsIgnoreCase(issue.severity())).count();
long warnings = issues.stream().filter(issue -> "warning".equalsIgnoreCase(issue.severity())).count();
packages.add(new PackageNode(root.toString(), errors, warnings, List.copyOf(issues)));
for (var issue : issues) {
var files = issue.files() == null || issue.files().isEmpty() ? List.of(".zpkg.toml") : issue.files();
for (var file : files) {
var resourcePath = Path.of(file);
var resource = resourcePath.isAbsolute() ? resourcePath.normalize() : root.resolve(resourcePath).normalize();
markers.add(new Marker(root.toString(), resource.toString(), issue.severity(), issue.id(), issue.title() + ": " + issue.detail()));
}
}
}
packages.sort(Comparator.comparing(PackageNode::root));
markers.sort(Comparator.comparing(Marker::resource).thenComparing(Marker::issueId));
return new Snapshot(List.copyOf(packages), List.copyOf(markers));
}

public static ActionPreview preview(ZedInspector.Action action, Path root) {
if (!"command".equals(action.kind())) throw new IllegalArgumentException("only command actions have an execution preview");
if (!action.requiresConfirmation()) throw new IllegalArgumentException("command actions must require explicit confirmation");
if (action.command() == null || action.command().isBlank()) throw new IllegalArgumentException("command executable must not be blank");
return new ActionPreview(
action.command(),
List.copyOf(action.arguments() == null ? List.of() : action.arguments()),
root.toAbsolutePath().normalize().toString(),
true
);
}
}
43 changes: 43 additions & 0 deletions src/test/java/tech/zpkg/eclipse/ZedWorkspaceModelTest.java
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
package tech.zpkg.eclipse;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.nio.file.Path;
import java.util.List;
import org.junit.jupiter.api.Test;

class ZedWorkspaceModelTest {
@Test
void projectsPackagesAndProblemsMarkersAcrossWorkspaceRoots() {
var warning = new ZedInspector.Issue(
"lock.stale", "warning", "Stale lock", "lock is stale", List.of(".zpkg.lock"),
List.of(new ZedInspector.Action("install", "Install", "command", "zed", List.of("install"), true))
);
var error = new ZedInspector.Issue("manifest.invalid", "error", "Invalid manifest", "bad toml", List.of(), List.of());
var snapshot = ZedWorkspaceModel.project(List.of(
new ZedInspector.Report(1, "zeta", null, List.of(warning)),
new ZedInspector.Report(1, "alpha", null, List.of(error))
));
assertEquals(2, snapshot.packages().size());
assertTrue(snapshot.packages().get(0).root().endsWith("alpha"));
assertEquals(1, snapshot.packages().get(0).errors());
assertEquals(1, snapshot.packages().get(1).warnings());
assertEquals(2, snapshot.markers().size());
assertTrue(snapshot.markers().stream().anyMatch(marker -> marker.resource().endsWith(".zpkg.toml")));
assertTrue(snapshot.markers().stream().anyMatch(marker -> marker.resource().endsWith(".zpkg.lock")));
}

@Test
void previewsOnlyConfirmationGatedQuickFixCommands() {
var action = new ZedInspector.Action("install", "Install", "command", "zed", List.of("install"), true);
var preview = ZedWorkspaceModel.preview(action, Path.of("workspace"));
assertEquals("zed", preview.executable());
assertEquals(List.of("install"), preview.arguments());
assertTrue(preview.requiresConfirmation());
assertThrows(IllegalArgumentException.class, () -> ZedWorkspaceModel.preview(
new ZedInspector.Action("bad", "Bad", "command", "zed", List.of("install"), false), Path.of("workspace")
));
}
}