Skip to content

Conversation

@danthe1st
Copy link
Contributor

@danthe1st danthe1st commented Oct 26, 2025

When collapsing projection regions and then setting the visible region in a certain way and then changing it to the surrounding visible region, it is possible that consecutive ProjectionMapping#toImageLine calls throw an IllegalStateException. This is because ProjectionDocument#internalRemoveMasterDocumentRange adds a Position to the document when a Position with the same offset but a length of 0 can be present already. In this case, ISynchronizableDocument#addPosition (which is supposed to insert it into the sorted array) might insert it before the Position resulting in the fragments being sorted incorrectly (the 0-length fragment after the positive-length fragment with both having the same offset). This can then result in IllegalStateExceptions when calling ProjectionMapping#toImageLine (which happens while drawing line numbers for example).

A similar issue also happens in ProjectionDocument#internalAddMasterDocumentRange. There, it is possible that a region is expanded to the right in a way that it fully surrounds the region on the right. While expansion is normally handled by Segments (ranges in the slave document), the Fragments are not correctly reordered in this case causing computeProjectedMasterRegions(int offsetInMaster, int lengthInMaster) not finding the region (at least that's what happened with my reproducer) and hence not being able to remove it from the editor. In the situation where one Fragment includes (is a "superset" of) another, it should be safe to delete the smaller one fixing the invalid state.

This change fixes these problems.

Standalone reproducer/test

To reproduce the issue, run the test added with this PR without the changes to ProjectionDocument.
Without the fix, the tests throw exceptions similar to the following:

java.lang.IllegalStateException: startLine (6) does not match endLine (12)
	at org.eclipse.jface.text.projection.ProjectionMapping.toImageLine(ProjectionMapping.java:482)
	at org.eclipse.jface.text.tests.ProjectionViewerTest.testImageLineStateAfterSettingVisibleRegionsWithProjectionsSetMethodAndClass(ProjectionViewerTest.java:483)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

and

org.opentest4j.AssertionFailedError: expected: <-1> but was: <8>
	at org.junit.jupiter.api.AssertionFailureBuilder.build(AssertionFailureBuilder.java:151)
	at org.junit.jupiter.api.AssertionFailureBuilder.buildAndThrow(AssertionFailureBuilder.java:132)
	at org.junit.jupiter.api.AssertEquals.failNotEqual(AssertEquals.java:197)
	at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:150)
	at org.junit.jupiter.api.AssertEquals.assertEquals(AssertEquals.java:145)
	at org.junit.jupiter.api.Assertions.assertEquals(Assertions.java:531)
	at org.eclipse.jface.text.tests.ProjectionViewerTest.testImageLineStateAfterSettingVisibleRegionsWithProjectionsSetDifferentMethods(ProjectionViewerTest.java:543)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)

Reproducing with JDT (patch)

This can be reproduced with JDT using the code from this PR I wrote following these steps:

  • Enable Window > Preferences > Java > Editor > Only show the selected Java element and folding in Window > Preferences > Java > Editor > Folding
  • Create the following class:
package test;

public class TM {
	void a() {
		
	}
	
	void b() {
		
	}
	
	void c() {
		
	}
}
  • Collapse the b() method
  • Select a() in the outline (does not happen with the other methods) to only show that method
  • Select the TM class in the outline
  • The following exception occurs and line numbers break:
!ENTRY org.eclipse.ui 4 0 2025-10-26 11:10:59.431
!MESSAGE Unhandled event loop exception
!STACK 0
java.lang.IllegalStateException: startLine (6) does not match endLine (12)
	at org.eclipse.jface.text.projection.ProjectionMapping.toImageLine(ProjectionMapping.java:482)
	at org.eclipse.jface.text.TextViewer.modelLine2WidgetLine(TextViewer.java:5397)
	at org.eclipse.jface.text.JFaceTextUtil.modelLineToWidgetLine(JFaceTextUtil.java:254)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.doPaint(LineNumberRulerColumn.java:728)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.doubleBufferPaint(LineNumberRulerColumn.java:703)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.lambda$2(LineNumberRulerColumn.java:616)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:268)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5889)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1656)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1682)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1665)
	at org.eclipse.swt.widgets.Control.gtk_draw(Control.java:3902)
	at org.eclipse.swt.widgets.Scrollable.gtk_draw(Scrollable.java:394)
	at org.eclipse.swt.widgets.Composite.gtk_draw(Composite.java:507)
	at org.eclipse.swt.widgets.Canvas.gtk_draw(Canvas.java:173)
	at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2614)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:6868)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:6196)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_do_event(Native Method)
	at org.eclipse.swt.widgets.Display.eventProc(Display.java:1624)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_iteration_do(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4542)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1147)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1038)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:677)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1387)

