View | Details | Raw Unified | Return to bug 372128 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java (-50 / +127 lines)
Lines 9-17 Link Here
9
 *     Christian Plesner Hansen (plesner@quenta.org) - initial API and implementation
9
 *     Christian Plesner Hansen (plesner@quenta.org) - initial API and implementation
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.jface.text.source;
11
package org.eclipse.jface.text.source;
12
import java.util.HashSet;
13
import java.util.Set;
14
15
import org.eclipse.core.runtime.Assert;
12
import org.eclipse.core.runtime.Assert;
16
13
17
import org.eclipse.jface.text.BadLocationException;
14
import org.eclipse.jface.text.BadLocationException;
Lines 132-170 Link Here
132
		if (document == null || offset < 0 || offset > document.getLength())
129
		if (document == null || offset < 0 || offset > document.getLength())
133
			return null;
130
			return null;
134
131
135
		int start;
132
		//maybe a bracket is selected
136
		int end;
133
		IRegion region= match(document, offset, length);
137
		if (length >= 0) {
134
		fAnchor= ICharacterPairMatcher.LEFT; //always set the anchor to LEFT
138
			start= offset;
135
		if (region != null) {
139
			end= offset + length;
136
			return region;
140
		} else {
141
			end= offset;
142
			start= offset + length;
143
		}
137
		}
144
138
145
		int sourceCaretOffset= offset + length;
139
		//bracket is not selected
146
		int adjustment= getOffsetAdjustment(document, sourceCaretOffset, length);
147
		sourceCaretOffset+= adjustment;
148
149
		try {
140
		try {
150
			for (int offset1= sourceCaretOffset; offset1 >= 0; offset1--) {
141
			final String partition1= TextUtilities.getContentType(document, fPartitioning, offset, false);
151
				char prevChar= document.getChar(Math.max(offset1 - 1, 0));
142
			final DocumentPartitionAccessor partDoc= new DocumentPartitionAccessor(document, fPartitioning, partition1);
152
				if (fPairs.contains(prevChar) && fPairs.isStartCharacter(prevChar)) {
143
			return findEnclosingPeers(document, partDoc, offset, length, 0, document.getLength());
153
					IRegion match= performMatch(document, offset1);
154
					if (match != null) {
155
						int matchOffset= match.getOffset();
156
						int matchLength= match.getLength();
157
						if ((matchOffset <= start) && (matchOffset + matchLength > start) && (matchOffset < end) && (matchOffset + matchLength >= end)) {
158
							return match;
159
						}
160
					}
161
				}
162
			}
163
		} catch (BadLocationException ble) {
144
		} catch (BadLocationException ble) {
145
			fAnchor= -1;
164
			return null;
146
			return null;
165
		}
147
		}
166
		return null;
167
	}
148
	}
149
168
150
169
	/**
151
	/**
170
	 * Computes the adjustment in the start offset for the purpose of finding a matching peer. This
152
	 * Computes the adjustment in the start offset for the purpose of finding a matching peer. This
Lines 261-266 Link Here
261
		return -1;
243
		return -1;
262
	}
244
	}
263
245
246
	/*
247
	 * Performs the actual work of finding enclosing peer characters for #findEnclosingPeerCharacters(IDocument, int, int).
248
	 */
249
	private IRegion findEnclosingPeers(IDocument document, DocumentPartitionAccessor doc, int offset, int length, int lowerBoundary, int upperBoundary) throws BadLocationException {
250
		char[] pairs= fPairs.fPairs;
251
	
252
		int start;
253
		int end;
254
		if (length >= 0) {
255
			start= offset;
256
			end= offset + length;
257
		} else {
258
			end= offset;
259
			start= offset + length;
260
		}
261
	
262
		boolean lowerFound= false;
263
		boolean upperFound= false;
264
		int[][] counts= new int[pairs.length][2];
265
		int pos1= doc.getNextPosition(start, false);
266
		int pos2= start;
267
	
268
		while ((pos1 >= lowerBoundary && !lowerFound) || (pos2 < upperBoundary && !upperFound)) {
269
			for (int i= 0; i < counts.length; i++) {
270
				counts[i][0]= counts[i][1]= 0;
271
			}
272
	
273
			outer1: while (pos1 >= lowerBoundary && !lowerFound) {
274
				final char c= doc.getChar(pos1);
275
				int i= getCharacterType(c, document, pos1);
276
				if (i != -1 && doc.inPartition(pos1)) {
277
					if (i % 2 == 0) {
278
						counts[i / 2][0]--; //start
279
					} else {
280
						counts[i / 2][0]++; //end
281
					}
282
					for (int j= 0; j < counts.length; j++) {
283
						if (counts[j][0] == -1) {
284
							lowerFound= true;
285
							break outer1;
286
						}
287
					}
288
				}
289
				pos1= doc.getNextPosition(pos1, false);
290
			}
291
	
292
			outer2: while (pos2 < upperBoundary && !upperFound) {
293
				final char c= doc.getChar(pos2);
294
				int i= getCharacterType(c, document, pos2);
295
				if (i != -1 && doc.inPartition(pos2)) {
296
					if (i % 2 == 0) {
297
						counts[i / 2][1]++; //start
298
					} else {
299
						counts[i / 2][1]--; //end
300
					}
301
					for (int j= 0; j < counts.length; j++) {
302
						if (counts[j][1] == -1 && counts[j][0] == -1) {
303
							upperFound= true;
304
							break outer2;
305
						}
306
					}
307
				}
308
				pos2= doc.getNextPosition(pos2, true);
309
			}
310
	
311
			if (pos1 > start || pos2 < end) {
312
				//match inside selection => discard
313
				pos1= doc.getNextPosition(pos1, false);
314
				pos2= doc.getNextPosition(pos2, true);
315
				lowerFound= false;
316
				upperFound= false;
317
			}
318
		}
319
		pos2++;
320
		if (pos1 < lowerBoundary || pos2 > upperBoundary)
321
			return null;
322
		return new Region(pos1, pos2 - pos1);
323
	}
