diff --git a/ui/org.eclipse.pde.ui/plugin.properties b/ui/org.eclipse.pde.ui/plugin.properties
index 66cb7c89f7..0279b9f863 100644
--- a/ui/org.eclipse.pde.ui/plugin.properties
+++ b/ui/org.eclipse.pde.ui/plugin.properties
@@ -158,6 +158,7 @@ rename.type.participant = Manifest Rename Type Participant
rename.package.participant = Manifest Rename Package Participant
move.type.participant = Manifest Move Type Participant
move.package.participant = Manifest Move Package Participant
+delete.type.participant = Manifest Delete Type Participant
queryParticipant.name.0 = PDE Java Search Participant
new.profile.name = Target Definition
diff --git a/ui/org.eclipse.pde.ui/plugin.xml b/ui/org.eclipse.pde.ui/plugin.xml
index 4a34c0b6ac..b8fba01309 100644
--- a/ui/org.eclipse.pde.ui/plugin.xml
+++ b/ui/org.eclipse.pde.ui/plugin.xml
@@ -1225,6 +1225,22 @@
+
+
+
+
+
+
+
+
+
+
();
+ fElements.put(element, type.getFullyQualifiedName());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getName() {
+ return PDEUIMessages.ManifestTypeDeleteParticipant_composite;
+ }
+
+ @Override
+ protected void addChange(CompositeChange result, IProgressMonitor pm) throws CoreException {
+ IFile file = PDEProject.getManifest(fProject);
+ if (!file.exists()) {
+ return;
+ }
+
+ Map> deletedByPackage = new HashMap<>();
+ fElements.forEach((element, fullyQualifiedName) -> {
+ if (element instanceof IType type) {
+ IPackageFragment pkg = type.getPackageFragment();
+ deletedByPackage.computeIfAbsent(pkg, k -> new ArrayList<>()).add(type);
+ }
+ });
+ // Check each package to see if it becomes empty after deletion
+ for (Map.Entry> entry : deletedByPackage.entrySet()) {
+ IPackageFragment pkg = entry.getKey();
+ List deletedTypes = entry.getValue();
+
+ try {
+ if (willPackageBeEmpty(pkg, deletedTypes)) {
+ Change change = BundleManifestChange.createEmptyPackageChange(file, pkg.getElementName(), pm);
+ if (change != null) {
+ result.add(change);
+ }
+ }
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Checks if a package will be empty after deleting the specified types.
+ * @param pkg the package to check
+ * @param deletedTypes the types being deleted
+ * @return true if the package will be empty after deletion
+ * @throws CoreException if an error occurs accessing package contents
+ */
+ private boolean willPackageBeEmpty(IPackageFragment pkg, List deletedTypes) throws CoreException {
+ IJavaElement[] javaChildren = pkg.getChildren();
+ if (javaChildren.length > deletedTypes.size()) {
+ return false;
+ }
+ // Check for non-Java resources (properties files, XML files, etc.)
+ Object[] nonJavaResources = pkg.getNonJavaResources();
+ if (nonJavaResources != null && nonJavaResources.length > 0) {
+ return false;
+ }
+
+ Set deletedJavaFileNames = new HashSet<>();
+ for (IType type : deletedTypes) {
+ // Get the compilation unit (the .java file) containing this type
+ if (type.getCompilationUnit() != null) {
+ deletedJavaFileNames.add(type.getCompilationUnit().getElementName());
+ }
+ }
+ // Check the underlying folder for any OTHER files
+ IResource resource = pkg.getCorrespondingResource();
+ if (resource instanceof IFolder folder) {
+ IResource[] members = folder.members();
+ for (IResource member : members) {
+ if (member instanceof IFile memberFile) {
+ String fileName = memberFile.getName();
+ String extension = memberFile.getFileExtension();
+ if ("class".equals(extension)) { //$NON-NLS-1$
+ continue;
+ }
+ if ("java".equals(extension) && deletedJavaFileNames.contains(fileName)) { //$NON-NLS-1$
+ continue;
+ }
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/refactoring/PDEDeleteParticipant.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/refactoring/PDEDeleteParticipant.java
new file mode 100644
index 0000000000..361bb872f1
--- /dev/null
+++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/refactoring/PDEDeleteParticipant.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * Copyright (c) 2026 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.internal.ui.refactoring;
+
+import java.util.HashMap;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.DeleteParticipant;
+import org.eclipse.ltk.core.refactoring.participants.ISharableParticipant;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
+
+public abstract class PDEDeleteParticipant extends DeleteParticipant implements ISharableParticipant {
+
+ protected IProject fProject;
+ protected HashMap