!ENTRY org.eclipse.ui 4 0 2025-10-26 11:11:02.394
!MESSAGE Unhandled event loop exception
!STACK 0
java.lang.IllegalStateException: startLine (6) does not match endLine (12)
	at org.eclipse.jface.text.projection.ProjectionMapping.toImageLine(ProjectionMapping.java:482)
	at org.eclipse.jface.text.TextViewer.modelLine2WidgetLine(TextViewer.java:5397)
	at org.eclipse.jface.text.JFaceTextUtil.modelLineToWidgetLine(JFaceTextUtil.java:254)
	at org.eclipse.jface.internal.text.source.DiffPainter.paintLine(DiffPainter.java:220)
	at org.eclipse.jface.internal.text.source.DiffPainter.paint(DiffPainter.java:160)
	at org.eclipse.jface.text.source.LineNumberChangeRulerColumn.doPaint(LineNumberChangeRulerColumn.java:181)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.lambda$6(LineNumberRulerColumn.java:712)
	at org.eclipse.swt.graphics.Image.drawWithImageGcDrawer(Image.java:1179)
	at org.eclipse.swt.graphics.Image.<init>(Image.java:705)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.newFullBufferImage(LineNumberRulerColumn.java:714)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.doubleBufferPaint(LineNumberRulerColumn.java:701)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.lambda$2(LineNumberRulerColumn.java:616)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:268)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5889)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1656)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1682)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1665)
	at org.eclipse.swt.widgets.Control.gtk_draw(Control.java:3902)
	at org.eclipse.swt.widgets.Scrollable.gtk_draw(Scrollable.java:394)
	at org.eclipse.swt.widgets.Composite.gtk_draw(Composite.java:507)
	at org.eclipse.swt.widgets.Canvas.gtk_draw(Canvas.java:173)
	at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2614)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:6868)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:6196)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_do_event(Native Method)
	at org.eclipse.swt.widgets.Display.eventProc(Display.java:1624)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_iteration_do(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4542)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1147)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1038)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:677)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1387)

!ENTRY org.eclipse.ui 4 0 2025-10-26 11:11:04.136
!MESSAGE Unhandled event loop exception
!STACK 0
java.lang.IllegalStateException: startLine (6) does not match endLine (12)
	at org.eclipse.jface.text.projection.ProjectionMapping.toImageLine(ProjectionMapping.java:482)
	at org.eclipse.jface.text.TextViewer.modelLine2WidgetLine(TextViewer.java:5397)
	at org.eclipse.jface.text.JFaceTextUtil.modelLineToWidgetLine(JFaceTextUtil.java:254)
	at org.eclipse.jface.internal.text.source.DiffPainter.paintLine(DiffPainter.java:220)
	at org.eclipse.jface.internal.text.source.DiffPainter.paint(DiffPainter.java:160)
	at org.eclipse.jface.text.source.LineNumberChangeRulerColumn.doPaint(LineNumberChangeRulerColumn.java:181)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.lambda$6(LineNumberRulerColumn.java:712)
	at org.eclipse.swt.graphics.Image.drawWithImageGcDrawer(Image.java:1179)
	at org.eclipse.swt.graphics.Image.<init>(Image.java:705)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.newFullBufferImage(LineNumberRulerColumn.java:714)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.doubleBufferPaint(LineNumberRulerColumn.java:701)
	at org.eclipse.jface.text.source.LineNumberRulerColumn.lambda$2(LineNumberRulerColumn.java:616)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:268)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:91)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:5889)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1656)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1682)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1665)
	at org.eclipse.swt.widgets.Control.gtk_draw(Control.java:3902)
	at org.eclipse.swt.widgets.Scrollable.gtk_draw(Scrollable.java:394)
	at org.eclipse.swt.widgets.Composite.gtk_draw(Composite.java:507)
	at org.eclipse.swt.widgets.Canvas.gtk_draw(Canvas.java:173)
	at org.eclipse.swt.widgets.Widget.windowProc(Widget.java:2614)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:6868)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:6196)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_do_event(Native Method)
	at org.eclipse.swt.widgets.Display.eventProc(Display.java:1624)
	at org.eclipse.swt.internal.gtk3.GTK3.gtk_main_iteration_do(Native Method)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:4542)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$5.run(PartRenderingEngine.java:1147)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1038)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:153)
	at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:677)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:339)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:583)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:173)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:185)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:219)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:149)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:115)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:467)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:298)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:565)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:615)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:563)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1415)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1387)
  • If you don't select the TM class in the outline but instead the b() method, the c() method will be shown incorrectly.

