From 310394be5789f56879584d15a5473c073f75ddd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 22 Feb 2026 09:00:12 +0100 Subject: [PATCH 1/4] Fix DS editor showing dirty on open without actual changes The DSComponent constructor called setNamespace() and setNamespacePrefix() which fired property change events, causing the model to be marked dirty during initial loading. Use super calls to set namespace defaults without triggering change events. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../org/eclipse/pde/internal/ds/core/text/DSComponent.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/text/DSComponent.java b/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/text/DSComponent.java index fba9e0b0055..d77f155748b 100644 --- a/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/text/DSComponent.java +++ b/ds/org.eclipse.pde.ds.core/src/org/eclipse/pde/internal/ds/core/text/DSComponent.java @@ -51,8 +51,10 @@ public class DSComponent extends DSObject implements IDSComponent { public DSComponent(DSModel model) { super(model, ELEMENT_COMPONENT); setAttributeName(IDSConstants.ELEMENT_COMPONENT); - setNamespace(IDSConstants.NAMESPACE); // hard code namespace to be 1.1 - setNamespacePrefix("scr"); //$NON-NLS-1$ + // Use super calls to set namespace defaults without firing property + // change events that would incorrectly mark the model as dirty + super.setNamespace(IDSConstants.NAMESPACE); + super.setNamespacePrefix("scr"); //$NON-NLS-1$ setInTheModel(true); } From 33e61ce8e088deb9b57d9d5ca75aff1321b66cf1 Mon Sep 17 00:00:00 2001 From: Eclipse PDE Bot Date: Sat, 28 Feb 2026 09:05:36 +0000 Subject: [PATCH 2/4] Version bump(s) for 4.40 stream --- ds/org.eclipse.pde.ds.core/META-INF/MANIFEST.MF | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ds/org.eclipse.pde.ds.core/META-INF/MANIFEST.MF b/ds/org.eclipse.pde.ds.core/META-INF/MANIFEST.MF index e9e6d20d0a5..9c8ee559139 100644 --- a/ds/org.eclipse.pde.ds.core/META-INF/MANIFEST.MF +++ b/ds/org.eclipse.pde.ds.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.pde.ds.core;singleton:=true -Bundle-Version: 1.3.900.qualifier +Bundle-Version: 1.3.1000.qualifier Bundle-Activator: org.eclipse.pde.internal.ds.core.Activator Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.29.0,4.0.0)", org.eclipse.core.resources;bundle-version="[3.3.0,4.0.0)", From f0f1778da3411ae2349eb12f8689be37672ee144 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:44:34 +0100 Subject: [PATCH 3/4] Fix DS annotation test setup reliability on macOS Fix DS annotation test setup reliability issues - Replace unreliable File.renameTo() with Files.move() for test.project rename, which throws on failure instead of failing silently - Fix afterAll() cleanup bug: project names were incorrectly doubled ("ds.annotations." + "ds.annotations.testN" instead of just the key) - Add workspace job result status checking after join to properly propagate setup errors - Increase build iterations from 2 to 3 for more reliable annotation processor output generation on all platforms --- .../tests/WorkspaceSetupExtension.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/WorkspaceSetupExtension.java b/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/WorkspaceSetupExtension.java index 703b1dab601..13d423dfd59 100644 --- a/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/WorkspaceSetupExtension.java +++ b/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/WorkspaceSetupExtension.java @@ -1,6 +1,5 @@ package org.eclipse.pde.ds.internal.annotations.tests; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -55,7 +54,8 @@ public void beforeAll(ExtensionContext context) throws Exception { Job wsJob = new WorkspaceJob("Test Workspace Setup") { @Override public IStatus runInWorkspace(IProgressMonitor m) throws CoreException { - SubMonitor monitor = SubMonitor.convert(m, PROJECTS.size() * 8); + // Per project: create(1) + open(1) + 3*(build(2) + refresh(1)) = 11 + SubMonitor monitor = SubMonitor.convert(m, PROJECTS.size() * 11); // import test projects Path wsRoot = ws.getRoot().getLocation().toPath(); for (Map.Entry entry : PROJECTS.entrySet()) { @@ -64,16 +64,17 @@ public IStatus runInWorkspace(IProgressMonitor m) throws CoreException { Path projectLocation = Files.createDirectories(wsRoot.resolve(project.getName())); copyResources(bundle, entry.getValue(), projectLocation); Files.createDirectories(projectLocation.resolve("OSGI-INF")); - File projectFile = projectLocation.resolve("test.project").toFile(); - if (projectFile.isFile()) { - projectFile.renameTo(projectLocation.resolve(".project").toFile()); + Path projectFile = projectLocation.resolve("test.project"); + if (Files.isRegularFile(projectFile)) { + Files.move(projectFile, projectLocation.resolve(".project"), + StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { throw new CoreException(Status.error("Error copying test project content.", e)); } project.create(monitor.split(1)); project.open(monitor.split(1)); - for (int i = 0; i < 2; i++) { // Build twice. Sometimes the setup is unstable + for (int i = 0; i < 3; i++) { // Annotation processor may need multiple builds to generate all outputs project.build(IncrementalProjectBuilder.FULL_BUILD, monitor.split(2)); project.refreshLocal(IResource.DEPTH_INFINITE, monitor.split(1)); } @@ -84,6 +85,10 @@ public IStatus runInWorkspace(IProgressMonitor m) throws CoreException { wsJob.schedule(); wsJob.join(); + IStatus result = wsJob.getResult(); + if (result != null && !result.isOK()) { + throw new CoreException(result); + } } @Override @@ -97,7 +102,7 @@ public void afterAll(ExtensionContext context) throws Exception { @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { for (String projectId : PROJECTS.keySet()) { - IProject project = wsRoot.getProject("ds.annotations." + projectId); + IProject project = wsRoot.getProject(projectId); if (project.exists()) { project.delete(true, true, monitor); } From b1b27be887150414ec8e8bf4e4d20883d184560a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 09:23:44 +0100 Subject: [PATCH 4/4] Fix manifestHeaderServiceComponentAdded test on macOS and Windows Fix manifestHeaderServiceComponentAdded test to read MANIFEST.MF directly The test was using PluginRegistry.findModel() which returns a cached in-memory model that may not reflect the updated MANIFEST.MF after the DS annotation builder writes the Service-Component header. On macOS and Windows, the model manager's resource change event processing can lag behind the file changes, causing the test to read stale data. Fix by reading the MANIFEST.MF file directly using java.util.jar.Manifest, with refreshLocal() before reading, consistent with how other DS annotation tests (AnnotationProcessorTest) read their test files. --- .../annotations/tests/ManagedProjectTest.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/ManagedProjectTest.java b/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/ManagedProjectTest.java index bcadcb2c37e..a47e46b9182 100644 --- a/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/ManagedProjectTest.java +++ b/ds/org.eclipse.pde.ds.annotations.tests/src/org/eclipse/pde/ds/internal/annotations/tests/ManagedProjectTest.java @@ -1,21 +1,19 @@ package org.eclipse.pde.ds.internal.annotations.tests; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.io.InputStream; import java.util.Arrays; import java.util.List; +import java.util.jar.Manifest; import org.eclipse.core.resources.ICommand; +import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; -import org.eclipse.pde.core.plugin.IPluginModelBase; -import org.eclipse.pde.core.plugin.PluginRegistry; import org.eclipse.pde.ds.internal.annotations.DSAnnotationCompilationParticipant; -import org.eclipse.pde.internal.core.ibundle.IBundleModel; -import org.eclipse.pde.internal.core.ibundle.IBundlePluginModelBase; import org.junit.jupiter.api.Test; @SuppressWarnings("restriction") @@ -45,11 +43,14 @@ public void folderOSGIInfCreated() throws Exception { @Test public void manifestHeaderServiceComponentAdded() throws Exception { - IPluginModelBase pluginModel = PluginRegistry.findModel(testProject); - assertThat(pluginModel).isInstanceOf(IBundlePluginModelBase.class); - IBundleModel bundleModel = ((IBundlePluginModelBase) pluginModel).getBundleModel(); - assertNotNull(bundleModel, "Missing bundle manifest!"); - String serviceComponentHeader = bundleModel.getBundle().getHeader("Service-Component"); + IFile manifestFile = testProject.getFile("META-INF/MANIFEST.MF"); + manifestFile.refreshLocal(IResource.DEPTH_ZERO, null); + assertTrue(manifestFile.exists(), "Missing MANIFEST.MF!"); + String serviceComponentHeader; + try (InputStream is = manifestFile.getContents(true)) { + Manifest manifest = new Manifest(is); + serviceComponentHeader = manifest.getMainAttributes().getValue("Service-Component"); + } assertNotNull(serviceComponentHeader, "Missing Service-Component header!"); String[] entries = serviceComponentHeader.split("\\s*,\\s*"); List entryList = Arrays.asList(entries);