Lines 9-14
Link Here
|
9 |
* IBM Corporation - initial API and implementation |
9 |
* IBM Corporation - initial API and implementation |
10 |
* Anton Leherbauer (Wind River Systems) |
10 |
* Anton Leherbauer (Wind River Systems) |
11 |
* Markus Schorn (Wind River Systems) |
11 |
* Markus Schorn (Wind River Systems) |
|
|
12 |
* Elazar Leibovich (IDF) |
12 |
*******************************************************************************/ |
13 |
*******************************************************************************/ |
13 |
|
14 |
|
14 |
package org.eclipse.cdt.internal.ui.text.folding; |
15 |
package org.eclipse.cdt.internal.ui.text.folding; |
Lines 25-30
Link Here
|
25 |
import java.util.Stack; |
26 |
import java.util.Stack; |
26 |
|
27 |
|
27 |
import org.eclipse.core.runtime.Assert; |
28 |
import org.eclipse.core.runtime.Assert; |
|
|
29 |
import org.eclipse.core.runtime.FileLocator; |
28 |
import org.eclipse.core.runtime.IProgressMonitor; |
30 |
import org.eclipse.core.runtime.IProgressMonitor; |
29 |
import org.eclipse.core.runtime.IStatus; |
31 |
import org.eclipse.core.runtime.IStatus; |
30 |
import org.eclipse.core.runtime.Platform; |
32 |
import org.eclipse.core.runtime.Platform; |
Lines 50-55
Link Here
|
50 |
import org.eclipse.ui.texteditor.IDocumentProvider; |
52 |
import org.eclipse.ui.texteditor.IDocumentProvider; |
51 |
import org.eclipse.ui.texteditor.ITextEditor; |
53 |
import org.eclipse.ui.texteditor.ITextEditor; |
52 |
|
54 |
|
|
|
55 |
import org.eclipse.cdt.core.CCorePlugin; |
56 |
import org.eclipse.cdt.core.dom.ast.ASTVisitor; |
57 |
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; |
58 |
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; |
59 |
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; |
60 |
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; |
61 |
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; |
62 |
import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; |
63 |
import org.eclipse.cdt.core.dom.ast.IASTDoStatement; |
64 |
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; |
65 |
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; |
66 |
import org.eclipse.cdt.core.dom.ast.IASTExpression; |
67 |
import org.eclipse.cdt.core.dom.ast.IASTFileLocation; |
68 |
import org.eclipse.cdt.core.dom.ast.IASTForStatement; |
69 |
import org.eclipse.cdt.core.dom.ast.IASTInitializer; |
70 |
import org.eclipse.cdt.core.dom.ast.IASTInitializerList; |
71 |
import org.eclipse.cdt.core.dom.ast.IASTNode; |
72 |
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; |
73 |
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; |
74 |
import org.eclipse.cdt.core.dom.ast.IASTIfStatement; |
75 |
import org.eclipse.cdt.core.dom.ast.IASTStatement; |
76 |
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; |
77 |
|
53 |
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; |
78 |
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; |
54 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement; |
79 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement; |
55 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement; |
80 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement; |
Lines 59-64
Link Here
|
59 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement; |
84 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement; |
60 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; |
85 |
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; |
61 |
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
86 |
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
|
|
87 |
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; |
62 |
import org.eclipse.cdt.core.model.CModelException; |
88 |
import org.eclipse.cdt.core.model.CModelException; |
63 |
import org.eclipse.cdt.core.model.CoreModel; |
89 |
import org.eclipse.cdt.core.model.CoreModel; |
64 |
import org.eclipse.cdt.core.model.ICElement; |
90 |
import org.eclipse.cdt.core.model.ICElement; |
Lines 86-102
Link Here
|
86 |
* Derived from JDT counterpart. |
112 |
* Derived from JDT counterpart. |
87 |
* </p> |
113 |
* </p> |
88 |
*/ |
114 |
*/ |
89 |
public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvider { |
115 |
public class DefaultCFoldingStructureProvider implements |
|
|
116 |
ICFoldingStructureProvider { |
90 |
|
117 |
|
91 |
/** |
118 |
/** |
92 |
* Listen to cursor position changes. |
119 |
* Listen to cursor position changes. |
93 |
*/ |
120 |
*/ |
94 |
private final class SelectionListener implements ISelectionChangedListener { |
121 |
private final class SelectionListener implements ISelectionChangedListener { |
95 |
public void selectionChanged(SelectionChangedEvent event) { |
122 |
public void selectionChanged(SelectionChangedEvent event) { |
96 |
ISelection s= event.getSelection(); |
123 |
ISelection s = event.getSelection(); |
97 |
if (s instanceof ITextSelection) { |
124 |
if (s instanceof ITextSelection) { |
98 |
ITextSelection selection= (ITextSelection)event.getSelection(); |
125 |
ITextSelection selection = (ITextSelection) event |
99 |
fCursorPosition= selection.getOffset(); |
126 |
.getSelection(); |
|
|
127 |
fCursorPosition = selection.getOffset(); |
100 |
} |
128 |
} |
101 |
} |
129 |
} |
102 |
} |
130 |
} |
Lines 104-148
Link Here
|
104 |
/** |
132 |
/** |
105 |
* Reconcile annotation positions from preprocessor branches. |
133 |
* Reconcile annotation positions from preprocessor branches. |
106 |
*/ |
134 |
*/ |
107 |
private class PreprocessorBranchesReconciler implements ICReconcilingListener { |
135 |
private class PreprocessorBranchesReconciler implements |
|
|
136 |
ICReconcilingListener { |
108 |
volatile boolean fReconciling; |
137 |
volatile boolean fReconciling; |
109 |
|
138 |
|
110 |
/* |
139 |
/* |
111 |
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled() |
140 |
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled() |
112 |
*/ |
141 |
*/ |
113 |
public void aboutToBeReconciled() { |
142 |
public void aboutToBeReconciled() { |
114 |
|
143 |
|
115 |
} |
144 |
} |
116 |
|
145 |
|
117 |
/* |
146 |
/* |
118 |
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, boolean, IProgressMonitor) |
147 |
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, |
|
|
148 |
* boolean, IProgressMonitor) |
119 |
*/ |
149 |
*/ |
120 |
public void reconciled(IASTTranslationUnit ast, boolean force, IProgressMonitor progressMonitor) { |
150 |
public void reconciled(IASTTranslationUnit ast, boolean force, |
|
|
151 |
IProgressMonitor progressMonitor) { |
121 |
if (fInput == null || fReconciling) { |
152 |
if (fInput == null || fReconciling) { |
122 |
return; |
153 |
return; |
123 |
} |
154 |
} |
124 |
if (fPreprocessorBranchFoldingEnabled && ast == null) { |
155 |
if (fPreprocessorBranchFoldingEnabled && ast == null) { |
125 |
return; |
156 |
return; |
126 |
} |
157 |
} |
127 |
fReconciling= true; |
158 |
fReconciling = true; |
128 |
try { |
159 |
try { |
129 |
FoldingStructureComputationContext ctx= createContext(fInitialReconcilePending); |
160 |
FoldingStructureComputationContext ctx = createContext(fInitialReconcilePending); |
130 |
fInitialReconcilePending= false; |
161 |
fInitialReconcilePending = false; |
131 |
if (ctx != null) { |
162 |
if (ctx != null) { |
132 |
ctx.fAST= ast; |
163 |
ctx.fAST = ast; |
133 |
update(ctx); |
164 |
update(ctx); |
134 |
} |
165 |
} |
135 |
} finally { |
166 |
} finally { |
136 |
fReconciling= false; |
167 |
fReconciling = false; |
137 |
} |
168 |
} |
138 |
} |
169 |
} |
139 |
|
170 |
|
140 |
} |
171 |
} |
141 |
|
172 |
|
142 |
|
|
|
143 |
/** |
173 |
/** |
144 |
* A context that contains the information needed to compute the folding structure of an |
174 |
* A context that contains the information needed to compute the folding |
145 |
* {@link ITranslationUnit}. Computed folding regions are collected via |
175 |
* structure of an {@link ITranslationUnit}. Computed folding regions are |
|
|
176 |
* collected via |
146 |
* {@linkplain #addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) addProjectionRange}. |
177 |
* {@linkplain #addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) addProjectionRange}. |
147 |
*/ |
178 |
*/ |
148 |
protected final class FoldingStructureComputationContext { |
179 |
protected final class FoldingStructureComputationContext { |
Lines 152-178
Link Here
|
152 |
|
183 |
|
153 |
private ISourceReference fFirstType; |
184 |
private ISourceReference fFirstType; |
154 |
private boolean fHasHeaderComment; |
185 |
private boolean fHasHeaderComment; |
155 |
private LinkedHashMap fMap= new LinkedHashMap(); |
186 |
private LinkedHashMap fMap = new LinkedHashMap(); |
156 |
private IASTTranslationUnit fAST; |
187 |
private IASTTranslationUnit fAST; |
157 |
|
188 |
|
158 |
FoldingStructureComputationContext(IDocument document, ProjectionAnnotationModel model, boolean allowCollapsing) { |
189 |
FoldingStructureComputationContext(IDocument document, |
|
|
190 |
ProjectionAnnotationModel model, boolean allowCollapsing) { |
159 |
Assert.isNotNull(document); |
191 |
Assert.isNotNull(document); |
160 |
Assert.isNotNull(model); |
192 |
Assert.isNotNull(model); |
161 |
fDocument= document; |
193 |
fDocument = document; |
162 |
fModel= model; |
194 |
fModel = model; |
163 |
fAllowCollapsing= allowCollapsing; |
195 |
fAllowCollapsing = allowCollapsing; |
164 |
} |
196 |
} |
165 |
|
197 |
|
166 |
void setFirstType(ISourceReference reference) { |
198 |
void setFirstType(ISourceReference reference) { |
167 |
if (hasFirstType()) |
199 |
if (hasFirstType()) |
168 |
throw new IllegalStateException(); |
200 |
throw new IllegalStateException(); |
169 |
fFirstType= reference; |
201 |
fFirstType = reference; |
170 |
} |
202 |
} |
171 |
|
203 |
|
172 |
boolean hasFirstType() { |
204 |
boolean hasFirstType() { |
173 |
return fFirstType != null; |
205 |
return fFirstType != null; |
174 |
} |
206 |
} |
175 |
|
207 |
|
176 |
ISourceReference getFirstType() { |
208 |
ISourceReference getFirstType() { |
177 |
return fFirstType; |
209 |
return fFirstType; |
178 |
} |
210 |
} |
Lines 182-198
Link Here
|
182 |
} |
214 |
} |
183 |
|
215 |
|
184 |
void setHasHeaderComment() { |
216 |
void setHasHeaderComment() { |
185 |
fHasHeaderComment= true; |
217 |
fHasHeaderComment = true; |
186 |
} |
218 |
} |
187 |
|
219 |
|
188 |
/** |
220 |
/** |
189 |
* Returns <code>true</code> if newly created folding regions may be collapsed, |
221 |
* Returns <code>true</code> if newly created folding regions may be |
190 |
* <code>false</code> if not. This is usually <code>false</code> when updating the |
222 |
* collapsed, <code>false</code> if not. This is usually |
191 |
* folding structure while typing; it may be <code>true</code> when computing or restoring |
223 |
* <code>false</code> when updating the folding structure while |
192 |
* the initial folding structure. |
224 |
* typing; it may be <code>true</code> when computing or restoring the |
|
|
225 |
* initial folding structure. |
193 |
* |
226 |
* |
194 |
* @return <code>true</code> if newly created folding regions may be collapsed, |
227 |
* @return <code>true</code> if newly created folding regions may be |
195 |
* <code>false</code> if not |
228 |
* collapsed, <code>false</code> if not |
196 |
*/ |
229 |
*/ |
197 |
public boolean allowCollapsing() { |
230 |
public boolean allowCollapsing() { |
198 |
return fAllowCollapsing; |
231 |
return fAllowCollapsing; |
Lines 210-225
Link Here
|
210 |
ProjectionAnnotationModel getModel() { |
243 |
ProjectionAnnotationModel getModel() { |
211 |
return fModel; |
244 |
return fModel; |
212 |
} |
245 |
} |
213 |
|
246 |
|
214 |
/** |
247 |
/** |
215 |
* Adds a projection (folding) region to this context. The created annotation / position |
248 |
* Adds a projection (folding) region to this context. The created |
216 |
* pair will be added to the {@link ProjectionAnnotationModel} of the |
249 |
* annotation / position pair will be added to the |
217 |
* {@link ProjectionViewer} of the editor. |
250 |
* {@link ProjectionAnnotationModel} of the {@link ProjectionViewer} of |
|
|
251 |
* the editor. |
218 |
* |
252 |
* |
219 |
* @param annotation the annotation to add |
253 |
* @param annotation |
220 |
* @param position the corresponding position |
254 |
* the annotation to add |
|
|
255 |
* @param position |
256 |
* the corresponding position |
221 |
*/ |
257 |
*/ |
222 |
public void addProjectionRange(CProjectionAnnotation annotation, Position position) { |
258 |
public void addProjectionRange(CProjectionAnnotation annotation, |
|
|
259 |
Position position) { |
223 |
fMap.put(annotation, position); |
260 |
fMap.put(annotation, position); |
224 |
} |
261 |
} |
225 |
|
262 |
|
Lines 293-326
Link Here
|
293 |
return fAST; |
330 |
return fAST; |
294 |
} |
331 |
} |
295 |
} |
332 |
} |
296 |
|
|
|
297 |
|
333 |
|
298 |
private static class CProjectionAnnotation extends ProjectionAnnotation { |
334 |
private static class CProjectionAnnotation extends ProjectionAnnotation { |
299 |
|
335 |
|
300 |
public final static int COMMENT= 1; |
336 |
public final static int COMMENT = 1; |
301 |
public final static int BRANCH= 2; |
337 |
public final static int BRANCH = 2; |
302 |
|
338 |
|
303 |
private Object fKey; |
339 |
private Object fKey; |
304 |
private int fCategory; |
340 |
private int fCategory; |
305 |
|
341 |
|
306 |
public CProjectionAnnotation(boolean isCollapsed, Object key, boolean isComment) { |
342 |
public CProjectionAnnotation(boolean isCollapsed, Object key, |
|
|
343 |
boolean isComment) { |
307 |
this(isCollapsed, key, isComment ? COMMENT : 0); |
344 |
this(isCollapsed, key, isComment ? COMMENT : 0); |
308 |
} |
345 |
} |
309 |
|
346 |
|
310 |
public CProjectionAnnotation(boolean isCollapsed, Object key, int category) { |
347 |
public CProjectionAnnotation(boolean isCollapsed, Object key, |
|
|
348 |
int category) { |
311 |
super(isCollapsed); |
349 |
super(isCollapsed); |
312 |
fKey= key; |
350 |
fKey = key; |
313 |
fCategory= category; |
351 |
fCategory = category; |
314 |
} |
352 |
} |
315 |
|
353 |
|
316 |
public Object getElement() { |
354 |
public Object getElement() { |
317 |
return fKey; |
355 |
return fKey; |
318 |
} |
356 |
} |
319 |
|
357 |
|
320 |
public void setElement(Object element) { |
358 |
public void setElement(Object element) { |
321 |
fKey= element; |
359 |
fKey = element; |
322 |
} |
360 |
} |
323 |
|
361 |
|
324 |
public int getCategory() { |
362 |
public int getCategory() { |
325 |
return fCategory; |
363 |
return fCategory; |
326 |
} |
364 |
} |
Lines 332-369
Link Here
|
332 |
public boolean isComment() { |
370 |
public boolean isComment() { |
333 |
return fCategory == COMMENT; |
371 |
return fCategory == COMMENT; |
334 |
} |
372 |
} |
335 |
|
373 |
|
336 |
public void setIsComment(boolean isComment) { |
374 |
public void setIsComment(boolean isComment) { |
337 |
fCategory= isComment ? COMMENT : 0; |
375 |
fCategory = isComment ? COMMENT : 0; |
338 |
} |
376 |
} |
|
|
377 |
|
339 |
/* |
378 |
/* |
340 |
* @see java.lang.Object#toString() |
379 |
* @see java.lang.Object#toString() |
341 |
*/ |
380 |
*/ |
342 |
public String toString() { |
381 |
public String toString() { |
343 |
return "CProjectionAnnotation:\n" + //$NON-NLS-1$ |
382 |
return "CProjectionAnnotation:\n" + //$NON-NLS-1$ |
344 |
"\tkey: \t"+ fKey + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
383 |
"\tkey: \t" + fKey + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
345 |
"\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
384 |
"\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ |
346 |
"\tcomment: \t" + isComment() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ |
385 |
"\tcomment: \t" + isComment() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ |
347 |
} |
386 |
} |
348 |
} |
387 |
} |
349 |
|
|
|
350 |
|
388 |
|
351 |
private static final class Tuple { |
389 |
private static final class Tuple { |
352 |
CProjectionAnnotation annotation; |
390 |
CProjectionAnnotation annotation; |
353 |
Position position; |
391 |
Position position; |
|
|
392 |
|
354 |
Tuple(CProjectionAnnotation annotation, Position position) { |
393 |
Tuple(CProjectionAnnotation annotation, Position position) { |
355 |
this.annotation= annotation; |
394 |
this.annotation = annotation; |
356 |
this.position= position; |
395 |
this.position = position; |
357 |
} |
396 |
} |
358 |
} |
397 |
} |
359 |
|
398 |
|
360 |
|
|
|
361 |
/** |
399 |
/** |
362 |
* Projection position that will return two foldable regions: one folding away |
400 |
* Projection position that will return two foldable regions: one folding |
363 |
* the region from after the '/*' to the beginning of the content, the other |
401 |
* away the region from after the '/*' to the beginning of the content, the |
364 |
* from after the first content line until after the comment. |
402 |
* other from after the first content line until after the comment. |
365 |
*/ |
403 |
*/ |
366 |
private static final class CommentPosition extends Position implements IProjectionPosition { |
404 |
private static final class CommentPosition extends Position implements |
|
|
405 |
IProjectionPosition { |
367 |
CommentPosition(int offset, int length) { |
406 |
CommentPosition(int offset, int length) { |
368 |
super(offset, length); |
407 |
super(offset, length); |
369 |
} |
408 |
} |
Lines 371-401
Link Here
|
371 |
/* |
410 |
/* |
372 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) |
411 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) |
373 |
*/ |
412 |
*/ |
374 |
public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException { |
413 |
public IRegion[] computeProjectionRegions(IDocument document) |
375 |
DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length); |
414 |
throws BadLocationException { |
376 |
int prefixEnd= 0; |
415 |
DocumentCharacterIterator sequence = new DocumentCharacterIterator( |
377 |
int contentStart= findFirstContent(sequence, prefixEnd); |
416 |
document, offset, offset + length); |
378 |
|
417 |
int prefixEnd = 0; |
379 |
int firstLine= document.getLineOfOffset(offset + prefixEnd); |
418 |
int contentStart = findFirstContent(sequence, prefixEnd); |
380 |
int captionLine= document.getLineOfOffset(offset + contentStart); |
419 |
|
381 |
int lastLine= document.getLineOfOffset(offset + length); |
420 |
int firstLine = document.getLineOfOffset(offset + prefixEnd); |
382 |
|
421 |
int captionLine = document.getLineOfOffset(offset + contentStart); |
383 |
Assert.isTrue(firstLine <= captionLine, "first folded line is greater than the caption line"); //$NON-NLS-1$ |
422 |
int lastLine = document.getLineOfOffset(offset + length); |
384 |
Assert.isTrue(captionLine <= lastLine, "caption line is greater than the last folded line"); //$NON-NLS-1$ |
423 |
|
|
|
424 |
Assert.isTrue(firstLine <= captionLine, |
425 |
"first folded line is greater than the caption line"); //$NON-NLS-1$ |
426 |
Assert.isTrue(captionLine <= lastLine, |
427 |
"caption line is greater than the last folded line"); //$NON-NLS-1$ |
385 |
|
428 |
|
386 |
IRegion preRegion; |
429 |
IRegion preRegion; |
387 |
if (firstLine < captionLine) { |
430 |
if (firstLine < captionLine) { |
388 |
int preOffset= document.getLineOffset(firstLine); |
431 |
int preOffset = document.getLineOffset(firstLine); |
389 |
IRegion preEndLineInfo= document.getLineInformation(captionLine); |
432 |
IRegion preEndLineInfo = document |
390 |
int preEnd= preEndLineInfo.getOffset(); |
433 |
.getLineInformation(captionLine); |
391 |
preRegion= new Region(preOffset, preEnd - preOffset); |
434 |
int preEnd = preEndLineInfo.getOffset(); |
|
|
435 |
preRegion = new Region(preOffset, preEnd - preOffset); |
392 |
} else { |
436 |
} else { |
393 |
preRegion= null; |
437 |
preRegion = null; |
394 |
} |
438 |
} |
395 |
|
439 |
|
396 |
if (captionLine < lastLine) { |
440 |
if (captionLine < lastLine) { |
397 |
int postOffset= document.getLineOffset(captionLine + 1); |
441 |
int postOffset = document.getLineOffset(captionLine + 1); |
398 |
IRegion postRegion= new Region(postOffset, offset + length - postOffset); |
442 |
IRegion postRegion = new Region(postOffset, offset + length |
|
|
443 |
- postOffset); |
399 |
|
444 |
|
400 |
if (preRegion == null) |
445 |
if (preRegion == null) |
401 |
return new IRegion[] { postRegion }; |
446 |
return new IRegion[] { postRegion }; |
Lines 410-425
Link Here
|
410 |
} |
455 |
} |
411 |
|
456 |
|
412 |
/** |
457 |
/** |
413 |
* Finds the offset of the first identifier part within <code>content</code>. |
458 |
* Finds the offset of the first identifier part within |
414 |
* Returns 0 if none is found. |
459 |
* <code>content</code>. Returns 0 if none is found. |
415 |
* |
460 |
* |
416 |
* @param content the content to search |
461 |
* @param content |
417 |
* @return the first index of a unicode identifier part, or zero if none can |
462 |
* the content to search |
418 |
* be found |
463 |
* @return the first index of a unicode identifier part, or zero if none |
|
|
464 |
* can be found |
419 |
*/ |
465 |
*/ |
420 |
private int findFirstContent(final CharSequence content, int prefixEnd) { |
466 |
private int findFirstContent(final CharSequence content, int prefixEnd) { |
421 |
int lenght= content.length(); |
467 |
int lenght = content.length(); |
422 |
for (int i= prefixEnd; i < lenght; i++) { |
468 |
for (int i = prefixEnd; i < lenght; i++) { |
423 |
if (Character.isUnicodeIdentifierPart(content.charAt(i))) |
469 |
if (Character.isUnicodeIdentifierPart(content.charAt(i))) |
424 |
return i; |
470 |
return i; |
425 |
} |
471 |
} |
Lines 430-506
Link Here
|
430 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) |
476 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) |
431 |
*/ |
477 |
*/ |
432 |
public int computeCaptionOffset(IDocument document) { |
478 |
public int computeCaptionOffset(IDocument document) { |
433 |
// return 0; |
479 |
// return 0; |
434 |
DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length); |
480 |
DocumentCharacterIterator sequence = new DocumentCharacterIterator( |
|
|
481 |
document, offset, offset + length); |
435 |
return findFirstContent(sequence, 0); |
482 |
return findFirstContent(sequence, 0); |
436 |
} |
483 |
} |
437 |
} |
484 |
} |
438 |
|
485 |
|
439 |
/** |
486 |
/** |
440 |
* Projection position that will return two foldable regions: one folding away |
487 |
* Projection position that will return two foldable regions: one folding |
441 |
* the lines before the one containing the simple name of the C element, one |
488 |
* away the lines before the one containing the simple name of the C |
442 |
* folding away any lines after the caption. |
489 |
* element, one folding away any lines after the caption. |
443 |
*/ |
490 |
*/ |
444 |
private static final class CElementPosition extends Position implements IProjectionPosition { |
491 |
private static final class CElementPosition extends Position implements |
|
|
492 |
IProjectionPosition { |
445 |
|
493 |
|
446 |
private ICElement fElement; |
494 |
private ICElement fElement; |
447 |
|
495 |
|
448 |
public CElementPosition(int offset, int length, ICElement element) { |
496 |
public CElementPosition(int offset, int length, ICElement element) { |
449 |
super(offset, length); |
497 |
super(offset, length); |
450 |
Assert.isNotNull(element); |
498 |
Assert.isNotNull(element); |
451 |
fElement= element; |
499 |
fElement = element; |
452 |
} |
500 |
} |
453 |
|
501 |
|
454 |
public void setElement(ICElement member) { |
502 |
public void setElement(ICElement member) { |
455 |
Assert.isNotNull(member); |
503 |
Assert.isNotNull(member); |
456 |
fElement= member; |
504 |
fElement = member; |
457 |
} |
505 |
} |
458 |
|
506 |
|
459 |
/* |
507 |
/* |
460 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) |
508 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) |
461 |
*/ |
509 |
*/ |
462 |
public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException { |
510 |
public IRegion[] computeProjectionRegions(IDocument document) |
463 |
int nameStart= offset; |
511 |
throws BadLocationException { |
|
|
512 |
int nameStart = offset; |
464 |
try { |
513 |
try { |
465 |
/* The member's name range may not be correct. However, |
514 |
/* |
|
|
515 |
* The member's name range may not be correct. However, |
466 |
* reconciling would trigger another element delta which would |
516 |
* reconciling would trigger another element delta which would |
467 |
* lead to reentrant situations. Therefore, we optimistically |
517 |
* lead to reentrant situations. Therefore, we optimistically |
468 |
* assume that the name range is correct, but double check the |
518 |
* assume that the name range is correct, but double check the |
469 |
* received lines below. */ |
519 |
* received lines below. |
|
|
520 |
*/ |
470 |
if (fElement instanceof ISourceReference) { |
521 |
if (fElement instanceof ISourceReference) { |
471 |
ISourceRange sourceRange= ((ISourceReference) fElement).getSourceRange(); |
522 |
ISourceRange sourceRange = ((ISourceReference) fElement) |
|
|
523 |
.getSourceRange(); |
472 |
if (sourceRange != null) |
524 |
if (sourceRange != null) |
473 |
nameStart= sourceRange.getIdStartPos(); |
525 |
nameStart = sourceRange.getIdStartPos(); |
474 |
} |
526 |
} |
475 |
} catch (CModelException e) { |
527 |
} catch (CModelException e) { |
476 |
// ignore and use default |
528 |
// ignore and use default |
477 |
} |
529 |
} |
478 |
|
530 |
|
479 |
int firstLine= document.getLineOfOffset(offset); |
531 |
int firstLine = document.getLineOfOffset(offset); |
480 |
int captionLine= document.getLineOfOffset(nameStart); |
532 |
int captionLine = document.getLineOfOffset(nameStart); |
481 |
int lastLine= document.getLineOfOffset(offset + length); |
533 |
int lastLine = document.getLineOfOffset(offset + length); |
482 |
|
534 |
|
483 |
/* see comment above - adjust the caption line to be inside the |
535 |
/* |
|
|
536 |
* see comment above - adjust the caption line to be inside the |
484 |
* entire folded region, and rely on later element deltas to correct |
537 |
* entire folded region, and rely on later element deltas to correct |
485 |
* the name range. */ |
538 |
* the name range. |
|
|
539 |
*/ |
486 |
if (captionLine < firstLine) |
540 |
if (captionLine < firstLine) |
487 |
captionLine= firstLine; |
541 |
captionLine = firstLine; |
488 |
if (captionLine > lastLine) |
542 |
if (captionLine > lastLine) |
489 |
captionLine= lastLine; |
543 |
captionLine = lastLine; |
490 |
|
544 |
|
491 |
IRegion preRegion; |
545 |
IRegion preRegion; |
492 |
if (firstLine < captionLine) { |
546 |
if (firstLine < captionLine) { |
493 |
int preOffset= document.getLineOffset(firstLine); |
547 |
int preOffset = document.getLineOffset(firstLine); |
494 |
IRegion preEndLineInfo= document.getLineInformation(captionLine); |
548 |
IRegion preEndLineInfo = document |
495 |
int preEnd= preEndLineInfo.getOffset(); |
549 |
.getLineInformation(captionLine); |
496 |
preRegion= new Region(preOffset, preEnd - preOffset); |
550 |
int preEnd = preEndLineInfo.getOffset(); |
|
|
551 |
preRegion = new Region(preOffset, preEnd - preOffset); |
497 |
} else { |
552 |
} else { |
498 |
preRegion= null; |
553 |
preRegion = null; |
499 |
} |
554 |
} |
500 |
|
555 |
|
501 |
if (captionLine < lastLine) { |
556 |
if (captionLine < lastLine) { |
502 |
int postOffset= document.getLineOffset(captionLine + 1); |
557 |
int postOffset = document.getLineOffset(captionLine + 1); |
503 |
IRegion postRegion= new Region(postOffset, offset + length - postOffset); |
558 |
IRegion postRegion = new Region(postOffset, offset + length |
|
|
559 |
- postOffset); |
504 |
|
560 |
|
505 |
if (preRegion == null) |
561 |
if (preRegion == null) |
506 |
return new IRegion[] { postRegion }; |
562 |
return new IRegion[] { postRegion }; |
Lines 517-530
Link Here
|
517 |
/* |
573 |
/* |
518 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) |
574 |
* @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) |
519 |
*/ |
575 |
*/ |
520 |
public int computeCaptionOffset(IDocument document) throws BadLocationException { |
576 |
public int computeCaptionOffset(IDocument document) |
521 |
int nameStart= offset; |
577 |
throws BadLocationException { |
|
|
578 |
int nameStart = offset; |
522 |
try { |
579 |
try { |
523 |
// need a reconcile here? |
580 |
// need a reconcile here? |
524 |
if (fElement instanceof ISourceReference) { |
581 |
if (fElement instanceof ISourceReference) { |
525 |
ISourceRange sourceRange= ((ISourceReference) fElement).getSourceRange(); |
582 |
ISourceRange sourceRange = ((ISourceReference) fElement) |
|
|
583 |
.getSourceRange(); |
526 |
if (sourceRange != null) |
584 |
if (sourceRange != null) |
527 |
nameStart= sourceRange.getIdStartPos(); |
585 |
nameStart = sourceRange.getIdStartPos(); |
528 |
} |
586 |
} |
529 |
} catch (CModelException e) { |
587 |
} catch (CModelException e) { |
530 |
// ignore and use default |
588 |
// ignore and use default |
Lines 534-540
Link Here
|
534 |
} |
592 |
} |
535 |
|
593 |
|
536 |
} |
594 |
} |
537 |
|
595 |
|
538 |
/** |
596 |
/** |
539 |
* Internal projection listener. |
597 |
* Internal projection listener. |
540 |
*/ |
598 |
*/ |
Lines 544-567
Link Here
|
544 |
/** |
602 |
/** |
545 |
* Registers the listener with the viewer. |
603 |
* Registers the listener with the viewer. |
546 |
* |
604 |
* |
547 |
* @param viewer the viewer to register a listener with |
605 |
* @param viewer |
|
|
606 |
* the viewer to register a listener with |
548 |
*/ |
607 |
*/ |
549 |
public ProjectionListener(ProjectionViewer viewer) { |
608 |
public ProjectionListener(ProjectionViewer viewer) { |
550 |
Assert.isLegal(viewer != null); |
609 |
Assert.isLegal(viewer != null); |
551 |
fViewer= viewer; |
610 |
fViewer = viewer; |
552 |
fViewer.addProjectionListener(this); |
611 |
fViewer.addProjectionListener(this); |
553 |
} |
612 |
} |
554 |
|
613 |
|
555 |
/** |
614 |
/** |
556 |
* Disposes of this listener and removes the projection listener from the viewer. |
615 |
* Disposes of this listener and removes the projection listener from |
|
|
616 |
* the viewer. |
557 |
*/ |
617 |
*/ |
558 |
public void dispose() { |
618 |
public void dispose() { |
559 |
if (fViewer != null) { |
619 |
if (fViewer != null) { |
560 |
fViewer.removeProjectionListener(this); |
620 |
fViewer.removeProjectionListener(this); |
561 |
fViewer= null; |
621 |
fViewer = null; |
562 |
} |
622 |
} |
563 |
} |
623 |
} |
564 |
|
624 |
|
565 |
/* |
625 |
/* |
566 |
* @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled() |
626 |
* @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled() |
567 |
*/ |
627 |
*/ |
Lines 578-590
Link Here
|
578 |
} |
638 |
} |
579 |
|
639 |
|
580 |
/** |
640 |
/** |
581 |
* Implementation of <code>IRegion</code> that can be reused |
641 |
* Implementation of <code>IRegion</code> that can be reused by setting |
582 |
* by setting the offset and the length. |
642 |
* the offset and the length. |
583 |
*/ |
643 |
*/ |
584 |
private static class ModifiableRegion extends Position implements IRegion { |
644 |
private static class ModifiableRegion extends Position implements IRegion { |
585 |
ModifiableRegion() { |
645 |
ModifiableRegion() { |
586 |
super(); |
646 |
super(); |
587 |
} |
647 |
} |
|
|
648 |
|
588 |
ModifiableRegion(int offset, int length) { |
649 |
ModifiableRegion(int offset, int length) { |
589 |
super(offset, length); |
650 |
super(offset, length); |
590 |
} |
651 |
} |
Lines 604-610
Link Here
|
604 |
*/ |
665 |
*/ |
605 |
Branch(int offset, boolean taken) { |
666 |
Branch(int offset, boolean taken) { |
606 |
super(offset, 0); |
667 |
super(offset, 0); |
607 |
fTaken= taken; |
668 |
fTaken = taken; |
608 |
} |
669 |
} |
609 |
|
670 |
|
610 |
/** |
671 |
/** |
Lines 614-620
Link Here
|
614 |
*/ |
675 |
*/ |
615 |
Branch(int offset, int length, boolean taken) { |
676 |
Branch(int offset, int length, boolean taken) { |
616 |
super(offset, length); |
677 |
super(offset, length); |
617 |
fTaken= taken; |
678 |
fTaken = taken; |
618 |
} |
679 |
} |
619 |
|
680 |
|
620 |
public void setEndOffset(int endOffset) { |
681 |
public void setEndOffset(int endOffset) { |
Lines 626-685
Link Here
|
626 |
} |
687 |
} |
627 |
|
688 |
|
628 |
public void setInclusive(boolean inclusive) { |
689 |
public void setInclusive(boolean inclusive) { |
629 |
fInclusive= inclusive; |
690 |
fInclusive = inclusive; |
630 |
} |
691 |
} |
631 |
} |
692 |
} |
632 |
|
693 |
|
633 |
private final static boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/folding")); //$NON-NLS-1$//$NON-NLS-2$; |
694 |
private final static boolean DEBUG = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/folding")); //$NON-NLS-1$//$NON-NLS-2$; |
634 |
|
695 |
|
635 |
private ITextEditor fEditor; |
696 |
private ITextEditor fEditor; |
636 |
private ProjectionListener fProjectionListener; |
697 |
private ProjectionListener fProjectionListener; |
637 |
protected ICElement fInput; |
698 |
protected ICElement fInput; |
638 |
private IElementChangedListener fElementListener; |
699 |
private IElementChangedListener fElementListener; |
639 |
|
700 |
|
640 |
private boolean fCollapseHeaderComments= true; |
701 |
private boolean fCollapseHeaderComments = true; |
641 |
private boolean fCollapseComments= false; |
702 |
private boolean fCollapseComments = false; |
642 |
private boolean fCollapseMacros= false; |
703 |
private boolean fCollapseMacros = false; |
643 |
private boolean fCollapseFunctions= true; |
704 |
private boolean fCollapseFunctions = true; |
644 |
private boolean fCollapseStructures= true; |
705 |
private boolean fCollapseStructures = true; |
645 |
private boolean fCollapseMethods= false; |
706 |
private boolean fCollapseMethods = false; |
646 |
private boolean fCollapseInactiveCode= true; |
707 |
private boolean fCollapseInactiveCode = true; |
647 |
|
708 |
|
648 |
private int fMinCommentLines= 1; |
709 |
private int fMinCommentLines = 1; |
649 |
private boolean fPreprocessorBranchFoldingEnabled= true; |
710 |
private boolean fPreprocessorBranchFoldingEnabled = true; |
650 |
private boolean fCommentFoldingEnabled= true; |
711 |
private boolean fStatementsFoldingEnabled = false; |
|
|
712 |
private boolean fCommentFoldingEnabled = true; |
651 |
|
713 |
|
652 |
private ICReconcilingListener fReconilingListener; |
714 |
private ICReconcilingListener fReconilingListener; |
653 |
boolean fInitialReconcilePending= true; |
715 |
boolean fInitialReconcilePending = true; |
654 |
|
716 |
|
655 |
private int fCursorPosition; |
717 |
private int fCursorPosition; |
656 |
|
718 |
|
657 |
private SelectionListener fSelectionListener; |
719 |
private SelectionListener fSelectionListener; |
658 |
|
720 |
|
659 |
|
|
|
660 |
/** |
721 |
/** |
661 |
* Creates a new folding provider. It must be |
722 |
* Creates a new folding provider. It must be |
662 |
* {@link #install(ITextEditor, ProjectionViewer) installed} on an editor/viewer pair before it |
723 |
* {@link #install(ITextEditor, ProjectionViewer) installed} on an |
663 |
* can be used, and {@link #uninstall() uninstalled} when not used any longer. |
724 |
* editor/viewer pair before it can be used, and |
|
|
725 |
* {@link #uninstall() uninstalled} when not used any longer. |
664 |
* <p> |
726 |
* <p> |
665 |
* The projection state may be reset by calling {@link #initialize()}. |
727 |
* The projection state may be reset by calling {@link #initialize()}. |
666 |
* </p> |
728 |
* </p> |
667 |
*/ |
729 |
*/ |
668 |
public DefaultCFoldingStructureProvider() { |
730 |
public DefaultCFoldingStructureProvider() { |
669 |
} |
731 |
} |
670 |
|
732 |
|
671 |
/* |
733 |
/* |
672 |
* @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#install(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.projection.ProjectionViewer) |
734 |
* @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#install(org.eclipse.ui.texteditor.ITextEditor, |
|
|
735 |
* org.eclipse.jface.text.source.projection.ProjectionViewer) |
673 |
*/ |
736 |
*/ |
674 |
public void install(ITextEditor editor, ProjectionViewer viewer) { |
737 |
public void install(ITextEditor editor, ProjectionViewer viewer) { |
675 |
Assert.isLegal(editor != null); |
738 |
Assert.isLegal(editor != null); |
676 |
Assert.isLegal(viewer != null); |
739 |
Assert.isLegal(viewer != null); |
677 |
|
740 |
|
678 |
internalUninstall(); |
741 |
internalUninstall(); |
679 |
|
742 |
|
680 |
if (editor instanceof CEditor) { |
743 |
if (editor instanceof CEditor) { |
681 |
fEditor= editor; |
744 |
fEditor = editor; |
682 |
fProjectionListener= new ProjectionListener(viewer); |
745 |
fProjectionListener = new ProjectionListener(viewer); |
683 |
} |
746 |
} |
684 |
} |
747 |
} |
685 |
|
748 |
|
Lines 689-695
Link Here
|
689 |
public void uninstall() { |
752 |
public void uninstall() { |
690 |
internalUninstall(); |
753 |
internalUninstall(); |
691 |
} |
754 |
} |
692 |
|
755 |
|
693 |
/** |
756 |
/** |
694 |
* Internal implementation of {@link #uninstall()}. |
757 |
* Internal implementation of {@link #uninstall()}. |
695 |
*/ |
758 |
*/ |
Lines 697-765
Link Here
|
697 |
if (isInstalled()) { |
760 |
if (isInstalled()) { |
698 |
handleProjectionDisabled(); |
761 |
handleProjectionDisabled(); |
699 |
fProjectionListener.dispose(); |
762 |
fProjectionListener.dispose(); |
700 |
fProjectionListener= null; |
763 |
fProjectionListener = null; |
701 |
fEditor= null; |
764 |
fEditor = null; |
702 |
} |
765 |
} |
703 |
} |
766 |
} |
704 |
|
767 |
|
705 |
/** |
768 |
/** |
706 |
* Returns <code>true</code> if the provider is installed, <code>false</code> otherwise. |
769 |
* Returns <code>true</code> if the provider is installed, |
|
|
770 |
* <code>false</code> otherwise. |
707 |
* |
771 |
* |
708 |
* @return <code>true</code> if the provider is installed, <code>false</code> otherwise |
772 |
* @return <code>true</code> if the provider is installed, |
|
|
773 |
* <code>false</code> otherwise |
709 |
*/ |
774 |
*/ |
710 |
protected final boolean isInstalled() { |
775 |
protected final boolean isInstalled() { |
711 |
return fEditor != null; |
776 |
return fEditor != null; |
712 |
} |
777 |
} |
713 |
|
778 |
|
714 |
/** |
779 |
/** |
715 |
* Called whenever projection is enabled, for example when the viewer issues a |
780 |
* Called whenever projection is enabled, for example when the viewer issues |
716 |
* {@link IProjectionListener#projectionEnabled() projectionEnabled} message. When the provider |
781 |
* a {@link IProjectionListener#projectionEnabled() projectionEnabled} |
717 |
* is already enabled when this method is called, it is first |
782 |
* message. When the provider is already enabled when this method is called, |
718 |
* {@link #handleProjectionDisabled() disabled}. |
783 |
* it is first {@link #handleProjectionDisabled() disabled}. |
719 |
* <p> |
784 |
* <p> |
720 |
* Subclasses may extend. |
785 |
* Subclasses may extend. |
721 |
* </p> |
786 |
* </p> |
722 |
*/ |
787 |
*/ |
723 |
protected void handleProjectionEnabled() { |
788 |
protected void handleProjectionEnabled() { |
724 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.handleProjectionEnabled()"); //$NON-NLS-1$ |
789 |
if (DEBUG) |
725 |
// projectionEnabled messages are not always paired with projectionDisabled |
790 |
System.out |
|
|
791 |
.println("DefaultCFoldingStructureProvider.handleProjectionEnabled()"); //$NON-NLS-1$ |
792 |
// projectionEnabled messages are not always paired with |
793 |
// projectionDisabled |
726 |
// i.e. multiple enabled messages may be sent out. |
794 |
// i.e. multiple enabled messages may be sent out. |
727 |
// we have to make sure that we disable first when getting an enable |
795 |
// we have to make sure that we disable first when getting an enable |
728 |
// message. |
796 |
// message. |
729 |
handleProjectionDisabled(); |
797 |
handleProjectionDisabled(); |
730 |
|
798 |
|
731 |
if (fEditor instanceof CEditor) { |
799 |
if (fEditor instanceof CEditor) { |
732 |
fInitialReconcilePending= true; |
800 |
fInitialReconcilePending = true; |
733 |
initialize(); |
801 |
initialize(); |
734 |
fReconilingListener= new PreprocessorBranchesReconciler(); |
802 |
fReconilingListener = new PreprocessorBranchesReconciler(); |
735 |
((CEditor)fEditor).addReconcileListener(fReconilingListener); |
803 |
((CEditor) fEditor).addReconcileListener(fReconilingListener); |
736 |
fSelectionListener= new SelectionListener(); |
804 |
fSelectionListener = new SelectionListener(); |
737 |
fEditor.getSelectionProvider().addSelectionChangedListener(fSelectionListener); |
805 |
fEditor.getSelectionProvider().addSelectionChangedListener( |
|
|
806 |
fSelectionListener); |
738 |
} |
807 |
} |
739 |
} |
808 |
} |
740 |
|
809 |
|
741 |
/** |
810 |
/** |
742 |
* Called whenever projection is disabled, for example when the provider is |
811 |
* Called whenever projection is disabled, for example when the provider is |
743 |
* {@link #uninstall() uninstalled}, when the viewer issues a |
812 |
* {@link #uninstall() uninstalled}, when the viewer issues a |
744 |
* {@link IProjectionListener#projectionDisabled() projectionDisabled} message and before |
813 |
* {@link IProjectionListener#projectionDisabled() projectionDisabled} |
745 |
* {@link #handleProjectionEnabled() enabling} the provider. Implementations must be prepared to |
814 |
* message and before {@link #handleProjectionEnabled() enabling} the |
746 |
* handle multiple calls to this method even if the provider is already disabled. |
815 |
* provider. Implementations must be prepared to handle multiple calls to |
|
|
816 |
* this method even if the provider is already disabled. |
747 |
* <p> |
817 |
* <p> |
748 |
* Subclasses may extend. |
818 |
* Subclasses may extend. |
749 |
* </p> |
819 |
* </p> |
750 |
*/ |
820 |
*/ |
751 |
protected void handleProjectionDisabled() { |
821 |
protected void handleProjectionDisabled() { |
752 |
if (fElementListener != null) { |
822 |
if (fElementListener != null) { |
753 |
CoreModel.getDefault().removeElementChangedListener(fElementListener); |
823 |
CoreModel.getDefault().removeElementChangedListener( |
754 |
fElementListener= null; |
824 |
fElementListener); |
|
|
825 |
fElementListener = null; |
755 |
} |
826 |
} |
756 |
if (fReconilingListener != null) { |
827 |
if (fReconilingListener != null) { |
757 |
((CEditor)fEditor).removeReconcileListener(fReconilingListener); |
828 |
((CEditor) fEditor).removeReconcileListener(fReconilingListener); |
758 |
fReconilingListener= null; |
829 |
fReconilingListener = null; |
759 |
} |
830 |
} |
760 |
if (fSelectionListener != null) { |
831 |
if (fSelectionListener != null) { |
761 |
fEditor.getSelectionProvider().removeSelectionChangedListener(fSelectionListener); |
832 |
fEditor.getSelectionProvider().removeSelectionChangedListener( |
762 |
fSelectionListener= null; |
833 |
fSelectionListener); |
|
|
834 |
fSelectionListener = null; |
763 |
} |
835 |
} |
764 |
} |
836 |
} |
765 |
|
837 |
|
Lines 767-873
Link Here
|
767 |
* @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#initialize() |
839 |
* @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#initialize() |
768 |
*/ |
840 |
*/ |
769 |
public final void initialize() { |
841 |
public final void initialize() { |
770 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.initialize()"); //$NON-NLS-1$ |
842 |
if (DEBUG) |
|
|
843 |
System.out.println("DefaultCFoldingStructureProvider.initialize()"); //$NON-NLS-1$ |
771 |
update(createInitialContext()); |
844 |
update(createInitialContext()); |
772 |
} |
845 |
} |
773 |
|
846 |
|
774 |
private FoldingStructureComputationContext createInitialContext() { |
847 |
private FoldingStructureComputationContext createInitialContext() { |
775 |
initializePreferences(); |
848 |
initializePreferences(); |
776 |
fInput= getInputElement(); |
849 |
fInput = getInputElement(); |
777 |
if (fInput == null) |
850 |
if (fInput == null) |
778 |
return null; |
851 |
return null; |
779 |
|
852 |
|
780 |
return createContext(true); |
853 |
return createContext(true); |
781 |
} |
854 |
} |
782 |
|
855 |
|
783 |
private FoldingStructureComputationContext createContext(boolean allowCollapse) { |
856 |
private FoldingStructureComputationContext createContext( |
|
|
857 |
boolean allowCollapse) { |
784 |
if (!isInstalled()) |
858 |
if (!isInstalled()) |
785 |
return null; |
859 |
return null; |
786 |
ProjectionAnnotationModel model= getModel(); |
860 |
ProjectionAnnotationModel model = getModel(); |
787 |
if (model == null) |
861 |
if (model == null) |
788 |
return null; |
862 |
return null; |
789 |
IDocument doc= getDocument(); |
863 |
IDocument doc = getDocument(); |
790 |
if (doc == null) |
864 |
if (doc == null) |
791 |
return null; |
865 |
return null; |
792 |
|
866 |
|
793 |
return new FoldingStructureComputationContext(doc, model, allowCollapse); |
867 |
return new FoldingStructureComputationContext(doc, model, allowCollapse); |
794 |
} |
868 |
} |
795 |
|
869 |
|
796 |
private ICElement getInputElement() { |
870 |
private ICElement getInputElement() { |
797 |
if (fEditor instanceof CEditor) { |
871 |
if (fEditor instanceof CEditor) { |
798 |
return ((CEditor)fEditor).getInputCElement(); |
872 |
return ((CEditor) fEditor).getInputCElement(); |
799 |
} |
873 |
} |
800 |
return null; |
874 |
return null; |
801 |
} |
875 |
} |
802 |
|
876 |
|
803 |
private void initializePreferences() { |
877 |
private void initializePreferences() { |
804 |
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); |
878 |
IPreferenceStore store = CUIPlugin.getDefault().getPreferenceStore(); |
805 |
fCollapseFunctions= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS); |
879 |
fCollapseFunctions = store |
806 |
fCollapseStructures= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES); |
880 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS); |
807 |
fCollapseMacros= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS); |
881 |
fCollapseStructures = store |
808 |
fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS); |
882 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES); |
809 |
fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS); |
883 |
fCollapseMacros = store |
810 |
fCollapseComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS); |
884 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS); |
811 |
fCollapseInactiveCode= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE); |
885 |
fCollapseMethods = store |
812 |
fPreprocessorBranchFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); |
886 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS); |
813 |
fCommentFoldingEnabled= true; |
887 |
fCollapseHeaderComments = store |
|
|
888 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS); |
889 |
fCollapseComments = store |
890 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS); |
891 |
fCollapseInactiveCode = store |
892 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE); |
893 |
fPreprocessorBranchFoldingEnabled = store |
894 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); |
895 |
fStatementsFoldingEnabled = store |
896 |
.getBoolean(PreferenceConstants.EDITOR_FOLDING_STATEMENTS); |
897 |
fCommentFoldingEnabled = true; |
814 |
} |
898 |
} |
815 |
|
899 |
|
816 |
private void update(FoldingStructureComputationContext ctx) { |
900 |
private void update(FoldingStructureComputationContext ctx) { |
817 |
if (ctx == null) |
901 |
if (ctx == null) |
818 |
return; |
902 |
return; |
819 |
|
903 |
|
820 |
if (!fInitialReconcilePending && fSelectionListener != null) { |
904 |
if (!fInitialReconcilePending && fSelectionListener != null) { |
821 |
fEditor.getSelectionProvider().removeSelectionChangedListener(fSelectionListener); |
905 |
fEditor.getSelectionProvider().removeSelectionChangedListener( |
822 |
fSelectionListener= null; |
906 |
fSelectionListener); |
|
|
907 |
fSelectionListener = null; |
823 |
} |
908 |
} |
824 |
|
909 |
|
825 |
Map additions= new HashMap(); |
910 |
Map additions = new HashMap(); |
826 |
List deletions= new ArrayList(); |
911 |
List deletions = new ArrayList(); |
827 |
List updates= new ArrayList(); |
912 |
List updates = new ArrayList(); |
828 |
|
913 |
|
829 |
computeFoldingStructure(ctx); |
914 |
computeFoldingStructure(ctx); |
830 |
Map updated= ctx.fMap; |
915 |
Map updated = ctx.fMap; |
831 |
Map previous= computeCurrentStructure(ctx); |
916 |
Map previous = computeCurrentStructure(ctx); |
832 |
|
917 |
|
833 |
Iterator e= updated.keySet().iterator(); |
918 |
Iterator e = updated.keySet().iterator(); |
834 |
while (e.hasNext()) { |
919 |
while (e.hasNext()) { |
835 |
CProjectionAnnotation newAnnotation= (CProjectionAnnotation) e.next(); |
920 |
CProjectionAnnotation newAnnotation = (CProjectionAnnotation) e |
836 |
Object key= newAnnotation.getElement(); |
921 |
.next(); |
837 |
Position newPosition= (Position) updated.get(newAnnotation); |
922 |
Object key = newAnnotation.getElement(); |
|
|
923 |
Position newPosition = (Position) updated.get(newAnnotation); |
838 |
|
924 |
|
839 |
List annotations= (List) previous.get(key); |
925 |
List annotations = (List) previous.get(key); |
840 |
if (annotations == null) { |
926 |
if (annotations == null) { |
841 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ |
927 |
if (DEBUG) |
|
|
928 |
System.out |
929 |
.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ |
842 |
|
930 |
|
843 |
additions.put(newAnnotation, newPosition); |
931 |
additions.put(newAnnotation, newPosition); |
844 |
|
932 |
|
845 |
} else { |
933 |
} else { |
846 |
Iterator x= annotations.iterator(); |
934 |
Iterator x = annotations.iterator(); |
847 |
boolean matched= false; |
935 |
boolean matched = false; |
848 |
while (x.hasNext()) { |
936 |
while (x.hasNext()) { |
849 |
Tuple tuple= (Tuple) x.next(); |
937 |
Tuple tuple = (Tuple) x.next(); |
850 |
CProjectionAnnotation existingAnnotation= tuple.annotation; |
938 |
CProjectionAnnotation existingAnnotation = tuple.annotation; |
851 |
Position existingPosition= tuple.position; |
939 |
Position existingPosition = tuple.position; |
852 |
if (newAnnotation.isComment() == existingAnnotation.isComment()) { |
940 |
if (newAnnotation.isComment() == existingAnnotation |
853 |
if (existingPosition != null && (!newPosition.equals(existingPosition) || ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed())) { |
941 |
.isComment()) { |
|
|
942 |
if (existingPosition != null |
943 |
&& (!newPosition.equals(existingPosition) || ctx |
944 |
.allowCollapsing() |
945 |
&& existingAnnotation.isCollapsed() != newAnnotation |
946 |
.isCollapsed())) { |
854 |
existingPosition.setOffset(newPosition.getOffset()); |
947 |
existingPosition.setOffset(newPosition.getOffset()); |
855 |
existingPosition.setLength(newPosition.getLength()); |
948 |
existingPosition.setLength(newPosition.getLength()); |
856 |
if (ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed()) |
949 |
if (ctx.allowCollapsing() |
857 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$ |
950 |
&& existingAnnotation.isCollapsed() != newAnnotation |
858 |
if (newAnnotation.isCollapsed()) |
951 |
.isCollapsed()) |
859 |
existingAnnotation.markCollapsed(); |
952 |
if (DEBUG) |
860 |
else |
953 |
System.out |
861 |
existingAnnotation.markExpanded(); |
954 |
.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$ |
|
|
955 |
if (newAnnotation.isCollapsed()) |
956 |
existingAnnotation.markCollapsed(); |
957 |
else |
958 |
existingAnnotation.markExpanded(); |
862 |
updates.add(existingAnnotation); |
959 |
updates.add(existingAnnotation); |
863 |
} |
960 |
} |
864 |
matched= true; |
961 |
matched = true; |
865 |
x.remove(); |
962 |
x.remove(); |
866 |
break; |
963 |
break; |
867 |
} |
964 |
} |
868 |
} |
965 |
} |
869 |
if (!matched) { |
966 |
if (!matched) { |
870 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ |
967 |
if (DEBUG) |
|
|
968 |
System.out |
969 |
.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ |
871 |
|
970 |
|
872 |
additions.put(newAnnotation, newPosition); |
971 |
additions.put(newAnnotation, newPosition); |
873 |
} |
972 |
} |
Lines 876-948
Link Here
|
876 |
} |
975 |
} |
877 |
} |
976 |
} |
878 |
|
977 |
|
879 |
e= previous.values().iterator(); |
978 |
e = previous.values().iterator(); |
880 |
while (e.hasNext()) { |
979 |
while (e.hasNext()) { |
881 |
List list= (List) e.next(); |
980 |
List list = (List) e.next(); |
882 |
int size= list.size(); |
981 |
int size = list.size(); |
883 |
for (int i= 0; i < size; i++) { |
982 |
for (int i = 0; i < size; i++) { |
884 |
CProjectionAnnotation annotation= ((Tuple) list.get(i)).annotation; |
983 |
CProjectionAnnotation annotation = ((Tuple) list.get(i)).annotation; |
885 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + annotation); //$NON-NLS-1$ |
984 |
if (DEBUG) |
|
|
985 |
System.out |
986 |
.println("DefaultCFoldingStructureProvider.update() deleted annotation " + annotation); //$NON-NLS-1$ |
886 |
deletions.add(annotation); |
987 |
deletions.add(annotation); |
887 |
} |
988 |
} |
888 |
} |
989 |
} |
889 |
|
990 |
|
890 |
match(deletions, additions, updates, ctx); |
991 |
match(deletions, additions, updates, ctx); |
891 |
|
992 |
|
892 |
Annotation[] removals= new Annotation[deletions.size()]; |
993 |
Annotation[] removals = new Annotation[deletions.size()]; |
893 |
deletions.toArray(removals); |
994 |
deletions.toArray(removals); |
894 |
Annotation[] changes= new Annotation[updates.size()]; |
995 |
Annotation[] changes = new Annotation[updates.size()]; |
895 |
updates.toArray(changes); |
996 |
updates.toArray(changes); |
896 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() "+removals.length+" deleted, "+additions.size()+" added, "+changes.length+" changed"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
997 |
if (DEBUG) |
|
|
998 |
System.out |
999 |
.println("DefaultCFoldingStructureProvider.update() " + removals.length + " deleted, " + additions.size() + " added, " + changes.length + " changed"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
897 |
ctx.getModel().modifyAnnotations(removals, additions, changes); |
1000 |
ctx.getModel().modifyAnnotations(removals, additions, changes); |
898 |
} |
1001 |
} |
899 |
|
1002 |
|
900 |
/** |
1003 |
/** |
901 |
* Matches deleted annotations to changed or added ones. A deleted |
1004 |
* Matches deleted annotations to changed or added ones. A deleted |
902 |
* annotation/position tuple that has a matching addition / change |
1005 |
* annotation/position tuple that has a matching addition / change is |
903 |
* is updated and marked as changed. The matching tuple is not added |
1006 |
* updated and marked as changed. The matching tuple is not added (for |
904 |
* (for additions) or marked as deletion instead (for changes). The |
1007 |
* additions) or marked as deletion instead (for changes). The result is |
905 |
* result is that more annotations are changed and fewer get |
1008 |
* that more annotations are changed and fewer get deleted/re-added. |
906 |
* deleted/re-added. |
|
|
907 |
*/ |
1009 |
*/ |
908 |
private void match(List deletions, Map additions, List changes, FoldingStructureComputationContext ctx) { |
1010 |
private void match(List deletions, Map additions, List changes, |
|
|
1011 |
FoldingStructureComputationContext ctx) { |
909 |
if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty())) |
1012 |
if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty())) |
910 |
return; |
1013 |
return; |
911 |
|
1014 |
|
912 |
List newDeletions= new ArrayList(); |
1015 |
List newDeletions = new ArrayList(); |
913 |
List newChanges= new ArrayList(); |
1016 |
List newChanges = new ArrayList(); |
914 |
|
1017 |
|
915 |
Iterator deletionIterator= deletions.iterator(); |
1018 |
Iterator deletionIterator = deletions.iterator(); |
916 |
while (deletionIterator.hasNext()) { |
1019 |
while (deletionIterator.hasNext()) { |
917 |
CProjectionAnnotation deleted= (CProjectionAnnotation) deletionIterator.next(); |
1020 |
CProjectionAnnotation deleted = (CProjectionAnnotation) deletionIterator |
918 |
Position deletedPosition= ctx.getModel().getPosition(deleted); |
1021 |
.next(); |
|
|
1022 |
Position deletedPosition = ctx.getModel().getPosition(deleted); |
919 |
if (deletedPosition == null) |
1023 |
if (deletedPosition == null) |
920 |
continue; |
1024 |
continue; |
921 |
|
|
|
922 |
Tuple deletedTuple= new Tuple(deleted, deletedPosition); |
923 |
|
1025 |
|
924 |
Tuple match= findMatch(deletedTuple, changes, null, ctx); |
1026 |
Tuple deletedTuple = new Tuple(deleted, deletedPosition); |
925 |
boolean addToDeletions= true; |
1027 |
|
|
|
1028 |
Tuple match = findMatch(deletedTuple, changes, null, ctx); |
1029 |
boolean addToDeletions = true; |
926 |
if (match == null) { |
1030 |
if (match == null) { |
927 |
match= findMatch(deletedTuple, additions.keySet(), additions, ctx); |
1031 |
match = findMatch(deletedTuple, additions.keySet(), additions, |
928 |
addToDeletions= false; |
1032 |
ctx); |
|
|
1033 |
addToDeletions = false; |
929 |
} |
1034 |
} |
930 |
|
1035 |
|
931 |
if (match != null) { |
1036 |
if (match != null) { |
932 |
Object element= match.annotation.getElement(); |
1037 |
Object element = match.annotation.getElement(); |
933 |
deleted.setElement(element); |
1038 |
deleted.setElement(element); |
934 |
deletedPosition.setLength(match.position.getLength()); |
1039 |
deletedPosition.setLength(match.position.getLength()); |
935 |
if (deletedPosition instanceof CElementPosition && element instanceof ICElement) { |
1040 |
if (deletedPosition instanceof CElementPosition |
936 |
CElementPosition cep= (CElementPosition) deletedPosition; |
1041 |
&& element instanceof ICElement) { |
|
|
1042 |
CElementPosition cep = (CElementPosition) deletedPosition; |
937 |
cep.setElement((ICElement) element); |
1043 |
cep.setElement((ICElement) element); |
938 |
} |
1044 |
} |
939 |
|
1045 |
|
940 |
deletionIterator.remove(); |
1046 |
deletionIterator.remove(); |
941 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() changed annotation " + deleted); //$NON-NLS-1$ |
1047 |
if (DEBUG) |
|
|
1048 |
System.out |
1049 |
.println("DefaultCFoldingStructureProvider.update() changed annotation " + deleted); //$NON-NLS-1$ |
942 |
newChanges.add(deleted); |
1050 |
newChanges.add(deleted); |
943 |
|
1051 |
|
944 |
if (addToDeletions) { |
1052 |
if (addToDeletions) { |
945 |
if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + match.annotation); //$NON-NLS-1$ |
1053 |
if (DEBUG) |
|
|
1054 |
System.out |
1055 |
.println("DefaultCFoldingStructureProvider.update() deleted annotation " + match.annotation); //$NON-NLS-1$ |
946 |
newDeletions.add(match.annotation); |
1056 |
newDeletions.add(match.annotation); |
947 |
} |
1057 |
} |
948 |
} |
1058 |
} |
Lines 953-986
Link Here
|
953 |
} |
1063 |
} |
954 |
|
1064 |
|
955 |
/** |
1065 |
/** |
956 |
* Finds a match for <code>tuple</code> in a collection of |
1066 |
* Finds a match for <code>tuple</code> in a collection of annotations. |
957 |
* annotations. The positions for the |
1067 |
* The positions for the <code>CProjectionAnnotation</code> instances in |
958 |
* <code>CProjectionAnnotation</code> instances in |
|
|
959 |
* <code>annotations</code> can be found in the passed |
1068 |
* <code>annotations</code> can be found in the passed |
960 |
* <code>positionMap</code> or <code>fCachedModel</code> if |
1069 |
* <code>positionMap</code> or <code>fCachedModel</code> if |
961 |
* <code>positionMap</code> is <code>null</code>. |
1070 |
* <code>positionMap</code> is <code>null</code>. |
962 |
* <p> |
1071 |
* <p> |
963 |
* A tuple is said to match another if their annotations have the |
1072 |
* A tuple is said to match another if their annotations have the same |
964 |
* same comment flag and their position offsets are equal. |
1073 |
* comment flag and their position offsets are equal. |
965 |
* </p> |
1074 |
* </p> |
966 |
* <p> |
1075 |
* <p> |
967 |
* If a match is found, the annotation gets removed from |
1076 |
* If a match is found, the annotation gets removed from |
968 |
* <code>annotations</code>. |
1077 |
* <code>annotations</code>. |
969 |
* </p> |
1078 |
* </p> |
970 |
* |
1079 |
* |
971 |
* @param tuple the tuple for which we want to find a match |
1080 |
* @param tuple |
972 |
* @param annotations collection of |
1081 |
* the tuple for which we want to find a match |
973 |
* <code>CProjectionAnnotation</code> |
1082 |
* @param annotations |
974 |
* @param positionMap a <code>Map<Annotation, Position></code> |
1083 |
* collection of <code>CProjectionAnnotation</code> |
975 |
* or <code>null</code> |
1084 |
* @param positionMap |
|
|
1085 |
* a <code>Map<Annotation, Position></code> or |
1086 |
* <code>null</code> |
976 |
* @return a matching tuple or <code>null</code> for no match |
1087 |
* @return a matching tuple or <code>null</code> for no match |
977 |
*/ |
1088 |
*/ |
978 |
private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap, FoldingStructureComputationContext ctx) { |
1089 |
private Tuple findMatch(Tuple tuple, Collection annotations, |
979 |
Iterator it= annotations.iterator(); |
1090 |
Map positionMap, FoldingStructureComputationContext ctx) { |
|
|
1091 |
Iterator it = annotations.iterator(); |
980 |
while (it.hasNext()) { |
1092 |
while (it.hasNext()) { |
981 |
CProjectionAnnotation annotation= (CProjectionAnnotation) it.next(); |
1093 |
CProjectionAnnotation annotation = (CProjectionAnnotation) it |
|
|
1094 |
.next(); |
982 |
if (tuple.annotation.isComment() == annotation.isComment()) { |
1095 |
if (tuple.annotation.isComment() == annotation.isComment()) { |
983 |
Position position= positionMap == null ? ctx.getModel().getPosition(annotation) : (Position) positionMap.get(annotation); |
1096 |
Position position = positionMap == null ? ctx.getModel() |
|
|
1097 |
.getPosition(annotation) : (Position) positionMap |
1098 |
.get(annotation); |
984 |
if (position == null) |
1099 |
if (position == null) |
985 |
continue; |
1100 |
continue; |
986 |
|
1101 |
|
Lines 990-1060
Link Here
|
990 |
} |
1105 |
} |
991 |
} |
1106 |
} |
992 |
} |
1107 |
} |
993 |
|
1108 |
|
994 |
return null; |
1109 |
return null; |
995 |
} |
1110 |
} |
996 |
|
1111 |
|
997 |
private Map computeCurrentStructure(FoldingStructureComputationContext ctx) { |
1112 |
private Map computeCurrentStructure(FoldingStructureComputationContext ctx) { |
998 |
boolean includeBranches= fPreprocessorBranchFoldingEnabled && ctx.fAST != null; |
1113 |
boolean includeBranches = fPreprocessorBranchFoldingEnabled |
999 |
Map map= new HashMap(); |
1114 |
&& ctx.fAST != null; |
1000 |
ProjectionAnnotationModel model= ctx.getModel(); |
1115 |
Map map = new HashMap(); |
1001 |
Iterator e= model.getAnnotationIterator(); |
1116 |
ProjectionAnnotationModel model = ctx.getModel(); |
|
|
1117 |
Iterator e = model.getAnnotationIterator(); |
1002 |
while (e.hasNext()) { |
1118 |
while (e.hasNext()) { |
1003 |
Object annotation= e.next(); |
1119 |
Object annotation = e.next(); |
1004 |
if (annotation instanceof CProjectionAnnotation) { |
1120 |
if (annotation instanceof CProjectionAnnotation) { |
1005 |
CProjectionAnnotation cAnnotation= (CProjectionAnnotation) annotation; |
1121 |
CProjectionAnnotation cAnnotation = (CProjectionAnnotation) annotation; |
1006 |
if (!includeBranches && cAnnotation.getCategory() == CProjectionAnnotation.BRANCH) { |
1122 |
if (!includeBranches |
|
|
1123 |
&& cAnnotation.getCategory() == CProjectionAnnotation.BRANCH) { |
1007 |
continue; |
1124 |
continue; |
1008 |
} |
1125 |
} |
1009 |
Position position= model.getPosition(cAnnotation); |
1126 |
Position position = model.getPosition(cAnnotation); |
1010 |
Assert.isNotNull(position); |
1127 |
Assert.isNotNull(position); |
1011 |
List list= (List) map.get(cAnnotation.getElement()); |
1128 |
List list = (List) map.get(cAnnotation.getElement()); |
1012 |
if (list == null) { |
1129 |
if (list == null) { |
1013 |
list= new ArrayList(2); |
1130 |
list = new ArrayList(2); |
1014 |
map.put(cAnnotation.getElement(), list); |
1131 |
map.put(cAnnotation.getElement(), list); |
1015 |
} |
1132 |
} |
1016 |
list.add(new Tuple(cAnnotation, position)); |
1133 |
list.add(new Tuple(cAnnotation, position)); |
1017 |
} |
1134 |
} |
1018 |
} |
1135 |
} |
1019 |
|
1136 |
|
1020 |
Comparator comparator= new Comparator() { |
1137 |
Comparator comparator = new Comparator() { |
1021 |
public int compare(Object o1, Object o2) { |
1138 |
public int compare(Object o1, Object o2) { |
1022 |
return ((Tuple) o1).position.getOffset() - ((Tuple) o2).position.getOffset(); |
1139 |
return ((Tuple) o1).position.getOffset() |
|
|
1140 |
- ((Tuple) o2).position.getOffset(); |
1023 |
} |
1141 |
} |
1024 |
}; |
1142 |
}; |
1025 |
for (Iterator it= map.values().iterator(); it.hasNext();) { |
1143 |
for (Iterator it = map.values().iterator(); it.hasNext();) { |
1026 |
List list= (List) it.next(); |
1144 |
List list = (List) it.next(); |
1027 |
Collections.sort(list, comparator); |
1145 |
Collections.sort(list, comparator); |
1028 |
} |
1146 |
} |
1029 |
return map; |
1147 |
return map; |
1030 |
} |
1148 |
} |
1031 |
|
|
|
1032 |
|
1149 |
|
1033 |
private void computeFoldingStructure(final FoldingStructureComputationContext ctx) { |
1150 |
private void computeFoldingStructure( |
|
|
1151 |
final FoldingStructureComputationContext ctx) { |
1034 |
if (fCommentFoldingEnabled) { |
1152 |
if (fCommentFoldingEnabled) { |
1035 |
// compute comment positions from partitioning |
1153 |
// compute comment positions from partitioning |
1036 |
try { |
1154 |
try { |
1037 |
IDocument doc= ctx.getDocument(); |
1155 |
IDocument doc = ctx.getDocument(); |
1038 |
ITypedRegion[] partitions = TextUtilities.computePartitioning(doc, ICPartitions.C_PARTITIONING, 0, doc.getLength(), false); |
1156 |
ITypedRegion[] partitions = TextUtilities.computePartitioning( |
|
|
1157 |
doc, ICPartitions.C_PARTITIONING, 0, doc.getLength(), |
1158 |
false); |
1039 |
computeFoldingStructure(partitions, ctx); |
1159 |
computeFoldingStructure(partitions, ctx); |
1040 |
} catch (BadLocationException e) { |
1160 |
} catch (BadLocationException e) { |
1041 |
// ignore |
1161 |
// ignore |
1042 |
} |
1162 |
} |
1043 |
} |
1163 |
} |
1044 |
if (fPreprocessorBranchFoldingEnabled) { |
1164 |
if (fPreprocessorBranchFoldingEnabled || fStatementsFoldingEnabled) { |
1045 |
IASTTranslationUnit ast= ctx.getAST(); |
1165 |
IASTTranslationUnit ast = ctx.getAST(); |
1046 |
if (ast == null) { |
1166 |
if (ast == null) { |
1047 |
final ASTProvider astProvider= CUIPlugin.getDefault().getASTProvider(); |
1167 |
final ASTProvider astProvider = CUIPlugin.getDefault() |
1048 |
IStatus status= astProvider.runOnAST(getInputElement(), ASTProvider.WAIT_ACTIVE_ONLY, null, new ASTCache.ASTRunnable() { |
1168 |
.getASTProvider(); |
1049 |
public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) { |
1169 |
IStatus status = astProvider.runOnAST(getInputElement(), |
1050 |
if (ast != null) { |
1170 |
ASTProvider.WAIT_ACTIVE_ONLY, null, |
1051 |
ctx.fAST= ast; |
1171 |
new ASTCache.ASTRunnable() { |
1052 |
fInitialReconcilePending= false; |
1172 |
public IStatus runOnAST(ILanguage lang, |
1053 |
computeFoldingStructure(ast, ctx); |
1173 |
IASTTranslationUnit ast) { |
1054 |
} |
1174 |
if (ast != null) { |
1055 |
return Status.OK_STATUS; |
1175 |
ctx.fAST = ast; |
1056 |
} |
1176 |
fInitialReconcilePending = false; |
1057 |
}); |
1177 |
computeFoldingStructure(ast, ctx); |
|
|
1178 |
} |
1179 |
return Status.OK_STATUS; |
1180 |
} |
1181 |
}); |
1058 |
if (status.matches(IStatus.ERROR)) { |
1182 |
if (status.matches(IStatus.ERROR)) { |
1059 |
CUIPlugin.getDefault().log(status); |
1183 |
CUIPlugin.getDefault().log(status); |
1060 |
} |
1184 |
} |
Lines 1063-1093
Link Here
|
1063 |
} |
1187 |
} |
1064 |
} |
1188 |
} |
1065 |
if (!fInitialReconcilePending || isConsistent(fInput)) { |
1189 |
if (!fInitialReconcilePending || isConsistent(fInput)) { |
1066 |
IParent parent= (IParent) fInput; |
1190 |
IParent parent = (IParent) fInput; |
1067 |
try { |
1191 |
try { |
1068 |
computeFoldingStructure(parent.getChildren(), ctx); |
1192 |
computeFoldingStructure(parent.getChildren(), ctx); |
1069 |
} catch (CModelException x) { |
1193 |
} catch (CModelException x) { |
1070 |
} |
1194 |
} |
1071 |
} |
1195 |
} |
1072 |
} |
1196 |
} |
1073 |
|
1197 |
|
1074 |
static boolean isConsistent(ICElement element) { |
1198 |
static boolean isConsistent(ICElement element) { |
1075 |
if (element instanceof ITranslationUnit) { |
1199 |
if (element instanceof ITranslationUnit) { |
1076 |
try { |
1200 |
try { |
1077 |
return ((ITranslationUnit)element).isConsistent(); |
1201 |
return ((ITranslationUnit) element).isConsistent(); |
1078 |
} catch (CModelException exc) { |
1202 |
} catch (CModelException exc) { |
1079 |
} |
1203 |
} |
1080 |
} |
1204 |
} |
1081 |
return false; |
1205 |
return false; |
1082 |
} |
1206 |
} |
1083 |
|
1207 |
|
|
|
1208 |
class ModifiableRegionExtra extends ModifiableRegion { |
1209 |
/* |
1210 |
* A modifiable region with extra information about the region it holds. |
1211 |
* It tells us whether or not to include the last line of the region |
1212 |
*/ |
1213 |
public boolean inclusive; |
1214 |
} |
1215 |
|
1216 |
/** |
1217 |
* Computes folding structure for preprocessor branches for the given AST. |
1218 |
* |
1219 |
* @param ast |
1220 |
* @param ctx |
1221 |
*/ |
1222 |
private void computeStatementFoldingStructure(IASTTranslationUnit ast, FoldingStructureComputationContext ctx) { |
1223 |
final Stack iral = new Stack(); |
1224 |
ast.accept(new ASTVisitor() { |
1225 |
{ |
1226 |
shouldVisitDeclarations = true; |
1227 |
shouldVisitEnumerators = true; |
1228 |
shouldVisitStatements = true; |
1229 |
} |
1230 |
|
1231 |
public int visit(IASTStatement statement) { |
1232 |
// if it's not part of the displayed - file, we don't need it |
1233 |
if (!statement.isPartOfTranslationUnitFile()) |
1234 |
return PROCESS_SKIP;// we neither need its descendants |
1235 |
try { |
1236 |
ModifiableRegionExtra mr; |
1237 |
IASTFileLocation fl; |
1238 |
if (statement instanceof IASTIfStatement) { |
1239 |
IASTIfStatement ifstmt = (IASTIfStatement) statement; |
1240 |
IASTStatement tmp; |
1241 |
mr = new ModifiableRegionExtra(); |
1242 |
tmp = ifstmt.getThenClause(); |
1243 |
if (tmp==null) return PROCESS_CONTINUE; |
1244 |
fl = tmp.getFileLocation(); |
1245 |
mr.setLength(fl.getNodeLength()); |
1246 |
mr.setOffset(fl.getNodeOffset()); |
1247 |
mr.inclusive = false; |
1248 |
tmp = ifstmt.getElseClause(); |
1249 |
if (tmp==null) { |
1250 |
mr.inclusive = true; |
1251 |
iral.push(mr); |
1252 |
return PROCESS_CONTINUE; |
1253 |
} |
1254 |
iral.push(mr); |
1255 |
mr = new ModifiableRegionExtra(); |
1256 |
fl = tmp.getFileLocation(); |
1257 |
mr.setLength(fl.getNodeLength()); |
1258 |
mr.setOffset(fl.getNodeOffset()); |
1259 |
mr.inclusive = true; |
1260 |
iral.push(mr); |
1261 |
} |
1262 |
mr = new ModifiableRegionExtra(); |
1263 |
mr.inclusive = true; |
1264 |
if (statement instanceof IASTDoStatement) |
1265 |
mr.inclusive = false; |
1266 |
if (statement instanceof IASTSwitchStatement) { |
1267 |
IASTStatement switchstmt = ((IASTSwitchStatement)statement).getBody(); |
1268 |
if (switchstmt instanceof IASTCompoundStatement) { |
1269 |
IASTStatement[] stmts = ((IASTCompoundStatement)switchstmt).getStatements(); |
1270 |
boolean pushedMR = false; |
1271 |
for (int i = 0; i < stmts.length; i++) { |
1272 |
IASTStatement tmpstmt = stmts[i]; |
1273 |
ModifiableRegionExtra tmpmr; |
1274 |
if (!(tmpstmt instanceof IASTCaseStatement || tmpstmt instanceof IASTDefaultStatement)) { |
1275 |
if (!pushedMR) return PROCESS_SKIP; |
1276 |
IASTFileLocation tmpfl = tmpstmt.getFileLocation(); |
1277 |
tmpmr = (ModifiableRegionExtra) iral.peek(); |
1278 |
tmpmr.setLength(tmpfl.getNodeLength()+tmpfl.getNodeOffset()-tmpmr.getOffset()); |
1279 |
if (tmpstmt instanceof IASTBreakStatement) pushedMR = false; |
1280 |
continue; |
1281 |
} |
1282 |
IASTFileLocation tmpfl; |
1283 |
tmpmr = new ModifiableRegionExtra(); |
1284 |
tmpmr.inclusive = true; |
1285 |
if (tmpstmt instanceof IASTCaseStatement) { |
1286 |
IASTCaseStatement casestmt = (IASTCaseStatement) tmpstmt; |
1287 |
tmpfl = casestmt.getExpression().getFileLocation(); |
1288 |
tmpmr.setOffset(tmpfl.getNodeOffset()); |
1289 |
tmpmr.setLength(tmpfl.getNodeLength()); |
1290 |
} else if (tmpstmt instanceof IASTDefaultStatement) { |
1291 |
IASTDefaultStatement defstmt = (IASTDefaultStatement) tmpstmt; |
1292 |
tmpfl = defstmt.getFileLocation(); |
1293 |
tmpmr.setOffset(tmpfl.getNodeOffset()+tmpfl.getNodeLength()); |
1294 |
tmpmr.setLength(0); |
1295 |
} |
1296 |
iral.push(tmpmr); |
1297 |
pushedMR = true; |
1298 |
} |
1299 |
} |
1300 |
} |
1301 |
if (statement instanceof IASTForStatement || |
1302 |
statement instanceof IASTWhileStatement || |
1303 |
statement instanceof IASTDoStatement || |
1304 |
statement instanceof IASTSwitchStatement || |
1305 |
statement instanceof IASTInitializerList) { |
1306 |
fl = statement.getFileLocation(); |
1307 |
mr.setLength(fl.getNodeLength()); |
1308 |
mr.setOffset(fl.getNodeOffset()); |
1309 |
iral.push(mr); |
1310 |
} |
1311 |
return PROCESS_CONTINUE; |
1312 |
} catch (Throwable e) { |
1313 |
CCorePlugin.log(e); |
1314 |
return PROCESS_CONTINUE; |
1315 |
} |
1316 |
} |
1317 |
public int visit(IASTDeclaration decl) { |
1318 |
IASTFileLocation fl = decl.getFileLocation(); |
1319 |
ModifiableRegionExtra mr = new ModifiableRegionExtra(); |
1320 |
mr .setLength(fl.getNodeLength()); |
1321 |
mr.inclusive = true; |
1322 |
mr.setOffset(fl.getNodeOffset()); |
1323 |
iral.push(mr); |
1324 |
return PROCESS_CONTINUE; |
1325 |
} |
1326 |
}); |
1327 |
while (!iral.empty()) { |
1328 |
ModifiableRegionExtra mr = (ModifiableRegionExtra) iral.pop(); |
1329 |
IRegion aligned = alignRegion(mr, ctx,mr.inclusive); |
1330 |
if (aligned != null) { |
1331 |
Position alignedPos= new Position(aligned.getOffset(), aligned.getLength()); |
1332 |
ctx.addProjectionRange(new CProjectionAnnotation(false, computeKey(mr, ctx), false), alignedPos); |
1333 |
} |
1334 |
} |
1335 |
} |
1336 |
|
1084 |
/** |
1337 |
/** |
1085 |
* Compute folding structure of the preprocessor branches for the given AST. |
1338 |
* Compute folding structure of things related to the AST tree. Currently it |
|
|
1339 |
* computes the folding structure for: preprocessor branches for the given |
1340 |
* AST. Also, it computes statements folding (if/else do/while for and |
1341 |
* switch) |
1086 |
* |
1342 |
* |
1087 |
* @param ast |
1343 |
* @param ast |
1088 |
* @param ctx |
1344 |
* @param ctx |
1089 |
*/ |
1345 |
*/ |
1090 |
private void computeFoldingStructure(IASTTranslationUnit ast, FoldingStructureComputationContext ctx) { |
1346 |
private void computeFoldingStructure(IASTTranslationUnit ast, |
|
|
1347 |
FoldingStructureComputationContext ctx) { |
1091 |
if (ast == null) { |
1348 |
if (ast == null) { |
1092 |
return; |
1349 |
return; |
1093 |
} |
1350 |
} |
Lines 1095-1104
Link Here
|
1095 |
if (fileName == null) { |
1352 |
if (fileName == null) { |
1096 |
return; |
1353 |
return; |
1097 |
} |
1354 |
} |
1098 |
List branches= new ArrayList(); |
1355 |
|
|
|
1356 |
if (fStatementsFoldingEnabled) |
1357 |
computeStatementFoldingStructure(ast, ctx); |
1358 |
|
1359 |
if (fPreprocessorBranchFoldingEnabled) |
1360 |
computePreprocessorFoldingStructure(ast, ctx, fileName); |
1361 |
} |
1362 |
|
1363 |
/** |
1364 |
* Computes folding structure for preprocessor branches for the given AST. |
1365 |
* |
1366 |
* @param ast |
1367 |
* @param ctx |
1368 |
* @param fileName |
1369 |
*/ |
1370 |
private void computePreprocessorFoldingStructure(IASTTranslationUnit ast, |
1371 |
FoldingStructureComputationContext ctx, String fileName) { |
1372 |
List branches = new ArrayList(); |
1099 |
Stack branchStack = new Stack(); |
1373 |
Stack branchStack = new Stack(); |
1100 |
|
1374 |
|
1101 |
IASTPreprocessorStatement[] preprocStmts = ast.getAllPreprocessorStatements(); |
1375 |
IASTPreprocessorStatement[] preprocStmts = ast |
|
|
1376 |
.getAllPreprocessorStatements(); |
1102 |
|
1377 |
|
1103 |
for (int i = 0; i < preprocStmts.length; i++) { |
1378 |
for (int i = 0; i < preprocStmts.length; i++) { |
1104 |
IASTPreprocessorStatement statement = preprocStmts[i]; |
1379 |
IASTPreprocessorStatement statement = preprocStmts[i]; |
Lines 1110-1133
Link Here
|
1110 |
if (nodeLocations.length != 1) { |
1385 |
if (nodeLocations.length != 1) { |
1111 |
continue; |
1386 |
continue; |
1112 |
} |
1387 |
} |
1113 |
IASTNodeLocation stmtLocation= nodeLocations[0]; |
1388 |
IASTNodeLocation stmtLocation = nodeLocations[0]; |
1114 |
if (statement instanceof IASTPreprocessorIfStatement) { |
1389 |
if (statement instanceof IASTPreprocessorIfStatement) { |
1115 |
IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement; |
1390 |
IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement) statement; |
1116 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifStmt.taken())); |
1391 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), |
|
|
1392 |
ifStmt.taken())); |
1117 |
} else if (statement instanceof IASTPreprocessorIfdefStatement) { |
1393 |
} else if (statement instanceof IASTPreprocessorIfdefStatement) { |
1118 |
IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement; |
1394 |
IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement) statement; |
1119 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifdefStmt.taken())); |
1395 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), |
|
|
1396 |
ifdefStmt.taken())); |
1120 |
} else if (statement instanceof IASTPreprocessorIfndefStatement) { |
1397 |
} else if (statement instanceof IASTPreprocessorIfndefStatement) { |
1121 |
IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement; |
1398 |
IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement) statement; |
1122 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifndefStmt.taken())); |
1399 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), |
|
|
1400 |
ifndefStmt.taken())); |
1123 |
} else if (statement instanceof IASTPreprocessorElseStatement) { |
1401 |
} else if (statement instanceof IASTPreprocessorElseStatement) { |
1124 |
if (branchStack.isEmpty()) { |
1402 |
if (branchStack.isEmpty()) { |
1125 |
// #else without #if |
1403 |
// #else without #if |
1126 |
continue; |
1404 |
continue; |
1127 |
} |
1405 |
} |
1128 |
Branch branch= (Branch)branchStack.pop(); |
1406 |
Branch branch = (Branch) branchStack.pop(); |
1129 |
IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement; |
1407 |
IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement) statement; |
1130 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), elseStmt.taken())); |
1408 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), |
|
|
1409 |
elseStmt.taken())); |
1131 |
branch.setEndOffset(stmtLocation.getNodeOffset()); |
1410 |
branch.setEndOffset(stmtLocation.getNodeOffset()); |
1132 |
branches.add(branch); |
1411 |
branches.add(branch); |
1133 |
} else if (statement instanceof IASTPreprocessorElifStatement) { |
1412 |
} else if (statement instanceof IASTPreprocessorElifStatement) { |
Lines 1135-1143
Link Here
|
1135 |
// #elif without #if |
1414 |
// #elif without #if |
1136 |
continue; |
1415 |
continue; |
1137 |
} |
1416 |
} |
1138 |
Branch branch= (Branch)branchStack.pop(); |
1417 |
Branch branch = (Branch) branchStack.pop(); |
1139 |
IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement) statement; |
1418 |
IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement) statement; |
1140 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), elifStmt.taken())); |
1419 |
branchStack.push(new Branch(stmtLocation.getNodeOffset(), |
|
|
1420 |
elifStmt.taken())); |
1141 |
branch.setEndOffset(stmtLocation.getNodeOffset()); |
1421 |
branch.setEndOffset(stmtLocation.getNodeOffset()); |
1142 |
branches.add(branch); |
1422 |
branches.add(branch); |
1143 |
} else if (statement instanceof IASTPreprocessorEndifStatement) { |
1423 |
} else if (statement instanceof IASTPreprocessorEndifStatement) { |
Lines 1145-1163
Link Here
|
1145 |
// #endif without #if |
1425 |
// #endif without #if |
1146 |
continue; |
1426 |
continue; |
1147 |
} |
1427 |
} |
1148 |
Branch branch= (Branch)branchStack.pop(); |
1428 |
Branch branch = (Branch) branchStack.pop(); |
1149 |
branch.setEndOffset(stmtLocation.getNodeOffset() + stmtLocation.getNodeLength()); |
1429 |
branch.setEndOffset(stmtLocation.getNodeOffset() |
|
|
1430 |
+ stmtLocation.getNodeLength()); |
1150 |
branch.setInclusive(true); |
1431 |
branch.setInclusive(true); |
1151 |
branches.add(branch); |
1432 |
branches.add(branch); |
1152 |
} |
1433 |
} |
1153 |
} |
1434 |
} |
1154 |
for (Iterator iter = branches.iterator(); iter.hasNext(); ) { |
1435 |
for (Iterator iter = branches.iterator(); iter.hasNext();) { |
1155 |
Branch branch= (Branch) iter.next(); |
1436 |
Branch branch = (Branch) iter.next(); |
1156 |
IRegion aligned = alignRegion(branch, ctx, branch.fInclusive); |
1437 |
IRegion aligned = alignRegion(branch, ctx, branch.fInclusive); |
1157 |
if (aligned != null) { |
1438 |
if (aligned != null) { |
1158 |
Position alignedPos= new Position(aligned.getOffset(), aligned.getLength()); |
1439 |
Position alignedPos = new Position(aligned.getOffset(), aligned |
1159 |
final boolean collapse= !branch.taken() && ctx.collapseInactiveCode() && !alignedPos.includes(fCursorPosition); |
1440 |
.getLength()); |
1160 |
ctx.addProjectionRange(new CProjectionAnnotation(collapse, computeKey(branch, ctx), false), alignedPos); |
1441 |
final boolean collapse = !branch.taken() |
|
|
1442 |
&& ctx.collapseInactiveCode() |
1443 |
&& !alignedPos.includes(fCursorPosition); |
1444 |
ctx.addProjectionRange(new CProjectionAnnotation(collapse, |
1445 |
computeKey(branch, ctx), false), alignedPos); |
1161 |
} |
1446 |
} |
1162 |
} |
1447 |
} |
1163 |
} |
1448 |
} |
Lines 1169-1175
Link Here
|
1169 |
* @param ctx |
1454 |
* @param ctx |
1170 |
* @return a key to recognise an annotation position |
1455 |
* @return a key to recognise an annotation position |
1171 |
*/ |
1456 |
*/ |
1172 |
private Object computeKey(Position pos, FoldingStructureComputationContext ctx) { |
1457 |
private Object computeKey(Position pos, |
|
|
1458 |
FoldingStructureComputationContext ctx) { |
1173 |
try { |
1459 |
try { |
1174 |
return ctx.getDocument().get(pos.offset, Math.min(16, pos.length)); |
1460 |
return ctx.getDocument().get(pos.offset, Math.min(16, pos.length)); |
1175 |
} catch (BadLocationException exc) { |
1461 |
} catch (BadLocationException exc) { |
Lines 1180-1215
Link Here
|
1180 |
/** |
1466 |
/** |
1181 |
* Compute folding structure based on partioning information. |
1467 |
* Compute folding structure based on partioning information. |
1182 |
* |
1468 |
* |
1183 |
* @param partitions array of document partitions |
1469 |
* @param partitions |
1184 |
* @param ctx the folding structure context |
1470 |
* array of document partitions |
1185 |
* @throws BadLocationException |
1471 |
* @param ctx |
|
|
1472 |
* the folding structure context |
1473 |
* @throws BadLocationException |
1186 |
*/ |
1474 |
*/ |
1187 |
private void computeFoldingStructure(ITypedRegion[] partitions, FoldingStructureComputationContext ctx) throws BadLocationException { |
1475 |
private void computeFoldingStructure(ITypedRegion[] partitions, |
|
|
1476 |
FoldingStructureComputationContext ctx) throws BadLocationException { |
1188 |
boolean collapse = ctx.collapseComments(); |
1477 |
boolean collapse = ctx.collapseComments(); |
1189 |
IDocument doc= ctx.getDocument(); |
1478 |
IDocument doc = ctx.getDocument(); |
1190 |
int startLine = -1; |
1479 |
int startLine = -1; |
1191 |
int endLine = -1; |
1480 |
int endLine = -1; |
1192 |
List comments= new ArrayList(); |
1481 |
List comments = new ArrayList(); |
1193 |
ModifiableRegion commentRange = new ModifiableRegion(); |
1482 |
ModifiableRegion commentRange = new ModifiableRegion(); |
1194 |
for (int i = 0; i < partitions.length; i++) { |
1483 |
for (int i = 0; i < partitions.length; i++) { |
1195 |
ITypedRegion partition = partitions[i]; |
1484 |
ITypedRegion partition = partitions[i]; |
1196 |
boolean singleLine= false; |
1485 |
boolean singleLine = false; |
1197 |
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())) { |
1486 |
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())) { |
1198 |
Position position= createCommentPosition(alignRegion(partition, ctx, true)); |
1487 |
Position position = createCommentPosition(alignRegion( |
|
|
1488 |
partition, ctx, true)); |
1199 |
if (position != null) { |
1489 |
if (position != null) { |
1200 |
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { |
1490 |
if (startLine >= 0 |
1201 |
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); |
1491 |
&& endLine - startLine >= fMinCommentLines) { |
|
|
1492 |
Position projection = createCommentPosition(alignRegion( |
1493 |
commentRange, ctx, true)); |
1202 |
if (projection != null) { |
1494 |
if (projection != null) { |
1203 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); |
1495 |
comments.add(new Tuple( |
|
|
1496 |
new CProjectionAnnotation(collapse, doc |
1497 |
.get(projection.offset, Math.min( |
1498 |
16, projection.length)), |
1499 |
true), projection)); |
1204 |
} |
1500 |
} |
1205 |
startLine= -1; |
1501 |
startLine = -1; |
1206 |
} |
1502 |
} |
1207 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(position.offset, Math.min(16, position.length)), true), position)); |
1503 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, |
|
|
1504 |
doc.get(position.offset, Math.min(16, |
1505 |
position.length)), true), position)); |
1208 |
} else { |
1506 |
} else { |
1209 |
singleLine= true; |
1507 |
singleLine = true; |
1210 |
} |
1508 |
} |
1211 |
} else { |
1509 |
} else { |
1212 |
singleLine= ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType()); |
1510 |
singleLine = ICPartitions.C_SINGLE_LINE_COMMENT |
|
|
1511 |
.equals(partition.getType()); |
1213 |
} |
1512 |
} |
1214 |
if (singleLine) { |
1513 |
if (singleLine) { |
1215 |
// if comment starts at column 0 and spans only one line |
1514 |
// if comment starts at column 0 and spans only one line |
Lines 1217-1237
Link Here
|
1217 |
// to the commentRange |
1516 |
// to the commentRange |
1218 |
int lineNr = doc.getLineOfOffset(partition.getOffset()); |
1517 |
int lineNr = doc.getLineOfOffset(partition.getOffset()); |
1219 |
IRegion lineRegion = doc.getLineInformation(lineNr); |
1518 |
IRegion lineRegion = doc.getLineInformation(lineNr); |
1220 |
boolean isLineStart = partition.getOffset() == lineRegion.getOffset(); |
1519 |
boolean isLineStart = partition.getOffset() == lineRegion |
|
|
1520 |
.getOffset(); |
1221 |
if (!isLineStart) { |
1521 |
if (!isLineStart) { |
1222 |
continue; |
1522 |
continue; |
1223 |
} |
1523 |
} |
1224 |
if (!singleLine) { |
1524 |
if (!singleLine) { |
1225 |
singleLine = lineRegion.getOffset() + lineRegion.getLength() >= partition.getOffset() + partition.getLength(); |
1525 |
singleLine = lineRegion.getOffset() |
|
|
1526 |
+ lineRegion.getLength() >= partition.getOffset() |
1527 |
+ partition.getLength(); |
1226 |
if (!singleLine) { |
1528 |
if (!singleLine) { |
1227 |
continue; |
1529 |
continue; |
1228 |
} |
1530 |
} |
1229 |
} |
1531 |
} |
1230 |
if (startLine < 0 || lineNr - endLine > 1) { |
1532 |
if (startLine < 0 || lineNr - endLine > 1) { |
1231 |
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { |
1533 |
if (startLine >= 0 |
1232 |
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); |
1534 |
&& endLine - startLine >= fMinCommentLines) { |
|
|
1535 |
Position projection = createCommentPosition(alignRegion( |
1536 |
commentRange, ctx, true)); |
1233 |
if (projection != null) { |
1537 |
if (projection != null) { |
1234 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); |
1538 |
comments.add(new Tuple( |
|
|
1539 |
new CProjectionAnnotation(collapse, doc |
1540 |
.get(projection.offset, Math.min( |
1541 |
16, projection.length)), |
1542 |
true), projection)); |
1235 |
} |
1543 |
} |
1236 |
} |
1544 |
} |
1237 |
startLine = lineNr; |
1545 |
startLine = lineNr; |
Lines 1240-1258
Link Here
|
1240 |
commentRange.length = lineRegion.getLength(); |
1548 |
commentRange.length = lineRegion.getLength(); |
1241 |
} else { |
1549 |
} else { |
1242 |
endLine = lineNr; |
1550 |
endLine = lineNr; |
1243 |
int delta = lineRegion.getOffset() + lineRegion.getLength() - commentRange.offset - commentRange.length; |
1551 |
int delta = lineRegion.getOffset() + lineRegion.getLength() |
|
|
1552 |
- commentRange.offset - commentRange.length; |
1244 |
commentRange.length += delta; |
1553 |
commentRange.length += delta; |
1245 |
} |
1554 |
} |
1246 |
} |
1555 |
} |
1247 |
} |
1556 |
} |
1248 |
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { |
1557 |
if (startLine >= 0 && endLine - startLine >= fMinCommentLines) { |
1249 |
Position projection = createCommentPosition(alignRegion(commentRange, ctx, true)); |
1558 |
Position projection = createCommentPosition(alignRegion( |
|
|
1559 |
commentRange, ctx, true)); |
1250 |
if (projection != null) { |
1560 |
if (projection != null) { |
1251 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection)); |
1561 |
comments.add(new Tuple(new CProjectionAnnotation(collapse, |
|
|
1562 |
doc.get(projection.offset, Math.min(16, |
1563 |
projection.length)), true), projection)); |
1252 |
} |
1564 |
} |
1253 |
} |
1565 |
} |
1254 |
if (!comments.isEmpty()) { |
1566 |
if (!comments.isEmpty()) { |
1255 |
// first comment starting before line 10 is considered the header comment |
1567 |
// first comment starting before line 10 is considered the header |
|
|
1568 |
// comment |
1256 |
Iterator iter = comments.iterator(); |
1569 |
Iterator iter = comments.iterator(); |
1257 |
Tuple tuple = (Tuple) iter.next(); |
1570 |
Tuple tuple = (Tuple) iter.next(); |
1258 |
int lineNr = doc.getLineOfOffset(tuple.position.getOffset()); |
1571 |
int lineNr = doc.getLineOfOffset(tuple.position.getOffset()); |
Lines 1271-1297
Link Here
|
1271 |
} |
1584 |
} |
1272 |
} |
1585 |
} |
1273 |
|
1586 |
|
1274 |
private void computeFoldingStructure(ICElement[] elements, FoldingStructureComputationContext ctx) throws CModelException { |
1587 |
private void computeFoldingStructure(ICElement[] elements, |
1275 |
for (int i= 0; i < elements.length; i++) { |
1588 |
FoldingStructureComputationContext ctx) throws CModelException { |
1276 |
ICElement element= elements[i]; |
1589 |
for (int i = 0; i < elements.length; i++) { |
|
|
1590 |
ICElement element = elements[i]; |
1277 |
|
1591 |
|
1278 |
computeFoldingStructure(element, ctx); |
1592 |
computeFoldingStructure(element, ctx); |
1279 |
|
1593 |
|
1280 |
if (element instanceof IParent) { |
1594 |
if (element instanceof IParent) { |
1281 |
IParent parent= (IParent) element; |
1595 |
IParent parent = (IParent) element; |
1282 |
computeFoldingStructure(parent.getChildren(), ctx); |
1596 |
computeFoldingStructure(parent.getChildren(), ctx); |
1283 |
} |
1597 |
} |
1284 |
} |
1598 |
} |
1285 |
} |
1599 |
} |
1286 |
|
1600 |
|
1287 |
/** |
1601 |
/** |
1288 |
* Computes the folding structure for a given {@link ICElement C element}. Computed |
1602 |
* Computes the folding structure for a given {@link ICElement C element}. |
1289 |
* projection annotations are |
1603 |
* Computed projection annotations are |
1290 |
* {@link DefaultCFoldingStructureProvider.FoldingStructureComputationContext#addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) added} |
1604 |
* {@link DefaultCFoldingStructureProvider.FoldingStructureComputationContext#addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) added} |
1291 |
* to the computation context. |
1605 |
* to the computation context. |
1292 |
* <p> |
1606 |
* <p> |
1293 |
* Subclasses may extend or replace. The default implementation creates projection annotations |
1607 |
* Subclasses may extend or replace. The default implementation creates |
1294 |
* for the following elements: |
1608 |
* projection annotations for the following elements: |
1295 |
* <ul> |
1609 |
* <ul> |
1296 |
* <li>structs, unions, classes</li> |
1610 |
* <li>structs, unions, classes</li> |
1297 |
* <li>functions</li> |
1611 |
* <li>functions</li> |
Lines 1300-1369
Link Here
|
1300 |
* </ul> |
1614 |
* </ul> |
1301 |
* </p> |
1615 |
* </p> |
1302 |
* |
1616 |
* |
1303 |
* @param element the C element to compute the folding structure for |
1617 |
* @param element |
1304 |
* @param ctx the computation context |
1618 |
* the C element to compute the folding structure for |
|
|
1619 |
* @param ctx |
1620 |
* the computation context |
1305 |
*/ |
1621 |
*/ |
1306 |
protected void computeFoldingStructure(ICElement element, FoldingStructureComputationContext ctx) { |
1622 |
protected void computeFoldingStructure(ICElement element, |
|
|
1623 |
FoldingStructureComputationContext ctx) { |
1307 |
|
1624 |
|
1308 |
boolean collapse= false; |
1625 |
boolean collapse = false; |
1309 |
switch (element.getElementType()) { |
1626 |
switch (element.getElementType()) { |
1310 |
|
1627 |
|
1311 |
case ICElement.C_STRUCT: |
1628 |
case ICElement.C_STRUCT: |
1312 |
case ICElement.C_CLASS: |
1629 |
case ICElement.C_CLASS: |
1313 |
case ICElement.C_UNION: |
1630 |
case ICElement.C_UNION: |
|
|
1631 |
case ICElement.C_ENUMERATION: |
1632 |
case ICElement.C_VARIABLE_DECLARATION: |
1314 |
case ICElement.C_TEMPLATE_STRUCT: |
1633 |
case ICElement.C_TEMPLATE_STRUCT: |
1315 |
case ICElement.C_TEMPLATE_CLASS: |
1634 |
case ICElement.C_TEMPLATE_CLASS: |
1316 |
case ICElement.C_TEMPLATE_UNION: |
1635 |
case ICElement.C_TEMPLATE_UNION: |
1317 |
collapse= ctx.collapseStructures(); |
1636 |
collapse = ctx.collapseStructures(); |
1318 |
break; |
1637 |
break; |
1319 |
case ICElement.C_MACRO: |
1638 |
case ICElement.C_MACRO: |
1320 |
collapse= ctx.collapseMacros(); |
1639 |
collapse = ctx.collapseMacros(); |
1321 |
break; |
1640 |
break; |
1322 |
case ICElement.C_FUNCTION: |
1641 |
case ICElement.C_FUNCTION: |
1323 |
case ICElement.C_TEMPLATE_FUNCTION: |
1642 |
case ICElement.C_TEMPLATE_FUNCTION: |
1324 |
collapse= ctx.collapseFunctions(); |
1643 |
collapse = ctx.collapseFunctions(); |
1325 |
break; |
1644 |
break; |
1326 |
case ICElement.C_METHOD: |
1645 |
case ICElement.C_METHOD: |
1327 |
case ICElement.C_TEMPLATE_METHOD: |
1646 |
case ICElement.C_TEMPLATE_METHOD: |
1328 |
collapse= ctx.collapseMethods(); |
1647 |
collapse = ctx.collapseMethods(); |
1329 |
break; |
1648 |
break; |
1330 |
default: |
1649 |
default: |
1331 |
return; |
1650 |
return; |
1332 |
} |
1651 |
} |
1333 |
|
1652 |
|
1334 |
IRegion[] regions= computeProjectionRanges((ISourceReference) element, ctx); |
1653 |
IRegion[] regions = computeProjectionRanges((ISourceReference) element, |
|
|
1654 |
ctx); |
1335 |
if (regions.length > 0) { |
1655 |
if (regions.length > 0) { |
1336 |
IRegion normalized= alignRegion(regions[regions.length - 1], ctx, true); |
1656 |
IRegion normalized = alignRegion(regions[regions.length - 1], ctx, |
|
|
1657 |
true); |
1337 |
if (normalized != null) { |
1658 |
if (normalized != null) { |
1338 |
Position position= createElementPosition(normalized, element); |
1659 |
Position position = createElementPosition(normalized, element); |
1339 |
if (position != null) { |
1660 |
if (position != null) { |
1340 |
collapse= collapse && !position.includes(fCursorPosition); |
1661 |
collapse = collapse && !position.includes(fCursorPosition); |
1341 |
ctx.addProjectionRange(new CProjectionAnnotation(collapse, element, false), position); |
1662 |
ctx.addProjectionRange(new CProjectionAnnotation(collapse, |
|
|
1663 |
element, false), position); |
1342 |
} |
1664 |
} |
1343 |
} |
1665 |
} |
1344 |
} |
1666 |
} |
1345 |
} |
1667 |
} |
1346 |
|
1668 |
|
1347 |
/** |
1669 |
/** |
1348 |
* Computes the projection ranges for a given <code>ISourceReference</code>. More than one |
1670 |
* Computes the projection ranges for a given <code>ISourceReference</code>. |
1349 |
* range or none at all may be returned. If there are no foldable regions, an empty array is |
1671 |
* More than one range or none at all may be returned. If there are no |
1350 |
* returned. |
1672 |
* foldable regions, an empty array is returned. |
1351 |
* <p> |
1673 |
* <p> |
1352 |
* The last region in the returned array (if not empty) describes the region for the C |
1674 |
* The last region in the returned array (if not empty) describes the region |
1353 |
* element that implements the source reference. Any preceding regions describe comments |
1675 |
* for the C element that implements the source reference. Any preceding |
1354 |
* of that element. |
1676 |
* regions describe comments of that element. |
1355 |
* </p> |
1677 |
* </p> |
1356 |
* |
1678 |
* |
1357 |
* @param reference a C element that is a source reference |
1679 |
* @param reference |
1358 |
* @param ctx the folding context |
1680 |
* a C element that is a source reference |
|
|
1681 |
* @param ctx |
1682 |
* the folding context |
1359 |
* @return the regions to be folded |
1683 |
* @return the regions to be folded |
1360 |
*/ |
1684 |
*/ |
1361 |
protected final IRegion[] computeProjectionRanges(ISourceReference reference, FoldingStructureComputationContext ctx) { |
1685 |
protected final IRegion[] computeProjectionRanges( |
|
|
1686 |
ISourceReference reference, FoldingStructureComputationContext ctx) { |
1362 |
try { |
1687 |
try { |
1363 |
ISourceRange range= reference.getSourceRange(); |
1688 |
ISourceRange range = reference.getSourceRange(); |
1364 |
return new IRegion[] { |
1689 |
return new IRegion[] { new Region(range.getStartPos(), range |
1365 |
new Region(range.getStartPos(), range.getLength()) |
1690 |
.getLength()) }; |
1366 |
}; |
|
|
1367 |
} catch (CModelException e) { |
1691 |
} catch (CModelException e) { |
1368 |
} |
1692 |
} |
1369 |
|
1693 |
|
Lines 1375-1381
Link Here
|
1375 |
* {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned} |
1699 |
* {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned} |
1376 |
* region. |
1700 |
* region. |
1377 |
* |
1701 |
* |
1378 |
* @param aligned an aligned region |
1702 |
* @param aligned |
|
|
1703 |
* an aligned region |
1379 |
* @return a folding position corresponding to <code>aligned</code> |
1704 |
* @return a folding position corresponding to <code>aligned</code> |
1380 |
*/ |
1705 |
*/ |
1381 |
protected final Position createCommentPosition(IRegion aligned) { |
1706 |
protected final Position createCommentPosition(IRegion aligned) { |
Lines 1390-1471
Link Here
|
1390 |
* {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned} |
1715 |
* {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext, boolean) aligned} |
1391 |
* region. |
1716 |
* region. |
1392 |
* |
1717 |
* |
1393 |
* @param aligned an aligned region |
1718 |
* @param aligned |
1394 |
* @param element the element to remember |
1719 |
* an aligned region |
|
|
1720 |
* @param element |
1721 |
* the element to remember |
1395 |
* @return a folding position corresponding to <code>aligned</code> |
1722 |
* @return a folding position corresponding to <code>aligned</code> |
1396 |
*/ |
1723 |
*/ |
1397 |
protected final Position createElementPosition(IRegion aligned, ICElement element) { |
1724 |
protected final Position createElementPosition(IRegion aligned, |
1398 |
return new CElementPosition(aligned.getOffset(), aligned.getLength(), element); |
1725 |
ICElement element) { |
|
|
1726 |
return new CElementPosition(aligned.getOffset(), aligned.getLength(), |
1727 |
element); |
1399 |
} |
1728 |
} |
1400 |
|
1729 |
|
1401 |
/** |
1730 |
/** |
1402 |
* Aligns <code>region</code> to start and end at a line offset. The region's start is |
1731 |
* Aligns <code>region</code> to start and end at a line offset. The |
1403 |
* decreased to the next line offset, and the end offset increased to the next line start or the |
1732 |
* region's start is decreased to the next line offset, and the end offset |
1404 |
* end of the document. <code>null</code> is returned if <code>region</code> is |
1733 |
* increased to the next line start or the end of the document. |
1405 |
* <code>null</code> itself or does not comprise at least one line delimiter, as a single line |
1734 |
* <code>null</code> is returned if <code>region</code> is |
1406 |
* cannot be folded. |
1735 |
* <code>null</code> itself or does not comprise at least one line |
|
|
1736 |
* delimiter, as a single line cannot be folded. |
1407 |
* |
1737 |
* |
1408 |
* @param region the region to align, may be <code>null</code> |
1738 |
* @param region |
1409 |
* @param ctx the folding context |
1739 |
* the region to align, may be <code>null</code> |
1410 |
* @return a region equal or greater than <code>region</code> that is aligned with line |
1740 |
* @param ctx |
1411 |
* offsets, <code>null</code> if the region is too small to be foldable (e.g. covers |
1741 |
* the folding context |
1412 |
* only one line) |
1742 |
* @return a region equal or greater than <code>region</code> that is |
|
|
1743 |
* aligned with line offsets, <code>null</code> if the region is |
1744 |
* too small to be foldable (e.g. covers only one line) |
1413 |
*/ |
1745 |
*/ |
1414 |
protected final IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx) { |
1746 |
protected final IRegion alignRegion(IRegion region, |
|
|
1747 |
FoldingStructureComputationContext ctx) { |
1415 |
return alignRegion(region, ctx, true); |
1748 |
return alignRegion(region, ctx, true); |
1416 |
} |
1749 |
} |
1417 |
|
1750 |
|
1418 |
/** |
1751 |
/** |
1419 |
* Aligns <code>region</code> to start and end at a line offset. The region's start is |
1752 |
* Aligns <code>region</code> to start and end at a line offset. The |
1420 |
* decreased to the next line offset, and the end offset increased to the next line start or the |
1753 |
* region's start is decreased to the next line offset, and the end offset |
1421 |
* end of the document. <code>null</code> is returned if <code>region</code> is |
1754 |
* increased to the next line start or the end of the document. |
1422 |
* <code>null</code> itself or does not comprise at least one line delimiter, as a single line |
1755 |
* <code>null</code> is returned if <code>region</code> is |
1423 |
* cannot be folded. |
1756 |
* <code>null</code> itself or does not comprise at least one line |
|
|
1757 |
* delimiter, as a single line cannot be folded. |
1424 |
* |
1758 |
* |
1425 |
* @param region the region to align, may be <code>null</code> |
1759 |
* @param region |
1426 |
* @param ctx the folding context |
1760 |
* the region to align, may be <code>null</code> |
1427 |
* @param inclusive include line of end offset |
1761 |
* @param ctx |
1428 |
* @return a region equal or greater than <code>region</code> that is aligned with line |
1762 |
* the folding context |
1429 |
* offsets, <code>null</code> if the region is too small to be foldable (e.g. covers |
1763 |
* @param inclusive |
1430 |
* only one line) |
1764 |
* include line of end offset |
|
|
1765 |
* @return a region equal or greater than <code>region</code> that is |
1766 |
* aligned with line offsets, <code>null</code> if the region is |
1767 |
* too small to be foldable (e.g. covers only one line) |
1431 |
*/ |
1768 |
*/ |
1432 |
protected final IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx, boolean inclusive) { |
1769 |
protected final IRegion alignRegion(IRegion region, |
|
|
1770 |
FoldingStructureComputationContext ctx, boolean inclusive) { |
1433 |
if (region == null) |
1771 |
if (region == null) |
1434 |
return null; |
1772 |
return null; |
1435 |
|
1773 |
|
1436 |
IDocument document= ctx.getDocument(); |
1774 |
IDocument document = ctx.getDocument(); |
1437 |
|
1775 |
|
1438 |
try { |
1776 |
try { |
1439 |
|
1777 |
|
1440 |
int start= document.getLineOfOffset(region.getOffset()); |
1778 |
int start = document.getLineOfOffset(region.getOffset()); |
1441 |
int end= document.getLineOfOffset(region.getOffset() + region.getLength()); |
1779 |
int end = document.getLineOfOffset(region.getOffset() |
|
|
1780 |
+ region.getLength()); |
1442 |
if (start >= end) |
1781 |
if (start >= end) |
1443 |
return null; |
1782 |
return null; |
1444 |
|
1783 |
|
1445 |
int offset= document.getLineOffset(start); |
1784 |
int offset = document.getLineOffset(start); |
1446 |
int endOffset; |
1785 |
int endOffset; |
1447 |
if (inclusive) { |
1786 |
if (inclusive) { |
1448 |
if (document.getNumberOfLines() > end + 1) |
1787 |
if (document.getNumberOfLines() > end + 1) |
1449 |
endOffset= document.getLineOffset(end + 1); |
1788 |
endOffset = document.getLineOffset(end + 1); |
1450 |
else |
1789 |
else |
1451 |
endOffset= document.getLineOffset(end) + document.getLineLength(end); |
1790 |
endOffset = document.getLineOffset(end) |
|
|
1791 |
+ document.getLineLength(end); |
1452 |
} else { |
1792 |
} else { |
1453 |
endOffset= document.getLineOffset(end); |
1793 |
endOffset = document.getLineOffset(end); |
1454 |
} |
1794 |
} |
1455 |
return new Region(offset, endOffset - offset); |
1795 |
return new Region(offset, endOffset - offset); |
1456 |
|
1796 |
|
1457 |
} catch (BadLocationException x) { |
1797 |
} catch (BadLocationException x) { |
1458 |
// concurrent modification |
1798 |
// concurrent modification |
1459 |
return null; |
1799 |
return null; |
1460 |
} |
1800 |
} |
1461 |
} |
1801 |
} |
1462 |
|
1802 |
|
1463 |
private ProjectionAnnotationModel getModel() { |
1803 |
private ProjectionAnnotationModel getModel() { |
1464 |
return (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class); |
1804 |
return (ProjectionAnnotationModel) fEditor |
|
|
1805 |
.getAdapter(ProjectionAnnotationModel.class); |
1465 |
} |
1806 |
} |
1466 |
|
1807 |
|
1467 |
private IDocument getDocument() { |
1808 |
private IDocument getDocument() { |
1468 |
IDocumentProvider provider= fEditor.getDocumentProvider(); |
1809 |
IDocumentProvider provider = fEditor.getDocumentProvider(); |
1469 |
return provider.getDocument(fEditor.getEditorInput()); |
1810 |
return provider.getDocument(fEditor.getEditorInput()); |
1470 |
} |
1811 |
} |
1471 |
|
1812 |
|