diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java index 2674b836fe8..b59ed29c4ba 100644 --- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java +++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java @@ -163,7 +163,9 @@ public void documentAboutToBeChanged(DocumentEvent event) { @Override public void documentChanged(DocumentEvent event) { - // Do nothing + if (endOffset != null && event != null && event.fDocument != null && event.fDocument.getLength() > endOffset) { + endOffset= null; + } } @Override diff --git a/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF index 74a27a2c7f8..506d79157e6 100644 --- a/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF +++ b/tests/org.eclipse.ui.editors.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Plugin.name Bundle-SymbolicName: org.eclipse.ui.editors.tests;singleton:=true -Bundle-Version: 3.13.600.qualifier +Bundle-Version: 3.13.700.qualifier Bundle-Vendor: %Plugin.providerName Bundle-Localization: plugin Export-Package: org.eclipse.jface.text.tests.codemining, diff --git a/tests/org.eclipse.ui.editors.tests/plugin.xml b/tests/org.eclipse.ui.editors.tests/plugin.xml index c43805fae01..4d8159a5c94 100644 --- a/tests/org.eclipse.ui.editors.tests/plugin.xml +++ b/tests/org.eclipse.ui.editors.tests/plugin.xml @@ -22,4 +22,14 @@ id="org.eclipse.jface.text.tests.codemining.CodeMiningTestProvider"> - \ No newline at end of file + + + + + diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTest.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTest.java index d91521f50f0..558572147f0 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTest.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTest.java @@ -13,6 +13,7 @@ import java.io.ByteArrayInputStream; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.HashMap; import java.util.concurrent.Callable; import org.junit.After; @@ -41,8 +42,12 @@ import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.ISourceViewerExtension5; +import org.eclipse.jface.text.source.projection.ProjectionAnnotation; +import org.eclipse.jface.text.source.projection.ProjectionViewer; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; @@ -100,6 +105,60 @@ public void run(IProgressMonitor monitor) throws CoreException { }, new NullProgressMonitor()); } + @Test + public void testInlinedAnnotationSupportIsInLinesReturnsValidResultAfterDocumentChange() throws Exception { + IFile file = project.getFile("test.testprojectionviewer"); + if (file.exists()) { + file.delete(true, new NullProgressMonitor()); + } + String source = "first\nsecond\nthird\n"; + file.create(new ByteArrayInputStream(source.getBytes("UTF-8")), true, new NullProgressMonitor()); + CodeMiningTestProvider.provideHeaderMiningAtLine = 2; + CodeMiningTestProvider.lineHeaderMiningText = " first line header\n secone line header\n third line header"; + int offset = source.indexOf("second") + "second".length(); + IEditorPart editor = IDE.openEditor(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(), file); + drainEventQueue(); + ISourceViewer viewer = (ISourceViewer) editor.getAdapter(ITextViewer.class); + StyledText widget = viewer.getTextWidget(); + + var annotationModel = ((ProjectionViewer) viewer).getProjectionAnnotationModel(); + var deletionsArray = new Annotation[] {}; + var additions = new HashMap(); + ProjectionAnnotation annot = new ProjectionAnnotation(); + additions.put(annot, new Position(0, source.length())); + annotationModel.modifyAnnotations(deletionsArray, additions, null); + + Assert.assertTrue("Line header code mining above 3rd line not drawn", + waitForCondition(widget.getDisplay(), 2000, new Callable() { + @Override + public Boolean call() throws Exception { + try { + return existsPixelWithNonBackgroundColorAtLine(viewer, 2); + } catch (BadLocationException e) { + e.printStackTrace(); + return false; + } + } + })); + + IDocument doc = viewer.getDocument(); + widget.setCaretOffset(offset); + doc.replace(offset, 0, "\n insert text"); + drainEventQueue(); + Assert.assertTrue("Line header code mining above 4th line after inserting text not drawn", + waitForCondition(widget.getDisplay(), 2000, new Callable() { + @Override + public Boolean call() throws Exception { + try { + return existsPixelWithNonBackgroundColorAtLine(viewer, 3); + } catch (BadLocationException e) { + e.printStackTrace(); + return false; + } + } + })); + } + @Test public void testCodeMiningOnEmptyLine() throws Exception { IFile file = project.getFile("test.txt"); @@ -208,12 +267,17 @@ private static boolean existsPixelWithNonBackgroundColorAtLine(ITextViewer viewe lineLength = 0; } int verticalScroolBarWidth = viewer.getTextWidget().getVerticalBar().getThumbBounds().width; - Rectangle lineBounds = widget.getTextBounds(document.getLineOffset(line), - document.getLineOffset(line) + lineLength); + int lineOffset = document.getLineOffset(line); + Rectangle lineBounds = widget.getTextBounds(lineOffset, lineOffset + lineLength); + String lineStr = document.get(lineOffset, lineLength); Image image = new Image(widget.getDisplay(), widget.getSize().x, widget.getSize().y); try { GC gc = new GC(widget); gc.copyArea(image, 0, 0); + Point textExtent = gc.textExtent(lineStr); + if (lineBounds.height - textExtent.y > textExtent.y) { + lineBounds.height -= textExtent.y; + } gc.dispose(); ImageData imageData = image.getImageData(); for (int x = lineBounds.x + 1; x < image.getBounds().width - verticalScroolBarWidth diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTestProvider.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTestProvider.java index 60f5ff4ffee..c3f6072bd10 100644 --- a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTestProvider.java +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/CodeMiningTestProvider.java @@ -29,7 +29,7 @@ public class CodeMiningTestProvider extends AbstractCodeMiningProvider { public static int provideHeaderMiningAtLine = -1; public static int provideContentMiningAtOffset = -1; - + public static String lineHeaderMiningText; @Override public CompletableFuture> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) { @@ -42,6 +42,9 @@ public CompletableFuture> provideCodeMinings(ITextVi minings.add(new LineHeaderCodeMining(provideHeaderMiningAtLine, viewer.getDocument(), this) { @Override public String getLabel() { + if (lineHeaderMiningText != null) { + return lineHeaderMiningText; + } return "line header mining"; } }); diff --git a/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/TextProjectionTextEditor.java b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/TextProjectionTextEditor.java new file mode 100644 index 00000000000..ef5440709e7 --- /dev/null +++ b/tests/org.eclipse.ui.editors.tests/src/org/eclipse/jface/text/tests/codemining/TextProjectionTextEditor.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2024 SAP + * + * 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 + *******************************************************************************/ +package org.eclipse.jface.text.tests.codemining; + +import org.eclipse.swt.widgets.Composite; + +import org.eclipse.jface.text.source.ISourceViewer; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.projection.ProjectionSupport; +import org.eclipse.jface.text.source.projection.ProjectionViewer; + +import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor; + +public class TextProjectionTextEditor extends AbstractDecoratedTextEditor { + + @Override + protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + fAnnotationAccess = getAnnotationAccess(); + fOverviewRuler = createOverviewRuler(getSharedColors()); + ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), + styles); + getSourceViewerDecorationSupport(viewer); + return viewer; + } + + @Override + public void createPartControl(Composite parent) { + super.createPartControl(parent); + var projectionViewer = (ProjectionViewer) getSourceViewer(); + var projectionSupport = new ProjectionSupport(projectionViewer, getAnnotationAccess(), getSharedColors()); + projectionSupport.install(); + projectionViewer.enableProjection(); + } +} \ No newline at end of file