324
325
	/**
326
	 * Determines whether the given character is a start character or an end character or none of
327
	 * these.
328
	 * 
329
	 * <p>
330
	 * Clients can override this method to handle characters which may have special meaning in some
331
	 * situations. E.g. In Java '<' is used as an angular bracket and as well as less-than operator.
332
	 * </p>
333
	 * 
334
	 * @param ch the character
335
	 * @param document the document
336
	 * @param offset the offset in document
337
	 * @return 0 if start character, 1 if end character and -1 if neither a start or an end character
338
	 * @since 3.8
339
	 */
340
	protected int getCharacterType(char ch, IDocument document, int offset) {
341
		char[] pairs= fPairs.fPairs;
342
		for (int i= 0; i < pairs.length; i++) {
343
			if (pairs[i] == ch) {
344
				return i;
345
			}
346
		}
347
		return -1;
348
	}
349
264
	/* @see ICharacterPairMatcher#getAnchor() */
350
	/* @see ICharacterPairMatcher#getAnchor() */
265
	public int getAnchor() {
351
	public int getAnchor() {
266
		return fAnchor;
352
		return fAnchor;
Lines 285-290 Link Here
285
		private final IDocument fDocument;
371
		private final IDocument fDocument;
286
		private final String fPartitioning, fPartition;
372
		private final String fPartitioning, fPartition;
287
		private ITypedRegion fCachedPartition;
373
		private ITypedRegion fCachedPartition;
374
		private int fLength;
288
375
289
		/**
376
		/**
290
		 * Creates a new partitioned document for the specified document.
377
		 * Creates a new partitioned document for the specified document.
Lines 298-303 Link Here
298
			fDocument= doc;
385
			fDocument= doc;
299
			fPartitioning= partitioning;
386
			fPartitioning= partitioning;
300
			fPartition= partition;
387
			fPartition= partition;
388
			fLength= doc.getLength();
301
		}
389
		}
302
390
303
		/**
391
		/**
Lines 338-344 Link Here
338
		}
426
		}
339
427
340
		/**
428
		/**
341
		 * Returns the next position to query in the search.  The position
429
		 * Returns the next position to query in the search. The position
342
		 * is not guaranteed to be in this document's partition.
430
		 * is not guaranteed to be in this document's partition.
343
		 *
431
		 *
344
		 * @param pos an offset within the document
432
		 * @param pos an offset within the document
Lines 347-354 Link Here
347
		 */
435
		 */
348
		public int getNextPosition(int pos, boolean searchForward) {
436
		public int getNextPosition(int pos, boolean searchForward) {
349
			final ITypedRegion partition= getPartition(pos);
437
			final ITypedRegion partition= getPartition(pos);
350
			if (partition == null) return simpleIncrement(pos, searchForward);
438
			if (partition == null || fPartition.equals(partition.getType()))
351
			if (fPartition.equals(partition.getType()))
352
				return simpleIncrement(pos, searchForward);
439
				return simpleIncrement(pos, searchForward);
353
			if (searchForward) {
440
			if (searchForward) {
354
				int end= partition.getOffset() + partition.getLength();
441
				int end= partition.getOffset() + partition.getLength();
Lines 376-382 Link Here
376
		 */
463
		 */
377
		private ITypedRegion getPartition(int pos) {
464
		private ITypedRegion getPartition(int pos) {
378
			if (fCachedPartition == null || !contains(fCachedPartition, pos)) {
465
			if (fCachedPartition == null || !contains(fCachedPartition, pos)) {
379
				Assert.isTrue(pos >= 0 && pos <= fDocument.getLength());
466
				Assert.isTrue(pos >= 0 && pos <= fLength);
380
				try {
467
				try {
381
					fCachedPartition= TextUtilities.getPartition(fDocument, fPartitioning, pos, false);
468
					fCachedPartition= TextUtilities.getPartition(fDocument, fPartitioning, pos, false);
382
				} catch (BadLocationException e) {
469
				} catch (BadLocationException e) {
Lines 405-432 Link Here
405
		}
492
		}
406
493
407
		/**
494
		/**
408
		 * Returns true if the specified character pair occurs in one
495
		 * Returns true if the specified character occurs in one of the character pairs.
409
		 * of the character pairs.
496
		 * 
410
		 *
411
		 * @param c a character
497
		 * @param c a character
412
		 * @return true exactly if the character occurs in one of the pairs
498
		 * @return true exactly if the character occurs in one of the pairs
413
		 */
499
		 */
414
		public boolean contains(char c) {
500
		public boolean contains(char c) {
415
			return getAllCharacters().contains(new Character(c));
501
			char[] pairs= fPairs;
416
		}
502
			for (int i= 0, n= pairs.length; i < n; i++) {
417
503
				if (c == pairs[i])
418
		private Set/*<Character>*/ fCharsCache= null;
504
					return true;
419
		/**
420
		 * @return A set containing all characters occurring in character pairs.
421
		 */
422
		private Set/*<Character>*/ getAllCharacters() {
423
			if (fCharsCache == null) {
424
				Set/*<Character>*/ set= new HashSet/*<Character>*/();
425
				for (int i= 0; i < fPairs.length; i++)
426
					set.add(new Character(fPairs[i]));
427
				fCharsCache= set;
428
			}
505
			}
429
			return fCharsCache;
506
			return false;
430
		}
507
		}
431
508
432
		/**
509
		/**
(-)a/org.eclipse.text.tests/src/org/eclipse/text/tests/CopyOnWriteTextStoreTest.java (-4 / +4 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation and others.
2
 * Copyright (c) 2005, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 31-37 Link Here
31
			super(new GapTextStore());
31
			super(new GapTextStore());
32
		}
32
		}
33
		ITextStore getStore() {
33
		ITextStore getStore() {
34
			return fTextStore;
34
			return (ITextStore)new Accessor(this, CopyOnWriteTextStore.class).get("fTextStore");
35
		}
35
		}
36
		String get() {
36
		String get() {
37
			return get(0, getLength());
37
			return get(0, getLength());
Lines 68-74 Link Here
68
		// check that underlying text store is not modifiable
68
		// check that underlying text store is not modifiable
69
		boolean failed= false;
69
		boolean failed= false;
70
		try {
70
		try {
71
			fText.getStore().replace(0,0,null);
71
			fText.getStore().replace(0, 0, null);
72
		} catch (UnsupportedOperationException uoe) {
72
		} catch (UnsupportedOperationException uoe) {
73
			failed= true;
73
			failed= true;
74
		}
74
		}
Lines 91-97 Link Here
91
		// check that underlying text store is not modifiable
91
		// check that underlying text store is not modifiable
92
		boolean failed= false;
92
		boolean failed= false;
93
		try {
93
		try {
94
			fText.getStore().replace(0,0,null);
94
			fText.getStore().replace(0, 0, null);
95
		} catch (UnsupportedOperationException uoe) {
95
		} catch (UnsupportedOperationException uoe) {
96
			failed= true;
96
			failed= true;
97
		}
97
		}
(-)a/org.eclipse.text/src/org/eclipse/jface/text/AbstractDocument.java (-3 / +5 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2010 IBM Corporation and others.
2
 * Copyright (c) 2000, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 802-810 Link Here
802
	 * @see org.eclipse.jface.text.IDocument#getChar(int)
802
	 * @see org.eclipse.jface.text.IDocument#getChar(int)
803
	 */
803
	 */
804
	public char getChar(int pos) throws BadLocationException {
804
	public char getChar(int pos) throws BadLocationException {
805
		if ((0 > pos) || (pos >= getLength()))
805
		try {
806
			return getStore().get(pos);
807
		} catch (IndexOutOfBoundsException e) {
806
			throw new BadLocationException();
808
			throw new BadLocationException();
807
		return getStore().get(pos);
809
		}
808
	}
810
	}
809
811
810
	/*
812
	/*
(-)a/org.eclipse.text/src/org/eclipse/jface/text/CopyOnWriteTextStore.java (-2 / +2 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2010 IBM Corporation and others.
2
 * Copyright (c) 2005, 2012 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 107-113 Link Here
107
	}
107
	}
108
108
109
	/** The underlying "real" text store */
109
	/** The underlying "real" text store */
110
	protected ITextStore fTextStore= new StringTextStore();
110
	private ITextStore fTextStore;
111
111
112
	/** A modifiable <code>ITextStore</code> instance */
112
	/** A modifiable <code>ITextStore</code> instance */
113
	private final ITextStore fModifiableTextStore;
113
	private final ITextStore fModifiableTextStore;

Return to bug 372128