@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch from 8067f5c to 883f03e Compare October 26, 2025 10:25
@github-actions
Copy link
Contributor

github-actions bot commented Oct 26, 2025

Test Results

 3 018 files  ±0   3 018 suites  ±0   2h 16m 39s ⏱️ + 3m 59s
 8 244 tests +2   7 996 ✅ +3  248 💤 ±0  0 ❌  - 1 
23 652 runs  +6  22 861 ✅ +7  791 💤 ±0  0 ❌  - 1 

Results for commit 3cee614. ± Comparison against base commit 26ddd0d.

♻️ This comment has been updated with latest results.

@danthe1st
Copy link
Contributor Author

danthe1st commented Oct 26, 2025

Test failures might be #2708 (comment) and #1517

@danthe1st
Copy link
Contributor Author

danthe1st commented Oct 27, 2025

Even with the fix, it seems there is still an issue with the JDT syntax highlighting breaking. As I don't know what causes this issue/#3455, I am marking this PR as a draft for now.

This is actually (at least partially) fixed by #3457 (not sure why and it wasn't intentional but if it works, it works). However, it is still a bit weird in my tests so I'm keeping it as a draft.

@danthe1st danthe1st marked this pull request as ready for review October 27, 2025 17:51
@danthe1st danthe1st marked this pull request as draft October 27, 2025 18:00
@iloveeclipse iloveeclipse force-pushed the projection-visible-region-imageLine-exception branch from 883f03e to dde2668 Compare October 30, 2025 21:13
@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch 2 times, most recently from 5041a5d to 17cd4dd Compare November 1, 2025 11:27
@danthe1st danthe1st marked this pull request as ready for review November 1, 2025 12:19
@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch 2 times, most recently from 1b4b381 to c8b2d47 Compare November 1, 2025 12:23
@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch from c8b2d47 to ae256ad Compare December 15, 2025 10:45
@eclipse-platform-bot
Copy link
Contributor

eclipse-platform-bot commented Dec 15, 2025

This pull request changes some projects for the first time in this development cycle.
Therefore the following files need a version increment:

bundles/org.eclipse.text/META-INF/MANIFEST.MF

An additional commit containing all the necessary changes was pushed to the top of this PR's branch. To obtain these changes (for example if you want to push more changes) either fetch from your fork or apply the git patch.

Git patch
From a0200d41ae1009eeb20a9a443e5bb6bcb653c4c6 Mon Sep 17 00:00:00 2001
From: Eclipse Platform Bot <platform-bot@eclipse.org>
Date: Mon, 15 Dec 2025 12:27:08 +0000
Subject: [PATCH] Version bump(s) for 4.39 stream


diff --git a/bundles/org.eclipse.text/META-INF/MANIFEST.MF b/bundles/org.eclipse.text/META-INF/MANIFEST.MF
index a247d39b79..516af6ca8a 100644
--- a/bundles/org.eclipse.text/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.text/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.text
-Bundle-Version: 3.14.500.qualifier
+Bundle-Version: 3.14.600.qualifier
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Export-Package: 
-- 
2.52.0

Further information are available in Common Build Issues - Missing version increments.

@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch from 94e8ec5 to 0b67a7f Compare December 15, 2025 12:17
@danthe1st danthe1st force-pushed the projection-visible-region-imageLine-exception branch from 6b907a8 to bc02784 Compare December 15, 2025 12:22
@danthe1st
Copy link
Contributor Author

@iloveeclipse Would you or someone else like to review this and #3585?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants