Skip to content

Commit e86d7f2

Browse files
tobias-melchertobiasmelcher
authored andcommitted
Simplify SourceViewer#computeStyleRanges() and fix finally-block
partitioner restore
1 parent 1fc9f09 commit e86d7f2

2 files changed

Lines changed: 72 additions & 40 deletions

File tree

bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,72 +1426,73 @@ private void uninstallTextViewer() {
14261426
* </p>
14271427
*
14281428
* @param document the external document whose content should be highlighted; must not be
1429-
* {@code null} and must use the same language/content type as this viewer
1429+
* {@code null} and must use the same language/content type as this viewer; must
1430+
* implement {@link org.eclipse.jface.text.IDocumentExtension3} — if either
1431+
* {@code document} or the viewer's current document does not implement
1432+
* {@code IDocumentExtension3}, an empty list is returned
14301433
* @param region the region within {@code document} for which style ranges are computed; must
14311434
* not be {@code null}
14321435
* @return the list of {@link org.eclipse.swt.custom.StyleRange}s covering the given region, as
14331436
* produced by this viewer's presentation reconciler; never {@code null}, may be empty
1434-
* if no repairer is registered for the content type
1437+
* if no repairer is registered for the content type, or if either document does not
1438+
* implement {@code IDocumentExtension3}
14351439
* @throws BadLocationException if {@code region} is outside the bounds of {@code document}
14361440
* @since 3.31
14371441
*/
14381442
public List<StyleRange> computeStyleRanges(IDocument document, IRegion region) throws BadLocationException {
14391443
Assert.isTrue(Display.getCurrent() != null, "computeStyleRanges must be called from SWT UI thread"); //$NON-NLS-1$
14401444
IDocument originalDocument= getDocument();
14411445
Assert.isNotNull(originalDocument, "viewer must have a document before calling computeStyleRanges"); //$NON-NLS-1$
1442-
String partition= IDocumentExtension3.DEFAULT_PARTITIONING;
1446+
List<StyleRange> result= new ArrayList<>();
1447+
String partitioning= IDocumentExtension3.DEFAULT_PARTITIONING;
14431448
IPresentationReconciler reconciler= fPresentationReconciler;
14441449
if (reconciler instanceof IPresentationReconcilerExtension ext) {
1445-
String extPartition= ext.getDocumentPartitioning();
1446-
if (extPartition != null && !extPartition.isEmpty()) {
1447-
partition= extPartition;
1450+
String extPartitioning= ext.getDocumentPartitioning();
1451+
if (extPartitioning != null && !extPartitioning.isEmpty()) {
1452+
partitioning= extPartitioning;
14481453
}
14491454
}
14501455
IDocumentPartitioner originalDocumentPartitioner= null;
14511456
IDocumentExtension3 documentExt= null;
14521457
if (document instanceof IDocumentExtension3 docExt
14531458
&& originalDocument instanceof IDocumentExtension3 originalExt) {
14541459
documentExt= docExt;
1455-
originalDocumentPartitioner= originalExt.getDocumentPartitioner(partition);
1460+
originalDocumentPartitioner= originalExt.getDocumentPartitioner(partitioning);
1461+
} else {
1462+
return result;
14561463
}
14571464
IDocumentPartitioner externalDocPartitioner= null;
14581465
try {
1459-
if (originalDocumentPartitioner != null && documentExt != null) {
1460-
// Temporarily reconnect the partitioner to the external document so that
1461-
// presentation repairers compute highlighting against the right content.
1462-
// The finally block always restores both documents to their original state.
1463-
externalDocPartitioner= documentExt.getDocumentPartitioner(partition);
1466+
// Temporarily reconnect the partitioner to the external document so that
1467+
// presentation repairers compute highlighting against the right content.
1468+
// The finally block always restores both documents to their original state.
1469+
externalDocPartitioner= documentExt.getDocumentPartitioner(partitioning);
1470+
if (originalDocumentPartitioner != null) {
14641471
originalDocumentPartitioner.disconnect();
14651472
originalDocumentPartitioner.connect(document);
1466-
documentExt.setDocumentPartitioner(partition, originalDocumentPartitioner);
1467-
} else {
1468-
externalDocPartitioner= document.getDocumentPartitioner();
1469-
document.setDocumentPartitioner(originalDocument.getDocumentPartitioner());
1473+
documentExt.setDocumentPartitioner(partitioning, originalDocumentPartitioner);
14701474
}
1471-
TextPresentation presentation= new TextPresentation(region, 1000);
1472-
ITypedRegion[] partitioning= TextUtilities.computePartitioning(document, partition, region.getOffset(),
1475+
TextPresentation presentation= new TextPresentation(region, Math.max(region.getLength() / 10, 16));
1476+
ITypedRegion[] partitioningRegions= TextUtilities.computePartitioning(document, partitioning, region.getOffset(),
14731477
region.getLength(), false);
1474-
for (ITypedRegion r : partitioning) {
1475-
IPresentationRepairer repairer= reconciler.getRepairer(r.getType());
1478+
for (ITypedRegion partitioningRegion : partitioningRegions) {
1479+
IPresentationRepairer repairer= reconciler.getRepairer(partitioningRegion.getType());
14761480
if (repairer != null) {
14771481
repairer.setDocument(document);
1478-
repairer.createPresentation(presentation, r);
1482+
repairer.createPresentation(presentation, partitioningRegion);
14791483
repairer.setDocument(originalDocument);
14801484
}
14811485
}
1482-
List<StyleRange> result= new ArrayList<>();
14831486
var it= presentation.getAllStyleRangeIterator();
14841487
while (it.hasNext()) {
14851488
result.add(it.next());
14861489
}
14871490
return result;
14881491
} finally {
1489-
if (originalDocumentPartitioner != null && documentExt != null) {
1492+
if (originalDocumentPartitioner != null) {
14901493
originalDocumentPartitioner.disconnect();
14911494
originalDocumentPartitioner.connect(originalDocument);
1492-
documentExt.setDocumentPartitioner(partition, externalDocPartitioner);
1493-
} else {
1494-
document.setDocumentPartitioner(externalDocPartitioner);
1495+
documentExt.setDocumentPartitioner(partitioning, externalDocPartitioner);
14951496
}
14961497
}
14971498
}

tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/source/SourceViewerComputeStyleRangesTest.java

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import static org.junit.jupiter.api.Assertions.assertNull;
1717
import static org.junit.jupiter.api.Assertions.assertThrows;
1818
import static org.junit.jupiter.api.Assertions.assertTrue;
19+
import static org.mockito.Mockito.mock;
1920

2021
import java.util.List;
2122

@@ -32,6 +33,7 @@
3233
import org.eclipse.jface.text.BadLocationException;
3334
import org.eclipse.jface.text.Document;
3435
import org.eclipse.jface.text.IDocument;
36+
import org.eclipse.jface.text.IDocumentExtension3;
3537
import org.eclipse.jface.text.IDocumentPartitioner;
3638
import org.eclipse.jface.text.Region;
3739
import org.eclipse.jface.text.TextAttribute;
@@ -74,7 +76,9 @@ public void tearDown() {
7476
@Test
7577
public void testBasicStyleRanges() throws Exception {
7678
SourceViewer viewer= createConfiguredViewer();
77-
viewer.setDocument(new Document("original content"));
79+
var document= new Document("original content");
80+
setupDefaultPartitioning(document);
81+
viewer.setDocument(document);
7882

7983
Document externalDoc= new Document("some 'highlighted' text");
8084
List<StyleRange> styles= viewer.computeStyleRanges(externalDoc, new Region(0, externalDoc.getLength()));
@@ -91,7 +95,9 @@ public void testBasicStyleRanges() throws Exception {
9195
@Test
9296
public void testNoMatchingContent() throws Exception {
9397
SourceViewer viewer= createConfiguredViewer();
94-
viewer.setDocument(new Document("original content"));
98+
var document= new Document("original content");
99+
setupDefaultPartitioning(document);
100+
viewer.setDocument(document);
95101

96102
Document externalDoc= new Document("no special content here");
97103
List<StyleRange> styles= viewer.computeStyleRanges(externalDoc, new Region(0, externalDoc.getLength()));
@@ -107,7 +113,9 @@ public void testNoMatchingContent() throws Exception {
107113
@Test
108114
public void testRegionSubset() throws Exception {
109115
SourceViewer viewer= createConfiguredViewer();
110-
viewer.setDocument(new Document("original content"));
116+
var document= new Document("original content");
117+
setupDefaultPartitioning(document);
118+
viewer.setDocument(document);
111119

112120
// Put quoted text at position 10..22
113121
Document externalDoc= new Document("0123456789'highlighted'rest");
@@ -129,28 +137,31 @@ public void testOriginalDocumentNotAffected() throws Exception {
129137
SourceViewer viewer= createConfiguredViewer();
130138
String originalContent= "original content";
131139
Document originalDoc= new Document(originalContent);
132-
IDocumentPartitioner originalPartitioner= setupPartitioning(originalDoc);
140+
IDocumentPartitioner originalPartitioner= setupDefaultPartitioning(originalDoc);
133141
assertNotNull(originalPartitioner);
134142
viewer.setDocument(originalDoc);
135143

136144
Document externalDoc= new Document("some 'highlighted' text");
137-
IDocumentPartitioner externalPartitioner= setupPartitioning(externalDoc);
145+
IDocumentPartitioner externalPartitioner= setupDefaultPartitioning(externalDoc);
138146
assertNotNull(externalPartitioner);
139147
viewer.computeStyleRanges(externalDoc, new Region(0, externalDoc.getLength()));
140148

141149
assertEquals(originalContent, originalDoc.get(), "Original document content must not change");
142-
assertEquals(originalPartitioner, originalDoc.getDocumentPartitioner(),
150+
assertEquals(originalPartitioner, originalDoc.getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING),
143151
"Original document partitioner must be restored");
144-
assertEquals(externalPartitioner, externalDoc.getDocumentPartitioner(),
152+
assertEquals(externalPartitioner, externalDoc.getDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING),
145153
"External document partitioner must be restored");
146154
}
147155

148156
@Test
149157
public void testEmptyRegion() throws Exception {
150-
SourceViewer viewer= createConfiguredViewer();
151-
viewer.setDocument(new Document("original content"));
158+
SourceViewer viewer= createConfiguredViewerWithNamedPartitioning();
159+
var document= new Document("original content");
160+
setupNamedPartitioning(document);
161+
viewer.setDocument(document);
152162

153163
Document externalDoc= new Document("some 'highlighted' text");
164+
setupNamedPartitioning(externalDoc);
154165
List<StyleRange> styles= viewer.computeStyleRanges(externalDoc, new Region(0, 0));
155166

156167
assertNotNull(styles);
@@ -163,8 +174,10 @@ public void testEmptyRegion() throws Exception {
163174

164175
@Test
165176
public void testMultipleStyleRanges() throws Exception {
166-
SourceViewer viewer= createConfiguredViewer();
167-
viewer.setDocument(new Document("original content"));
177+
SourceViewer viewer= createConfiguredViewerWithNamedPartitioning();
178+
var document= new Document("original content");
179+
setupNamedPartitioning(document);
180+
viewer.setDocument(document);
168181

169182
Document externalDoc= new Document("'first' normal 'second' end");
170183
List<StyleRange> styles= viewer.computeStyleRanges(externalDoc, new Region(0, externalDoc.getLength()));
@@ -179,7 +192,9 @@ public void testMultipleStyleRanges() throws Exception {
179192
@Test
180193
public void testBadLocationExceptionForOutOfBoundsRegion() throws Exception {
181194
SourceViewer viewer= createConfiguredViewer();
182-
viewer.setDocument(new Document("original content"));
195+
var document= new Document("original content");
196+
setupDefaultPartitioning(document);
197+
viewer.setDocument(document);
183198

184199
Document externalDoc= new Document("short");
185200
assertThrows(BadLocationException.class,
@@ -248,6 +263,22 @@ public void testNamedPartitioning() throws Exception {
248263
assertEquals(externalPartitioner, restoredExternalPartitioner);
249264
}
250265

266+
@Test
267+
public void testNonDocumentExtension3ReturnsEmpty() throws Exception {
268+
SourceViewer viewer= createConfiguredViewer();
269+
Document originalDoc= new Document("original content");
270+
setupDefaultPartitioning(originalDoc);
271+
viewer.setDocument(originalDoc);
272+
273+
// Create a document that does NOT implement IDocumentExtension3
274+
// so that computeStyleRanges takes the early-return path
275+
IDocument document= mock(IDocument.class);
276+
List<StyleRange> styles= viewer.computeStyleRanges(document, new Region(0, document.getLength()));
277+
278+
assertNotNull(styles);
279+
assertTrue(styles.isEmpty(), "Expected empty style ranges for non-IDocumentExtension3 document");
280+
}
281+
251282
private SourceViewer createConfiguredViewer() {
252283
SourceViewer viewer= new SourceViewer(shell, null, SWT.NONE);
253284
viewer.configure(new SourceViewerConfiguration() {
@@ -297,10 +328,10 @@ private IDocumentPartitioner setupNamedPartitioning(Document document) {
297328
return partitioner;
298329
}
299330

300-
private IDocumentPartitioner setupPartitioning(Document document) {
331+
private IDocumentPartitioner setupDefaultPartitioning(Document document) {
301332
IPartitionTokenScanner partitionScanner= new RuleBasedPartitionScanner();
302333
IDocumentPartitioner partitioner= new FastPartitioner(partitionScanner, new String[] {});
303-
document.setDocumentPartitioner(partitioner);
334+
document.setDocumentPartitioner(IDocumentExtension3.DEFAULT_PARTITIONING, partitioner);
304335
partitioner.connect(document);
305336
return partitioner;
306337
}

0 commit comments

Comments
 (0)