Mercurial > projects > dwt-addons
annotate dwtx/jface/text/formatter/ContentFormatter.d @ 153:f70d9508c95c
Fix java Collection imports
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Mon, 25 Aug 2008 00:27:31 +0200 |
parents | eb21d3dfc767 |
children | 1a5b8f8129df |
rev | line source |
---|---|
129 | 1 /******************************************************************************* |
2 * Copyright (c) 2000, 2006 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 | |
131 | 14 |
151 | 15 module dwtx.jface.text.formatter.ContentFormatter; |
16 | |
131 | 17 import dwtx.jface.text.formatter.MultiPassContentFormatter; // packageimport |
18 import dwtx.jface.text.formatter.ContextBasedFormattingStrategy; // packageimport | |
19 import dwtx.jface.text.formatter.FormattingContext; // packageimport | |
20 import dwtx.jface.text.formatter.IFormattingStrategy; // packageimport | |
21 import dwtx.jface.text.formatter.IContentFormatterExtension; // packageimport | |
22 import dwtx.jface.text.formatter.IFormattingStrategyExtension; // packageimport | |
23 import dwtx.jface.text.formatter.IContentFormatter; // packageimport | |
24 import dwtx.jface.text.formatter.FormattingContextProperties; // packageimport | |
25 import dwtx.jface.text.formatter.IFormattingContext; // packageimport | |
26 | |
129 | 27 import dwt.dwthelper.utils; |
28 | |
29 | |
153
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
151
diff
changeset
|
30 import dwtx.dwtxhelper.Collection; |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
151
diff
changeset
|
31 |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
151
diff
changeset
|
32 |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
151
diff
changeset
|
33 |
f70d9508c95c
Fix java Collection imports
Frank Benoit <benoit@tionex.de>
parents:
151
diff
changeset
|
34 |
129 | 35 |
36 import dwtx.core.runtime.Assert; | |
37 import dwtx.jface.text.BadLocationException; | |
38 import dwtx.jface.text.BadPositionCategoryException; | |
39 import dwtx.jface.text.DefaultPositionUpdater; | |
40 import dwtx.jface.text.DocumentEvent; | |
41 import dwtx.jface.text.IDocument; | |
42 import dwtx.jface.text.IDocumentExtension3; | |
43 import dwtx.jface.text.IPositionUpdater; | |
44 import dwtx.jface.text.IRegion; | |
45 import dwtx.jface.text.ITypedRegion; | |
46 import dwtx.jface.text.Position; | |
47 import dwtx.jface.text.TextUtilities; | |
48 import dwtx.jface.text.TypedPosition; | |
49 | |
50 | |
51 /** | |
52 * Standard implementation of <code>IContentFormatter</code>. | |
53 * The formatter supports two operation modes: partition aware and | |
54 * partition unaware. <p> | |
55 * In the partition aware mode, the formatter determines the | |
56 * partitioning of the document region to be formatted. For each | |
57 * partition it determines all document positions which are affected | |
58 * when text changes are applied to the partition. Those which overlap | |
59 * with the partition are remembered as character positions. These | |
60 * character positions are passed over to the formatting strategy | |
61 * registered for the partition's content type. The formatting strategy | |
62 * returns a string containing the formatted document partition as well | |
63 * as the adapted character positions. The formatted partition replaces | |
64 * the old content of the partition. The remembered document positions | |
65 * are updated with the adapted character positions. In addition, all | |
66 * other document positions are accordingly adapted to the formatting | |
67 * changes.<p> | |
68 * In the partition unaware mode, the document's partitioning is ignored | |
69 * and the document is considered consisting of only one partition of | |
70 * the content type <code>IDocument.DEFAULT_CONTENT_TYPE</code>. The | |
71 * formatting process is similar to the partition aware mode, with the | |
72 * exception of having only one partition.<p> | |
73 * Usually, clients instantiate this class and configure it before using it. | |
74 * | |
75 * @see IContentFormatter | |
76 * @see IDocument | |
77 * @see ITypedRegion | |
78 * @see Position | |
79 */ | |
80 public class ContentFormatter : IContentFormatter { | |
81 | |
82 /** | |
83 * Defines a reference to either the offset or the end offset of | |
84 * a particular position. | |
85 */ | |
86 static class PositionReference : Comparable { | |
87 | |
88 /** The referenced position */ | |
89 protected Position fPosition; | |
90 /** The reference to either the offset or the end offset */ | |
91 protected bool fRefersToOffset; | |
92 /** The original category of the referenced position */ | |
93 protected String fCategory; | |
94 | |
95 /** | |
96 * Creates a new position reference. | |
97 * | |
98 * @param position the position to be referenced | |
99 * @param refersToOffset <code>true</code> if position offset should be referenced | |
100 * @param category the category the given position belongs to | |
101 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
102 protected this(Position position, bool refersToOffset, String category) { |
129 | 103 fPosition= position; |
104 fRefersToOffset= refersToOffset; | |
105 fCategory= category; | |
106 } | |
107 | |
108 /** | |
109 * Returns the offset of the referenced position. | |
110 * | |
111 * @return the offset of the referenced position | |
112 */ | |
113 protected int getOffset() { | |
114 return fPosition.getOffset(); | |
115 } | |
116 | |
117 /** | |
118 * Manipulates the offset of the referenced position. | |
119 * | |
120 * @param offset the new offset of the referenced position | |
121 */ | |
122 protected void setOffset(int offset) { | |
123 fPosition.setOffset(offset); | |
124 } | |
125 | |
126 /** | |
127 * Returns the length of the referenced position. | |
128 * | |
129 * @return the length of the referenced position | |
130 */ | |
131 protected int getLength() { | |
132 return fPosition.getLength(); | |
133 } | |
134 | |
135 /** | |
136 * Manipulates the length of the referenced position. | |
137 * | |
138 * @param length the new length of the referenced position | |
139 */ | |
140 protected void setLength(int length) { | |
141 fPosition.setLength(length); | |
142 } | |
143 | |
144 /** | |
145 * Returns whether this reference points to the offset or end offset | |
146 * of the references position. | |
147 * | |
148 * @return <code>true</code> if the offset of the position is referenced, <code>false</code> otherwise | |
149 */ | |
150 protected bool refersToOffset() { | |
151 return fRefersToOffset; | |
152 } | |
153 | |
154 /** | |
155 * Returns the category of the referenced position. | |
156 * | |
157 * @return the category of the referenced position | |
158 */ | |
159 protected String getCategory() { | |
160 return fCategory; | |
161 } | |
162 | |
163 /** | |
164 * Returns the referenced position. | |
165 * | |
166 * @return the referenced position | |
167 */ | |
168 protected Position getPosition() { | |
169 return fPosition; | |
170 } | |
171 | |
172 /** | |
173 * Returns the referenced character position | |
174 * | |
175 * @return the referenced character position | |
176 */ | |
177 protected int getCharacterPosition() { | |
178 if (fRefersToOffset) | |
179 return getOffset(); | |
180 return getOffset() + getLength(); | |
181 } | |
182 | |
183 /* | |
184 * @see Comparable#compareTo(Object) | |
185 */ | |
186 public int compareTo(Object obj) { | |
187 | |
138 | 188 if ( cast(PositionReference)obj ) { |
134 | 189 PositionReference r= cast(PositionReference) obj; |
129 | 190 return getCharacterPosition() - r.getCharacterPosition(); |
191 } | |
192 | |
193 throw new ClassCastException(); | |
194 } | |
195 } | |
196 | |
197 /** | |
198 * The position updater used to update the remembered partitions. | |
199 * | |
200 * @see IPositionUpdater | |
201 * @see DefaultPositionUpdater | |
202 */ | |
203 class NonDeletingPositionUpdater : DefaultPositionUpdater { | |
204 | |
205 /** | |
206 * Creates a new updater for the given category. | |
207 * | |
208 * @param category the category | |
209 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
210 protected this(String category) { |
129 | 211 super(category); |
212 } | |
213 | |
214 /* | |
215 * @see DefaultPositionUpdater#notDeleted() | |
216 */ | |
217 protected bool notDeleted() { | |
218 return true; | |
219 } | |
220 } | |
221 | |
222 /** | |
223 * The position updater which runs as first updater on the document's positions. | |
224 * Used to remove all affected positions from their categories to avoid them | |
225 * from being regularly updated. | |
226 * | |
227 * @see IPositionUpdater | |
228 */ | |
229 class RemoveAffectedPositions : IPositionUpdater { | |
230 /* | |
231 * @see IPositionUpdater#update(DocumentEvent) | |
232 */ | |
233 public void update(DocumentEvent event) { | |
234 removeAffectedPositions(event.getDocument()); | |
235 } | |
236 } | |
237 | |
238 /** | |
239 * The position updater which runs as last updater on the document's positions. | |
240 * Used to update all affected positions and adding them back to their | |
241 * original categories. | |
242 * | |
243 * @see IPositionUpdater | |
244 */ | |
245 class UpdateAffectedPositions : IPositionUpdater { | |
246 | |
247 /** The affected positions */ | |
248 private int[] fPositions; | |
249 /** The offset */ | |
250 private int fOffset; | |
251 | |
252 /** | |
253 * Creates a new updater. | |
254 * | |
255 * @param positions the affected positions | |
256 * @param offset the offset | |
257 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
258 public this(int[] positions, int offset) { |
129 | 259 fPositions= positions; |
260 fOffset= offset; | |
261 } | |
262 | |
263 /* | |
264 * @see IPositionUpdater#update(DocumentEvent) | |
265 */ | |
266 public void update(DocumentEvent event) { | |
267 updateAffectedPositions(event.getDocument(), fPositions, fOffset); | |
268 } | |
269 } | |
270 | |
271 | |
272 /** Internal position category used for the formatter partitioning */ | |
146 | 273 private const static String PARTITIONING= "__formatter_partitioning"; //$NON-NLS-1$ |
129 | 274 |
275 /** The map of <code>IFormattingStrategy</code> objects */ | |
276 private Map fStrategies; | |
277 /** The indicator of whether the formatter operates in partition aware mode or not */ | |
278 private bool fIsPartitionAware= true; | |
279 | |
280 /** The partition information managing document position categories */ | |
281 private String[] fPartitionManagingCategories; | |
282 /** The list of references to offset and end offset of all overlapping positions */ | |
283 private List fOverlappingPositionReferences; | |
284 /** Position updater used for partitioning positions */ | |
285 private IPositionUpdater fPartitioningUpdater; | |
286 /** | |
287 * The document partitioning used by this formatter. | |
288 * @since 3.0 | |
289 */ | |
290 private String fPartitioning; | |
291 /** | |
292 * The document this formatter works on. | |
293 * @since 3.0 | |
294 */ | |
295 private IDocument fDocument; | |
296 /** | |
297 * The external partition managing categories. | |
298 * @since 3.0 | |
299 */ | |
300 private String[] fExternalPartitonManagingCategories; | |
301 /** | |
302 * Indicates whether <code>fPartitionManagingCategories</code> must be computed. | |
303 * @since 3.0 | |
304 */ | |
305 private bool fNeedsComputation= true; | |
306 | |
307 | |
308 /** | |
309 * Creates a new content formatter. The content formatter operates by default | |
310 * in the partition-aware mode. There are no preconfigured formatting strategies. | |
311 * Will use the default document partitioning if not further configured. | |
312 */ | |
133
7d818bd32d63
Fix ctors to this with gvim regexp
Frank Benoit <benoit@tionex.de>
parents:
131
diff
changeset
|
313 public this() { |
129 | 314 fPartitioning= IDocumentExtension3.DEFAULT_PARTITIONING; |
315 } | |
316 | |
317 /** | |
318 * Registers a strategy for a particular content type. If there is already a strategy | |
319 * registered for this type, the new strategy is registered instead of the old one. | |
320 * If the given content type is <code>null</code> the given strategy is registered for | |
321 * all content types as is called only once per formatting session. | |
322 * | |
323 * @param strategy the formatting strategy to register, or <code>null</code> to remove an existing one | |
324 * @param contentType the content type under which to register | |
325 */ | |
326 public void setFormattingStrategy(IFormattingStrategy strategy, String contentType) { | |
327 | |
328 Assert.isNotNull(contentType); | |
329 | |
330 if (fStrategies is null) | |
331 fStrategies= new HashMap(); | |
332 | |
333 if (strategy is null) | |
334 fStrategies.remove(contentType); | |
335 else | |
336 fStrategies.put(contentType, strategy); | |
337 } | |
338 | |
339 /** | |
340 * Informs this content formatter about the names of those position categories | |
341 * which are used to manage the document's partitioning information and thus should | |
342 * be ignored when this formatter updates positions. | |
343 * | |
344 * @param categories the categories to be ignored | |
345 * @deprecated incompatible with an open set of document partitionings. The provided information is only used | |
346 * if this formatter can not compute the partition managing position categories. | |
347 */ | |
348 public void setPartitionManagingPositionCategories(String[] categories) { | |
349 fExternalPartitonManagingCategories= TextUtilities.copy(categories); | |
350 } | |
351 | |
352 /** | |
353 * Sets the document partitioning to be used by this formatter. | |
354 * | |
355 * @param partitioning the document partitioning | |
356 * @since 3.0 | |
357 */ | |
358 public void setDocumentPartitioning(String partitioning) { | |
359 fPartitioning= partitioning; | |
360 } | |
361 | |
362 /** | |
363 * Sets the formatter's operation mode. | |
364 * | |
365 * @param enable indicates whether the formatting process should be partition ware | |
366 */ | |
367 public void enablePartitionAwareFormatting(bool enable) { | |
368 fIsPartitionAware= enable; | |
369 } | |
370 | |
371 /* | |
372 * @see IContentFormatter#getFormattingStrategy(String) | |
373 */ | |
374 public IFormattingStrategy getFormattingStrategy(String contentType) { | |
375 | |
376 Assert.isNotNull(contentType); | |
377 | |
378 if (fStrategies is null) | |
379 return null; | |
380 | |
134 | 381 return cast(IFormattingStrategy) fStrategies.get(contentType); |
129 | 382 } |
383 | |
384 /* | |
385 * @see IContentFormatter#format(IDocument, IRegion) | |
386 */ | |
387 public void format(IDocument document, IRegion region) { | |
388 fNeedsComputation= true; | |
389 fDocument= document; | |
390 try { | |
391 | |
392 if (fIsPartitionAware) | |
393 formatPartitions(region); | |
394 else | |
395 formatRegion(region); | |
396 | |
397 } finally { | |
398 fNeedsComputation= true; | |
399 fDocument= null; | |
400 } | |
401 } | |
402 | |
403 /** | |
404 * Determines the partitioning of the given region of the document. | |
405 * Informs the formatting strategies of each partition about the start, | |
406 * the process, and the termination of the formatting session. | |
407 * | |
408 * @param region the document region to be formatted | |
409 * @since 3.0 | |
410 */ | |
411 private void formatPartitions(IRegion region) { | |
412 | |
413 addPartitioningUpdater(); | |
414 | |
415 try { | |
416 | |
417 TypedPosition[] ranges= getPartitioning(region); | |
418 if (ranges !is null) { | |
419 start(ranges, getIndentation(region.getOffset())); | |
420 format(ranges); | |
421 stop(ranges); | |
422 } | |
423 | |
424 } catch (BadLocationException x) { | |
425 } | |
426 | |
427 removePartitioningUpdater(); | |
428 } | |
429 | |
430 /** | |
431 * Formats the given region with the strategy registered for the default | |
432 * content type. The strategy is informed about the start, the process, and | |
433 * the termination of the formatting session. | |
434 * | |
435 * @param region the region to be formatted | |
436 * @since 3.0 | |
437 */ | |
438 private void formatRegion(IRegion region) { | |
439 | |
440 IFormattingStrategy strategy= getFormattingStrategy(IDocument.DEFAULT_CONTENT_TYPE); | |
441 if (strategy !is null) { | |
442 strategy.formatterStarts(getIndentation(region.getOffset())); | |
443 format(strategy, new TypedPosition(region.getOffset(), region.getLength(), IDocument.DEFAULT_CONTENT_TYPE)); | |
444 strategy.formatterStops(); | |
445 } | |
446 } | |
447 | |
448 /** | |
449 * Returns the partitioning of the given region of the document to be formatted. | |
450 * As one partition after the other will be formatted and formatting will | |
451 * probably change the length of the formatted partition, it must be kept | |
452 * track of the modifications in order to submit the correct partition to all | |
453 * formatting strategies. For this, all partitions are remembered as positions | |
454 * in a dedicated position category. (As formatting strategies might rely on each | |
455 * other, calling them in reversed order is not an option.) | |
456 * | |
457 * @param region the region for which the partitioning must be determined | |
458 * @return the partitioning of the specified region | |
459 * @exception BadLocationException of region is invalid in the document | |
460 * @since 3.0 | |
461 */ | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
462 private TypedPosition[] getPartitioning(IRegion region) { |
129 | 463 |
464 ITypedRegion[] regions= TextUtilities.computePartitioning(fDocument, fPartitioning, region.getOffset(), region.getLength(), false); | |
465 TypedPosition[] positions= new TypedPosition[regions.length]; | |
466 | |
467 for (int i= 0; i < regions.length; i++) { | |
468 positions[i]= new TypedPosition(regions[i]); | |
469 try { | |
470 fDocument.addPosition(PARTITIONING, positions[i]); | |
471 } catch (BadPositionCategoryException x) { | |
472 // should not happen | |
473 } | |
474 } | |
475 | |
476 return positions; | |
477 } | |
478 | |
479 /** | |
480 * Fires <code>formatterStarts</code> to all formatter strategies | |
481 * which will be involved in the forthcoming formatting process. | |
482 * | |
483 * @param regions the partitioning of the document to be formatted | |
484 * @param indentation the initial indentation | |
485 */ | |
486 private void start(TypedPosition[] regions, String indentation) { | |
487 for (int i= 0; i < regions.length; i++) { | |
488 IFormattingStrategy s= getFormattingStrategy(regions[i].getType()); | |
489 if (s !is null) | |
490 s.formatterStarts(indentation); | |
491 } | |
492 } | |
493 | |
494 /** | |
495 * Formats one partition after the other using the formatter strategy registered for | |
496 * the partition's content type. | |
497 * | |
498 * @param ranges the partitioning of the document region to be formatted | |
499 * @since 3.0 | |
500 */ | |
501 private void format(TypedPosition[] ranges) { | |
502 for (int i= 0; i < ranges.length; i++) { | |
503 IFormattingStrategy s= getFormattingStrategy(ranges[i].getType()); | |
504 if (s !is null) { | |
505 format(s, ranges[i]); | |
506 } | |
507 } | |
508 } | |
509 | |
510 /** | |
511 * Formats the given region of the document using the specified formatting | |
512 * strategy. In order to maintain positions correctly, first all affected | |
513 * positions determined, after all document listeners have been informed about | |
514 * the coming change, the affected positions are removed to avoid that they | |
515 * are regularly updated. After all position updaters have run, the affected | |
516 * positions are updated with the formatter's information and added back to | |
517 * their categories, right before the first document listener is informed about | |
518 * that a change happened. | |
519 * | |
520 * @param strategy the strategy to be used | |
521 * @param region the region to be formatted | |
522 * @since 3.0 | |
523 */ | |
524 private void format(IFormattingStrategy strategy, TypedPosition region) { | |
525 try { | |
526 | |
527 final int offset= region.getOffset(); | |
528 int length= region.getLength(); | |
529 | |
530 String content= fDocument.get(offset, length); | |
531 final int[] positions= getAffectedPositions(offset, length); | |
532 String formatted= strategy.format(content, isLineStart(offset), getIndentation(offset), positions); | |
533 | |
534 if (formatted !is null && !formatted.equals(content)) { | |
535 | |
536 IPositionUpdater first= new RemoveAffectedPositions(); | |
537 fDocument.insertPositionUpdater(first, 0); | |
538 IPositionUpdater last= new UpdateAffectedPositions(positions, offset); | |
539 fDocument.addPositionUpdater(last); | |
540 | |
541 fDocument.replace(offset, length, formatted); | |
542 | |
543 fDocument.removePositionUpdater(first); | |
544 fDocument.removePositionUpdater(last); | |
545 } | |
546 | |
547 } catch (BadLocationException x) { | |
548 // should not happen | |
549 } | |
550 } | |
551 | |
552 /** | |
553 * Fires <code>formatterStops</code> to all formatter strategies which were | |
554 * involved in the formatting process which is about to terminate. | |
555 * | |
556 * @param regions the partitioning of the document which has been formatted | |
557 */ | |
558 private void stop(TypedPosition[] regions) { | |
559 for (int i= 0; i < regions.length; i++) { | |
560 IFormattingStrategy s= getFormattingStrategy(regions[i].getType()); | |
561 if (s !is null) | |
562 s.formatterStops(); | |
563 } | |
564 } | |
565 | |
566 /** | |
567 * Installs those updaters which the formatter needs to keep track of the partitions. | |
568 * @since 3.0 | |
569 */ | |
570 private void addPartitioningUpdater() { | |
571 fPartitioningUpdater= new NonDeletingPositionUpdater(PARTITIONING); | |
572 fDocument.addPositionCategory(PARTITIONING); | |
573 fDocument.addPositionUpdater(fPartitioningUpdater); | |
574 } | |
575 | |
576 /** | |
577 * Removes the formatter's internal position updater and category. | |
578 * | |
579 * @since 3.0 | |
580 */ | |
581 private void removePartitioningUpdater() { | |
582 | |
583 try { | |
584 | |
585 fDocument.removePositionUpdater(fPartitioningUpdater); | |
586 fDocument.removePositionCategory(PARTITIONING); | |
587 fPartitioningUpdater= null; | |
588 | |
589 } catch (BadPositionCategoryException x) { | |
590 // should not happen | |
591 } | |
592 } | |
593 | |
594 /** | |
595 * Returns the partition managing position categories for the formatted document. | |
596 * | |
597 * @return the position managing position categories | |
598 * @since 3.0 | |
599 */ | |
600 private String[] getPartitionManagingCategories() { | |
601 if (fNeedsComputation) { | |
602 fNeedsComputation= false; | |
603 fPartitionManagingCategories= TextUtilities.computePartitionManagingCategories(fDocument); | |
604 if (fPartitionManagingCategories is null) | |
605 fPartitionManagingCategories= fExternalPartitonManagingCategories; | |
606 } | |
607 return fPartitionManagingCategories; | |
608 } | |
609 | |
610 /** | |
611 * Determines whether the given document position category should be ignored | |
612 * by this formatter's position updating. | |
613 * | |
614 * @param category the category to check | |
615 * @return <code>true</code> if the category should be ignored, <code>false</code> otherwise | |
616 */ | |
617 private bool ignoreCategory(String category) { | |
618 | |
619 if (PARTITIONING.equals(category)) | |
620 return true; | |
621 | |
622 String[] categories= getPartitionManagingCategories(); | |
623 if (categories !is null) { | |
624 for (int i= 0; i < categories.length; i++) { | |
625 if (categories[i].equals(category)) | |
626 return true; | |
627 } | |
628 } | |
629 | |
630 return false; | |
631 } | |
632 | |
633 /** | |
634 * Determines all embracing, overlapping, and follow up positions | |
635 * for the given region of the document. | |
636 * | |
637 * @param offset the offset of the document region to be formatted | |
638 * @param length the length of the document to be formatted | |
639 * @since 3.0 | |
640 */ | |
641 private void determinePositionsToUpdate(int offset, int length) { | |
642 | |
643 String[] categories= fDocument.getPositionCategories(); | |
644 if (categories !is null) { | |
645 for (int i= 0; i < categories.length; i++) { | |
646 | |
647 if (ignoreCategory(categories[i])) | |
648 continue; | |
649 | |
650 try { | |
651 | |
652 Position[] positions= fDocument.getPositions(categories[i]); | |
653 | |
654 for (int j= 0; j < positions.length; j++) { | |
655 | |
656 Position p= positions[j]; | |
657 if (p.overlapsWith(offset, length)) { | |
658 | |
659 if (offset < p.getOffset()) | |
660 fOverlappingPositionReferences.add(new PositionReference(p, true, categories[i])); | |
661 | |
662 if (p.getOffset() + p.getLength() < offset + length) | |
663 fOverlappingPositionReferences.add(new PositionReference(p, false, categories[i])); | |
664 } | |
665 } | |
666 | |
667 } catch (BadPositionCategoryException x) { | |
668 // can not happen | |
669 } | |
670 } | |
671 } | |
672 } | |
673 | |
674 /** | |
675 * Returns all offset and the end offset of all positions overlapping with the | |
676 * specified document range. | |
677 * | |
678 * @param offset the offset of the document region to be formatted | |
679 * @param length the length of the document to be formatted | |
680 * @return all character positions of the interleaving positions | |
681 * @since 3.0 | |
682 */ | |
683 private int[] getAffectedPositions(int offset, int length) { | |
684 | |
685 fOverlappingPositionReferences= new ArrayList(); | |
686 | |
687 determinePositionsToUpdate(offset, length); | |
688 | |
689 Collections.sort(fOverlappingPositionReferences); | |
690 | |
691 int[] positions= new int[fOverlappingPositionReferences.size()]; | |
692 for (int i= 0; i < positions.length; i++) { | |
134 | 693 PositionReference r= cast(PositionReference) fOverlappingPositionReferences.get(i); |
129 | 694 positions[i]= r.getCharacterPosition() - offset; |
695 } | |
696 | |
697 return positions; | |
698 } | |
699 | |
700 /** | |
701 * Removes the affected positions from their categories to avoid | |
702 * that they are invalidly updated. | |
703 * | |
704 * @param document the document | |
705 */ | |
706 private void removeAffectedPositions(IDocument document) { | |
707 int size= fOverlappingPositionReferences.size(); | |
708 for (int i= 0; i < size; i++) { | |
134 | 709 PositionReference r= cast(PositionReference) fOverlappingPositionReferences.get(i); |
129 | 710 try { |
711 document.removePosition(r.getCategory(), r.getPosition()); | |
712 } catch (BadPositionCategoryException x) { | |
713 // can not happen | |
714 } | |
715 } | |
716 } | |
717 | |
718 /** | |
719 * Updates all the overlapping positions. Note, all other positions are | |
720 * automatically updated by their document position updaters. | |
721 * | |
722 * @param document the document to has been formatted | |
723 * @param positions the adapted character positions to be used to update the document positions | |
724 * @param offset the offset of the document region that has been formatted | |
725 */ | |
726 protected void updateAffectedPositions(IDocument document, int[] positions, int offset) { | |
727 | |
728 if (document !is fDocument) | |
729 return; | |
730 | |
731 if (positions.length is 0) | |
732 return; | |
733 | |
734 for (int i= 0; i < positions.length; i++) { | |
735 | |
134 | 736 PositionReference r= cast(PositionReference) fOverlappingPositionReferences.get(i); |
129 | 737 |
738 if (r.refersToOffset()) | |
739 r.setOffset(offset + positions[i]); | |
740 else | |
741 r.setLength((offset + positions[i]) - r.getOffset()); | |
742 | |
743 Position p= r.getPosition(); | |
744 String category= r.getCategory(); | |
745 if (!document.containsPosition(category, p.offset, p.length)) { | |
746 try { | |
747 if (positionAboutToBeAdded(document, category, p)) | |
748 document.addPosition(r.getCategory(), p); | |
749 } catch (BadPositionCategoryException x) { | |
750 // can not happen | |
751 } catch (BadLocationException x) { | |
752 // should not happen | |
753 } | |
754 } | |
755 | |
756 } | |
757 | |
758 fOverlappingPositionReferences= null; | |
759 } | |
760 | |
761 /** | |
762 * The given position is about to be added to the given position category of the given document. <p> | |
763 * This default implementation return <code>true</code>. | |
764 * | |
765 * @param document the document | |
766 * @param category the position category | |
767 * @param position the position that will be added | |
768 * @return <code>true</code> if the position can be added, <code>false</code> if it should be ignored | |
769 */ | |
770 protected bool positionAboutToBeAdded(IDocument document, String category, Position position) { | |
771 return true; | |
772 } | |
773 | |
774 /** | |
775 * Returns the indentation of the line of the given offset. | |
776 * | |
777 * @param offset the offset | |
778 * @return the indentation of the line of the offset | |
779 * @since 3.0 | |
780 */ | |
781 private String getIndentation(int offset) { | |
782 | |
783 try { | |
784 int start= fDocument.getLineOfOffset(offset); | |
785 start= fDocument.getLineOffset(start); | |
786 | |
787 int end= start; | |
788 char c= fDocument.getChar(end); | |
789 while ('\t' is c || ' ' is c) | |
790 c= fDocument.getChar(++end); | |
791 | |
792 return fDocument.get(start, end - start); | |
793 } catch (BadLocationException x) { | |
794 } | |
795 | |
796 return ""; //$NON-NLS-1$ | |
797 } | |
798 | |
799 /** | |
800 * Determines whether the offset is the beginning of a line in the given document. | |
801 * | |
802 * @param offset the offset | |
803 * @return <code>true</code> if offset is the beginning of a line | |
804 * @exception BadLocationException if offset is invalid in document | |
805 * @since 3.0 | |
806 */ | |
136
6dcb0baaa031
Regex removal of throws decls, some instanceof
Frank Benoit <benoit@tionex.de>
parents:
134
diff
changeset
|
807 private bool isLineStart(int offset) { |
129 | 808 int start= fDocument.getLineOfOffset(offset); |
809 start= fDocument.getLineOffset(start); | |
810 return (start is offset); | |
811 } | |
812 } |