1616import static org .eclipse .compare .unifieddiff .internal .UnifiedDiffManager .error ;
1717import static org .eclipse .compare .unifieddiff .internal .UnifiedDiffManager .isOverlay ;
1818
19- import java .lang .reflect .Field ;
2019import java .util .ArrayList ;
2120import java .util .HashMap ;
2221import java .util .Iterator ;
3332import org .eclipse .jface .text .BadLocationException ;
3433import org .eclipse .jface .text .Document ;
3534import org .eclipse .jface .text .IDocument ;
36- import org .eclipse .jface .text .IDocumentExtension3 ;
37- import org .eclipse .jface .text .IDocumentPartitioner ;
3835import org .eclipse .jface .text .IRegion ;
3936import org .eclipse .jface .text .ITextViewer ;
40- import org .eclipse .jface .text .ITypedRegion ;
4137import org .eclipse .jface .text .Position ;
4238import org .eclipse .jface .text .Region ;
43- import org .eclipse .jface .text .TextPresentation ;
44- import org .eclipse .jface .text .TextUtilities ;
4539import org .eclipse .jface .text .codemining .AbstractCodeMiningProvider ;
4640import org .eclipse .jface .text .codemining .DocumentFooterCodeMining ;
4741import org .eclipse .jface .text .codemining .ICodeMining ;
4842import org .eclipse .jface .text .codemining .ICodeMiningProvider ;
4943import org .eclipse .jface .text .codemining .LineHeaderCodeMining ;
50- import org .eclipse .jface .text .presentation .IPresentationReconciler ;
51- import org .eclipse .jface .text .presentation .IPresentationReconcilerExtension ;
52- import org .eclipse .jface .text .presentation .IPresentationRepairer ;
5344import org .eclipse .jface .text .source .Annotation ;
5445import org .eclipse .jface .text .source .IAnnotationModel ;
5546import org .eclipse .jface .text .source .ISourceViewer ;
@@ -345,7 +336,7 @@ public Point draw(GC gc, StyledText textWidget, Color color, int x, int y) {
345336 gc .fillRectangle (0 , y , textWidget .getBounds ().width /* result.x */ , result .y );
346337
347338 String label = getLabel ();
348- List <StyleRange > ranges = getStyleRanges (viewer , label );
339+ List <StyleRange > ranges = computeStyleRanges (viewer , label );
349340 HashMap <Font , Map <Integer /* style */ , Font >> styledFonts = new HashMap <>();
350341
351342 // draw darker background for detailed diff
@@ -498,7 +489,8 @@ private Point getPositionForOffset(GC gc, int offset, String str, List<StyleRang
498489 Point result = null ;
499490 var before = gc .getFont ();
500491 try {
501- for (var range : ranges ) {
492+ for (int i = 0 ; i < ranges .size (); i ++) {
493+ var range = ranges .get (i );
502494 if (range .start <= offset ) {
503495 int rangeEnd = range .start + range .length ;
504496 if (rangeEnd > offset ) {
@@ -512,8 +504,12 @@ private Point getPositionForOffset(GC gc, int offset, String str, List<StyleRang
512504 }
513505 int lfIdx = sub .lastIndexOf ("\n " ); //$NON-NLS-1$
514506 if (lfIdx > 0 ) {
515- sub = sub .substring (lfIdx + 1 );
516- result = null ;
507+ if (lfIdx == sub .length () - 1 && isLastForCurrentOffset (ranges , i , offset )) {
508+ sub = sub .substring (0 , lfIdx );
509+ } else {
510+ sub = sub .substring (lfIdx + 1 );
511+ result = null ;
512+ }
517513 }
518514 var rangeWithFont = transformFontStyleToFont (before , range , styledFonts );
519515 if (rangeWithFont .font != null ) {
@@ -537,6 +533,18 @@ private Point getPositionForOffset(GC gc, int offset, String str, List<StyleRang
537533 return result ;
538534 }
539535
536+ private boolean isLastForCurrentOffset (List <StyleRange > ranges , int i , int offset ) {
537+ int nextIdx = i + 1 ;
538+ if (nextIdx >= ranges .size ()) {
539+ return false ;
540+ }
541+ StyleRange next = ranges .get (nextIdx );
542+ if (next .start >= offset ) {
543+ return true ;
544+ }
545+ return false ;
546+ }
547+
540548 private StyleRange transformFontStyleToFont (Font baseFont , StyleRange styleRange ,
541549 HashMap <Font , Map <Integer /* style */ , Font >> styledFonts ) {
542550 // as per the StyleRange contract, only consider fontStyle if font is not
@@ -556,82 +564,30 @@ private StyleRange transformFontStyleToFont(Font baseFont, StyleRange styleRange
556564 return styleRange ;
557565 }
558566
559- private List <StyleRange > getStyleRanges (ITextViewer v , String source ) {
567+ private List <StyleRange > computeStyleRanges (ITextViewer v , String source ) {
560568 List <StyleRange > result = new ArrayList <>();
561569 if (!(v instanceof SourceViewer sv )) {
562570 return result ;
563571 }
572+ // TODO (tm) should we better cache the presentation and don't calculate it each
573+ // time?
564574 try {
565- // TODO (tm) API needed to access IPresentationReconciler
566- Field f = SourceViewer .class .getDeclaredField ("fPresentationReconciler" ); //$NON-NLS-1$
567- f .setAccessible (true );
568- var reconciler = (IPresentationReconciler ) f .get (sv );
569- // TODO (tm) should we better cache the presentation and don't calculate it each
570- // time?
571- result = createPresentation (reconciler , sv .getDocument (), source );
572- } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException e ) {
573- error (e );
574- }
575- return result ;
576- }
577-
578- private List <StyleRange > createPresentation (IPresentationReconciler reconciler , IDocument originalDocument ,
579- String source ) {
580- try {
575+ IDocument originalDocument = sv .getDocument ();
581576 String prefix = originalDocument .get (0 , diff .leftStart );
582577 IDocument document = new Document (prefix + source );
583578 IRegion damage = new Region (prefix .length (), source .length ());
584- String partition = IDocumentExtension3 .DEFAULT_PARTITIONING ;
585- if (reconciler instanceof IPresentationReconcilerExtension ext ) {
586- String extPartition = ext .getDocumentPartitioning ();
587- if (extPartition != null && !extPartition .isEmpty ()) {
588- partition = extPartition ;
589- }
590- }
591- IDocumentPartitioner partitioner = originalDocument .getDocumentPartitioner ();
592- document .setDocumentPartitioner (partitioner );
593- IDocumentPartitioner originalDocumentPartitioner = null ;
594- if (document instanceof IDocumentExtension3 ext
595- && originalDocument instanceof IDocumentExtension3 originalExt ) {
596- originalDocumentPartitioner = originalExt .getDocumentPartitioner (partition );
597- if (originalDocumentPartitioner != null ) {
598- // set temporarily another document in partitioner so that presentation can be
599- // created for given source
600- originalDocumentPartitioner .disconnect ();
601- originalDocumentPartitioner .connect (document );
602- ext .setDocumentPartitioner (partition , originalDocumentPartitioner );
603- }
604- }
605- TextPresentation presentation = new TextPresentation (damage , 1000 );
606-
607- ITypedRegion [] partitioning = TextUtilities .computePartitioning (document , partition , damage .getOffset (),
608- damage .getLength (), false );
609- for (ITypedRegion r : partitioning ) {
610- IPresentationRepairer repairer = reconciler .getRepairer (r .getType ());
611- if (repairer != null ) {
612- repairer .setDocument (document );
613- repairer .createPresentation (presentation , r );
614- repairer .setDocument (originalDocument );
615- }
616- }
617- if (originalDocumentPartitioner != null ) {
618- originalDocumentPartitioner .connect (originalDocument );
619- }
620- List <StyleRange > result = new ArrayList <>();
621- var it = presentation .getAllStyleRangeIterator ();
579+ result = sv .computeStyleRanges (document , damage );
622580 int startOffset = prefix .length ();
623- while (it .hasNext ()) {
624- StyleRange next = it .next ();
581+ for (StyleRange next : result ) {
625582 if (next .start < startOffset ) {
626583 throw new IllegalStateException (
627584 "Invalid presentation with style range starting before source offset" ); //$NON-NLS-1$
628585 }
629586 next .start -= startOffset ;
630- result .add (next );
631587 }
632588 return result ;
633- } catch (BadLocationException x ) {
634- return null ;
589+ } catch (BadLocationException e ) {
590+ return result ;
635591 }
636592 }
637593
0 commit comments