2323import java .util .Map ;
2424import java .util .Map .Entry ;
2525import java .util .concurrent .CopyOnWriteArrayList ;
26+ import java .util .concurrent .atomic .AtomicInteger ;
27+ import java .util .concurrent .atomic .AtomicLong ;
28+ import java .util .concurrent .atomic .AtomicReference ;
2629import java .util .regex .PatternSyntaxException ;
2730
2831import org .eclipse .core .runtime .Assert ;
@@ -115,17 +118,17 @@ static private class RegisteredReplace {
115118 * The list of post notification changes
116119 * @since 2.0
117120 */
118- private List <RegisteredReplace > fPostNotificationChanges ;
121+ private volatile List <RegisteredReplace > fPostNotificationChanges ;
119122 /**
120123 * The reentrance count for post notification changes.
121124 * @since 2.0
122125 */
123- private int fReentranceCount = 0 ;
126+ private volatile int fReentranceCount ;
124127 /**
125128 * Indicates whether post notification change processing has been stopped.
126129 * @since 2.0
127130 */
128- private int fStoppedCount = 0 ;
131+ private volatile int fStoppedCount ;
129132 /**
130133 * Indicates whether the registration of post notification changes should be ignored.
131134 * @since 2.1
@@ -135,22 +138,22 @@ static private class RegisteredReplace {
135138 * Indicates whether the notification of listeners has been stopped.
136139 * @since 2.1
137140 */
138- private int fStoppedListenerNotification = 0 ;
141+ private final AtomicInteger fStoppedListenerNotification ;
139142 /**
140- * The document event to be sent after listener notification has been resumed.
141- * @since 2.1
143+ * The document event list to be sent after listener notification has been resumed.
144+ * @since 3.15
142145 */
143- private DocumentEvent fDeferredDocumentEvent ;
146+ private final List < DocumentEvent > fDeferredDocumentEvents ;
144147 /**
145148 * The registered document partitioners.
146149 * @since 3.0
147150 */
148151 private Map <String , IDocumentPartitioner > fDocumentPartitioners ;
149152 /**
150153 * The partitioning changed event.
151- * @since 3.0
154+ * @since 3.15. 0
152155 */
153- private DocumentPartitioningChangedEvent fDocumentPartitioningChangedEvent ;
156+ private final AtomicReference < DocumentPartitioningChangedEvent > fDocumentPartitioningChangedEvent ;
154157 /**
155158 * The find/replace document adapter.
156159 * @since 3.0
@@ -175,7 +178,7 @@ static private class RegisteredReplace {
175178 * Keeps track of next modification stamp.
176179 * @since 3.1.1
177180 */
178- private long fNextModificationStamp = IDocumentExtension4 .UNKNOWN_MODIFICATION_STAMP ;
181+ private final AtomicLong fNextModificationStamp = new AtomicLong ( IDocumentExtension4 .UNKNOWN_MODIFICATION_STAMP ) ;
179182 /**
180183 * This document's default line delimiter.
181184 * @since 3.1
@@ -191,6 +194,9 @@ static private class RegisteredReplace {
191194 */
192195 protected AbstractDocument () {
193196 fModificationStamp = getNextModificationStamp ();
197+ fStoppedListenerNotification = new AtomicInteger ();
198+ fDeferredDocumentEvents = new CopyOnWriteArrayList <>();
199+ fDocumentPartitioningChangedEvent = new AtomicReference <>();
194200 }
195201
196202
@@ -437,7 +443,7 @@ public boolean containsPositionCategory(String category) {
437443 * @see IDocument#computeIndexInCategory(String, int)
438444 * @deprecated As of 3.4, replaced by {@link #computeIndexInPositionList(List, int, boolean)}
439445 */
440- @ Deprecated
446+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
441447 protected int computeIndexInPositionList (List <? extends Position > positions , int offset ) {
442448 return computeIndexInPositionList (positions , offset , true );
443449 }
@@ -542,7 +548,7 @@ public int computeIndexInCategory(String category, int offset) throws BadLocatio
542548 *
543549 * @deprecated as of 2.0. Use <code>fireDocumentPartitioningChanged(IRegion)</code> instead.
544550 */
545- @ Deprecated
551+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
546552 protected void fireDocumentPartitioningChanged () {
547553 if (fDocumentPartitioningListeners == null ) {
548554 return ;
@@ -565,7 +571,7 @@ protected void fireDocumentPartitioningChanged() {
565571 * <code>fireDocumentPartitioningChanged(DocumentPartitioningChangedEvent)</code>
566572 * instead.
567573 */
568- @ Deprecated
574+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
569575 protected void fireDocumentPartitioningChanged (IRegion region ) {
570576 if (fDocumentPartitioningListeners == null ) {
571577 return ;
@@ -670,7 +676,7 @@ protected void fireDocumentAboutToBeChanged(DocumentEvent event) {
670676 protected void updateDocumentStructures (DocumentEvent event ) {
671677
672678 if (fDocumentPartitioners != null ) {
673- fDocumentPartitioningChangedEvent = new DocumentPartitioningChangedEvent (this );
679+ DocumentPartitioningChangedEvent newValue = new DocumentPartitioningChangedEvent (this );
674680 for (Entry <String , IDocumentPartitioner > entry : fDocumentPartitioners .entrySet ()) {
675681
676682 String partitioning = entry .getKey ();
@@ -685,14 +691,15 @@ protected void updateDocumentStructures(DocumentEvent event) {
685691 if (partitioner instanceof IDocumentPartitionerExtension extension ) {
686692 IRegion r = extension .documentChanged2 (event );
687693 if (r != null ) {
688- fDocumentPartitioningChangedEvent .setPartitionChange (partitioning , r .getOffset (), r .getLength ());
694+ newValue .setPartitionChange (partitioning , r .getOffset (), r .getLength ());
689695 }
690696 } else {
691697 if (partitioner .documentChanged (event )) {
692- fDocumentPartitioningChangedEvent .setPartitionChange (partitioning , 0 , event .getDocument ().getLength ());
698+ newValue .setPartitionChange (partitioning , 0 , event .getDocument ().getLength ());
693699 }
694700 }
695701 }
702+ fDocumentPartitioningChangedEvent .set (newValue );
696703 }
697704
698705 if (!fPositions .isEmpty ()) {
@@ -709,8 +716,9 @@ protected void updateDocumentStructures(DocumentEvent event) {
709716 * @param event the event to be sent out.
710717 */
711718 protected void doFireDocumentChanged (DocumentEvent event ) {
712- boolean changed = fDocumentPartitioningChangedEvent != null && !fDocumentPartitioningChangedEvent .isEmpty ();
713- IRegion change = changed ? fDocumentPartitioningChangedEvent .getCoverage () : null ;
719+ DocumentPartitioningChangedEvent changedEvent = fDocumentPartitioningChangedEvent .get ();
720+ boolean changed = changedEvent != null && !changedEvent .isEmpty ();
721+ IRegion change = changed ? changedEvent .getCoverage () : null ;
714722 doFireDocumentChanged (event , changed , change );
715723 }
716724
@@ -725,7 +733,7 @@ protected void doFireDocumentChanged(DocumentEvent event) {
725733 * @since 2.0
726734 * @deprecated as of 3.0. Use <code>doFireDocumentChanged2(DocumentEvent)</code> instead; this method will be removed.
727735 */
728- @ Deprecated
736+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
729737 protected void doFireDocumentChanged (DocumentEvent event , boolean firePartitionChange , IRegion partitionChange ) {
730738 doFireDocumentChanged2 (event );
731739 }
@@ -743,8 +751,7 @@ protected void doFireDocumentChanged(DocumentEvent event, boolean firePartitionC
743751 */
744752 protected void doFireDocumentChanged2 (DocumentEvent event ) {
745753
746- DocumentPartitioningChangedEvent p = fDocumentPartitioningChangedEvent ;
747- fDocumentPartitioningChangedEvent = null ;
754+ DocumentPartitioningChangedEvent p = fDocumentPartitioningChangedEvent .getAndSet (null );
748755 if (p != null && !p .isEmpty ()) {
749756 fireDocumentPartitioningChanged (p );
750757 }
@@ -786,10 +793,10 @@ protected void doFireDocumentChanged2(DocumentEvent event) {
786793 protected void fireDocumentChanged (DocumentEvent event ) {
787794 updateDocumentStructures (event );
788795
789- if (fStoppedListenerNotification == 0 ) {
796+ if (fStoppedListenerNotification . get () == 0 ) {
790797 doFireDocumentChanged (event );
791798 } else {
792- fDeferredDocumentEvent = event ;
799+ fDeferredDocumentEvents . add ( event ) ;
793800 }
794801 }
795802
@@ -1099,13 +1106,13 @@ public void removePositionUpdater(IPositionUpdater updater) {
10991106 }
11001107
11011108 private long getNextModificationStamp () {
1102- if ( fNextModificationStamp == Long . MAX_VALUE || fNextModificationStamp == IDocumentExtension4 . UNKNOWN_MODIFICATION_STAMP ) {
1103- fNextModificationStamp = 0 ;
1104- } else {
1105- fNextModificationStamp = fNextModificationStamp + 1 ;
1106- }
1107-
1108- return fNextModificationStamp ;
1109+ return fNextModificationStamp . getAndUpdate ( current -> {
1110+ if ( current == Long . MAX_VALUE || current == IDocumentExtension4 . UNKNOWN_MODIFICATION_STAMP ) {
1111+ return 0 ;
1112+ } else {
1113+ return current + 1 ;
1114+ }
1115+ }) ;
11091116 }
11101117
11111118 @ Override
@@ -1126,7 +1133,7 @@ public void replace(int pos, int length, String text, long modificationStamp) th
11261133 getTracker ().replace (pos , length , text );
11271134
11281135 fModificationStamp = modificationStamp ;
1129- fNextModificationStamp = Math . max (fModificationStamp , fNextModificationStamp );
1136+ fNextModificationStamp . getAndAccumulate (fModificationStamp , Math :: max );
11301137 e .fModificationStamp = fModificationStamp ;
11311138
11321139 fireDocumentChanged (e );
@@ -1167,7 +1174,7 @@ public void set(String text, long modificationStamp) {
11671174 getTracker ().set (text );
11681175
11691176 fModificationStamp = modificationStamp ;
1170- fNextModificationStamp = Math . max (fModificationStamp , fNextModificationStamp );
1177+ fNextModificationStamp . getAndAccumulate (fModificationStamp , Math :: max );
11711178 e .fModificationStamp = fModificationStamp ;
11721179
11731180 fireDocumentChanged (e );
@@ -1192,7 +1199,7 @@ protected void updatePositions(DocumentEvent event) {
11921199 *
11931200 * @deprecated as of 3.0 search is provided by {@link FindReplaceDocumentAdapter}
11941201 */
1195- @ Deprecated
1202+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
11961203 @ Override
11971204 public int search (int startPosition , String findString , boolean forwardSearch , boolean caseSensitive , boolean wholeWord ) throws BadLocationException {
11981205 try {
@@ -1295,7 +1302,7 @@ public void resumePostNotificationProcessing() {
12951302 * {@link IDocumentExtension4#startRewriteSession(DocumentRewriteSessionType)}
12961303 * instead.
12971304 */
1298- @ Deprecated
1305+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
12991306 @ Override
13001307 public void startSequentialRewrite (boolean normalized ) {
13011308 }
@@ -1306,22 +1313,21 @@ public void startSequentialRewrite(boolean normalized) {
13061313 * @since 2.0
13071314 * @deprecated As of 3.1, replaced by {@link IDocumentExtension4#stopRewriteSession(DocumentRewriteSession)}
13081315 */
1309- @ Deprecated
1316+ @ Deprecated ( forRemoval = true , since = "3.15.0" )
13101317 @ Override
13111318 public void stopSequentialRewrite () {
13121319 }
13131320
13141321 @ Override
13151322 public void resumeListenerNotification () {
1316- -- fStoppedListenerNotification ;
1317- if (fStoppedListenerNotification == 0 ) {
1323+ if (fStoppedListenerNotification .decrementAndGet () == 0 ) {
13181324 resumeDocumentListenerNotification ();
13191325 }
13201326 }
13211327
13221328 @ Override
13231329 public void stopListenerNotification () {
1324- ++ fStoppedListenerNotification ;
1330+ fStoppedListenerNotification . incrementAndGet () ;
13251331 }
13261332
13271333 /**
@@ -1331,17 +1337,18 @@ public void stopListenerNotification() {
13311337 * @since 2.1
13321338 */
13331339 private void resumeDocumentListenerNotification () {
1334- if (fDeferredDocumentEvent != null ) {
1335- DocumentEvent event = fDeferredDocumentEvent ;
1336- fDeferredDocumentEvent = null ;
1337- doFireDocumentChanged (event );
1340+ while (!fDeferredDocumentEvents .isEmpty ()) {
1341+ if (fStoppedListenerNotification .get () == 0 ) {
1342+ try {
1343+ DocumentEvent event = fDeferredDocumentEvents .remove (0 );
1344+ doFireDocumentChanged (event );
1345+ } catch (IndexOutOfBoundsException ex ) {
1346+ log (ex );
1347+ }
1348+ }
13381349 }
13391350 }
13401351
1341- /*
1342- * @see org.eclipse.jface.text.IDocumentExtension3#computeZeroLengthPartitioning(java.lang.String, int, int)
1343- * @since 3.0
1344- */
13451352 @ Override
13461353 public ITypedRegion [] computePartitioning (String partitioning , int offset , int length , boolean includeZeroLengthPartitions ) throws BadLocationException , BadPartitioningException {
13471354 if ((0 > offset ) || (0 > length ) || (offset + length > getLength ())) {
0 commit comments