diff --git a/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/AllTargetEditorTests.java b/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/AllTargetEditorTests.java
index 7beaf403cd2..be0ea38fc39 100644
--- a/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/AllTargetEditorTests.java
+++ b/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/AllTargetEditorTests.java
@@ -20,7 +20,8 @@
@RunWith(Suite.class)
@SuiteClasses({ AttributeNameCompletionTests.class, AttributeValueCompletionTests.class, TagNameCompletionTests.class,
TagValueCompletionTests.class, Bug527084CompletionWithCommentsTest.class,
- Bug528706CompletionWithMultilineTagsTest.class, UpdateUnitVersionsCommandTests.class, Bug531602FormattingTests.class })
+ Bug528706CompletionWithMultilineTagsTest.class, UpdateUnitVersionsCommandTests.class, Bug531602FormattingTests.class,
+ TargetPlatformPresentationReconcilerTest.class })
public class AllTargetEditorTests {
}
diff --git a/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/TargetPlatformPresentationReconcilerTest.java b/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/TargetPlatformPresentationReconcilerTest.java
new file mode 100644
index 00000000000..e8c65f675b0
--- /dev/null
+++ b/ui/org.eclipse.pde.genericeditor.extension.tests/src/org/eclipse/pde/genericeditor/extension/tests/TargetPlatformPresentationReconcilerTest.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2026 vogella GmbH 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:
+ * Lars Vogel - initial implementation
+ *******************************************************************************/
+package org.eclipse.pde.genericeditor.extension.tests;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.presentation.IPresentationRepairer;
+import org.eclipse.pde.internal.genericeditor.target.extension.reconciler.presentation.TargetPlatformPresentationReconciler;
+import org.junit.Test;
+
+/**
+ * Tests for {@link TargetPlatformPresentationReconciler}.
+ *
+ * The reconciler overrides {@code createPresentation} to scan from offset 0
+ * so that multi-line rules (XML comments) are correctly recognised even when
+ * the damaged region is deep inside the document. These tests verify that the
+ * presentation is computed correctly for several representative document shapes
+ * and damage positions.
+ */
+public class TargetPlatformPresentationReconcilerTest {
+
+ /** Subclass that exposes the protected {@code createPresentation} for testing. */
+ private static class TestableReconciler extends TargetPlatformPresentationReconciler {
+ TextPresentation createPresentation(IDocument document, IRegion damage) {
+ IPresentationRepairer repairer = getRepairer(IDocument.DEFAULT_CONTENT_TYPE);
+ if (repairer != null) {
+ repairer.setDocument(document);
+ }
+ return createPresentation(damage, document);
+ }
+ }
+
+ @Test
+ public void testCreatePresentationReturnsNonNullForSimpleDocument() {
+ TestableReconciler reconciler = new TestableReconciler();
+ String content = "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + " \n" //$NON-NLS-1$
+ + "\n"; //$NON-NLS-1$
+ IDocument document = new Document(content);
+ IRegion damage = new Region(0, content.length());
+
+ TextPresentation presentation = reconciler.createPresentation(document, damage);
+
+ assertNotNull("Expected a non-null TextPresentation for a simple document", presentation); //$NON-NLS-1$
+ }
+
+ @Test
+ public void testCreatePresentationWithDamageSubsetOfDocument() {
+ TestableReconciler reconciler = new TestableReconciler();
+ String content = "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + " \n" //$NON-NLS-1$
+ + " \n" //$NON-NLS-1$
+ + "\n"; //$NON-NLS-1$
+ IDocument document = new Document(content);
+ // Damage is only the last few characters, not the full document.
+ int damageOffset = content.indexOf(""); //$NON-NLS-1$
+ IRegion damage = new Region(damageOffset, content.length() - damageOffset);
+
+ TextPresentation presentation = reconciler.createPresentation(document, damage);
+
+ assertNotNull("Expected a non-null TextPresentation when damage covers only end of document", presentation); //$NON-NLS-1$
+ }
+
+ @Test
+ public void testCreatePresentationWithMultilineCommentBeforeDamage() {
+ TestableReconciler reconciler = new TestableReconciler();
+ // Multi-line comment appears before the damage region. The reconciler must
+ // scan from offset 0 so it can correctly determine the scanner state
+ // (comment vs normal) at the start of the damage.
+ String content = "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + " \n" //$NON-NLS-1$
+ + "\n"; //$NON-NLS-1$
+ IDocument document = new Document(content);
+ // Damage is after the comment closes.
+ int damageOffset = content.indexOf(""); //$NON-NLS-1$
+ IRegion damage = new Region(damageOffset, content.length() - damageOffset);
+
+ TextPresentation presentation = reconciler.createPresentation(document, damage);
+
+ assertNotNull("Expected a non-null TextPresentation when a multi-line comment precedes the damage", //$NON-NLS-1$
+ presentation);
+ }
+
+ @Test
+ public void testCreatePresentationWithDamageInsideMultilineComment() {
+ TestableReconciler reconciler = new TestableReconciler();
+ String content = "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + "\n"; //$NON-NLS-1$
+ IDocument document = new Document(content);
+ // Damage is inside the comment body.
+ int damageOffset = content.indexOf(" line two"); //$NON-NLS-1$
+ IRegion damage = new Region(damageOffset, " line two\n".length()); //$NON-NLS-1$
+
+ TextPresentation presentation = reconciler.createPresentation(document, damage);
+
+ assertNotNull("Expected a non-null TextPresentation when damage is inside a multi-line comment", presentation); //$NON-NLS-1$
+ }
+}
diff --git a/ui/org.eclipse.pde.genericeditor.extension/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.genericeditor.extension/META-INF/MANIFEST.MF
index 0ee79b46b8d..845bd9df355 100644
--- a/ui/org.eclipse.pde.genericeditor.extension/META-INF/MANIFEST.MF
+++ b/ui/org.eclipse.pde.genericeditor.extension/META-INF/MANIFEST.MF
@@ -28,6 +28,6 @@ Export-Package: org.eclipse.pde.internal.genericeditor.target.extension.autocomp
org.eclipse.pde.internal.genericeditor.target.extension.model.xml;x-internal:=true,
org.eclipse.pde.internal.genericeditor.target.extension.p2;x-internal:=true,
org.eclipse.pde.internal.genericeditor.target.extension.reconciler.folding;x-internal:=true,
- org.eclipse.pde.internal.genericeditor.target.extension.reconciler.presentation;x-internal:=true,
+ org.eclipse.pde.internal.genericeditor.target.extension.reconciler.presentation;x-friends:="org.eclipse.pde.genericeditor.extension.tests",
org.eclipse.pde.internal.genericeditor.target.extension.validator;x-internal:=true
Automatic-Module-Name: org.eclipse.pde.genericeditor.extension
diff --git a/ui/org.eclipse.pde.genericeditor.extension/src/org/eclipse/pde/internal/genericeditor/target/extension/reconciler/presentation/TargetPlatformPresentationReconciler.java b/ui/org.eclipse.pde.genericeditor.extension/src/org/eclipse/pde/internal/genericeditor/target/extension/reconciler/presentation/TargetPlatformPresentationReconciler.java
index 1efa13de4af..2522208bd11 100644
--- a/ui/org.eclipse.pde.genericeditor.extension/src/org/eclipse/pde/internal/genericeditor/target/extension/reconciler/presentation/TargetPlatformPresentationReconciler.java
+++ b/ui/org.eclipse.pde.genericeditor.extension/src/org/eclipse/pde/internal/genericeditor/target/extension/reconciler/presentation/TargetPlatformPresentationReconciler.java
@@ -109,8 +109,11 @@ private void setDamageRepairerScanner() {
}
/**
- * Performs the repair on the full document to ensure MultiLineRules are
- * enforced
+ * Performs the repair from the start of the document up to and including the
+ * damaged region to ensure MultiLineRules (e.g. XML comments) are correctly
+ * recognised. Scanning stops at the damage end rather than the document end
+ * because the returned {@link TextPresentation} is bounded by {@code damage}
+ * anyway, so any style ranges beyond that point would be discarded.
*/
@Override
protected TextPresentation createPresentation(IRegion damage, IDocument document) {
@@ -118,8 +121,9 @@ protected TextPresentation createPresentation(IRegion damage, IDocument document
IPresentationRepairer repairer = this.getRepairer(IDocument.DEFAULT_CONTENT_TYPE);
if (repairer != null) {
try {
+ int scanEnd = Math.min(damage.getOffset() + damage.getLength(), document.getLength());
ITypedRegion[] regions = TextUtilities.computePartitioning(document, getDocumentPartitioning(), 0,
- document.getLength(), false);
+ scanEnd, false);
if (regions.length > 0) {
repairer.createPresentation(presentation, regions[0]);
return presentation;