diff --git a/core/org.eclipse.cdt.ui/.options b/core/org.eclipse.cdt.ui/.options
index 4917fd522fb..ed41271de7b 100644
--- a/core/org.eclipse.cdt.ui/.options
+++ b/core/org.eclipse.cdt.ui/.options
@@ -8,3 +8,6 @@ org.eclipse.cdt.ui/debug/ASTProvider=false
# Enables all semantic highlighting types
org.eclipse.cdt.ui/debug/SemanticHighlighting=false
+
+# Enables debug information related to folding
+org.eclipse.cdt.ui/debug/folding=false
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java
index de841841a41..5094f08c59e 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ASTProvider.java
@@ -28,6 +28,7 @@ import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.cdt.core.IPositionConverter;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.model.ICElement;
@@ -93,12 +94,10 @@ public final class ASTProvider {
*/
public static final WAIT_FLAG WAIT_NO= new WAIT_FLAG("don't wait"); //$NON-NLS-1$
- public static int PARSE_MODE_FULL= ILanguage.AST_SKIP_IF_NO_BUILD_INFO;
- public static int PARSE_MODE_FAST= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS;
- public static int PARSE_MODE_FAST_INDEX= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS | ILanguage.AST_USE_INDEX;
- public static int PARSE_MODE_INDEX= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_USE_INDEX;
-
- public static int PARSE_MODE= PARSE_MODE_FULL;
+ /** Full parse mode (no PDOM) */
+ public static int PARSE_MODE_FULL= 0;
+ /** Fast parse mode (use PDOM) */
+ public static int PARSE_MODE_FAST= ILanguage.AST_SKIP_INDEXED_HEADERS | ILanguage.AST_USE_INDEX;
/**
* Tells whether this class is in debug mode.
@@ -232,6 +231,7 @@ public final class ASTProvider {
private ICElement fReconcilingCElement;
private ICElement fActiveCElement;
+ private IPositionConverter fActivePositionConverter;
private IASTTranslationUnit fAST;
private ActivationListener fActivationListener;
private Object fReconcileLock= new Object();
@@ -239,7 +239,8 @@ public final class ASTProvider {
private boolean fIsReconciling;
private IWorkbenchPart fActiveEditor;
-
+ protected int fParseMode= PARSE_MODE_FAST;
+
/**
* Returns the C plug-in's AST provider.
*
@@ -280,7 +281,7 @@ public final class ASTProvider {
synchronized (this) {
fActiveEditor= editor;
fActiveCElement= cElement;
- cache(null, cElement);
+ cache(null, null, cElement);
}
if (DEBUG)
@@ -337,7 +338,7 @@ public final class ASTProvider {
fIsReconciling= true;
fReconcilingCElement= cElement;
}
- cache(null, cElement);
+ cache(null, null, cElement);
}
/**
@@ -353,7 +354,7 @@ public final class ASTProvider {
fAST= null;
- cache(null, null);
+ cache(null, null, null);
}
/**
@@ -393,7 +394,7 @@ public final class ASTProvider {
* @param ast
* @param cElement
*/
- private synchronized void cache(IASTTranslationUnit ast, ICElement cElement) {
+ private synchronized void cache(IASTTranslationUnit ast, IPositionConverter converter, ICElement cElement) {
if (fActiveCElement != null && !fActiveCElement.equals(cElement)) {
if (DEBUG && cElement != null) // don't report call from disposeAST()
@@ -408,6 +409,7 @@ public final class ASTProvider {
disposeAST();
fAST= ast;
+ fActivePositionConverter= converter;
// Signal AST change
synchronized (fWaitLock) {
@@ -502,9 +504,9 @@ public final class ASTProvider {
if (fAST != null) {
if (DEBUG)
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "Ignore created AST for " + cElement.getElementName() + "- AST from reconciler is newer"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- reconciled(fAST, cElement, null);
+ reconciled(fAST, fActivePositionConverter, cElement, null);
} else
- reconciled(ast, cElement, null);
+ reconciled(ast, null, cElement, null);
}
}
@@ -550,7 +552,7 @@ public final class ASTProvider {
if (progressMonitor != null && progressMonitor.isCanceled()) {
root[0]= null;
} else {
- root[0]= tu.getLanguage().getASTTranslationUnit(tu, PARSE_MODE);
+ root[0]= tu.getLanguage().getASTTranslationUnit(tu, fParseMode);
}
} catch (OperationCanceledException ex) {
root[0]= null;
@@ -601,9 +603,9 @@ public final class ASTProvider {
}
/*
- * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(org.eclipse.cdt.core.dom.IASTTranslationUnit)
+ * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled()
*/
- void reconciled(IASTTranslationUnit ast, ICElement cElement, IProgressMonitor progressMonitor) {
+ void reconciled(IASTTranslationUnit ast, IPositionConverter converter, ICElement cElement, IProgressMonitor progressMonitor) {
if (DEBUG)
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "reconciled: " + toString(cElement) + ", AST: " + toString(ast)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -624,7 +626,7 @@ public final class ASTProvider {
return;
}
- cache(ast, cElement);
+ cache(ast, converter, cElement);
}
}
@@ -635,6 +637,17 @@ public final class ASTProvider {
else
return Thread.currentThread().toString();
}
+
+ /**
+ * @param element
+ * @return the position converter for the AST of the active element or null
+ */
+ public IPositionConverter getActivePositionConverter(ICElement element) {
+ if (fActiveCElement == element) {
+ return fActivePositionConverter;
+ }
+ return null;
+ }
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
index 16ddfde2a8b..7e025fee866 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java
@@ -2183,7 +2183,7 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
return;
// Always notify AST provider
- cuiPlugin.getASTProvider().reconciled(ast, getInputCElement(), progressMonitor);
+ cuiPlugin.getASTProvider().reconciled(ast, positionTracker, getInputCElement(), progressMonitor);
// Notify listeners
Object[] listeners = fReconcilingListeners.getListeners();
@@ -2200,10 +2200,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
* @param listener The reconcile listener to be added
* @since 4.0
*/
- final void addReconcileListener(ICReconcilingListener listener) {
- synchronized (fReconcilingListeners) {
- fReconcilingListeners.add(listener);
- }
+ final public void addReconcileListener(ICReconcilingListener listener) {
+ fReconcilingListeners.add(listener);
}
/**
@@ -2213,10 +2211,8 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
* @param listener the reconcile listener to be removed
* @since 4.0
*/
- final void removeReconcileListener(ICReconcilingListener listener) {
- synchronized (fReconcilingListeners) {
- fReconcilingListeners.remove(listener);
- }
+ final public void removeReconcileListener(ICReconcilingListener listener) {
+ fReconcilingListeners.remove(listener);
}
/**
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/WorkInProgressPreferencePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/WorkInProgressPreferencePage.java
index f931265a16c..43617cf9564 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/WorkInProgressPreferencePage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/WorkInProgressPreferencePage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -84,7 +84,10 @@ public class WorkInProgressPreferencePage extends PreferencePage implements IWor
result.setLayout(layout);
// Add your controls here
- addCheckBox(result, "Semantic Highlighting", PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED); //$NON-NLS-1$
+ addCheckBox(result, "Enable semantic highlighting", PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED); //$NON-NLS-1$
+ addCheckBox(result, "Enable folding of preprocessor branches (#if/#endif)", PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); //$NON-NLS-1$
+ addCheckBox(result, "Enable comment folding", PreferenceConstants.EDITOR_FOLDING_COMMENTS_ENABLED); //$NON-NLS-1$
+
applyDialogFont(result);
return result;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java
index a3831f3f2cf..bcc4c0c4580 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingPreferenceBlock.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.folding;
@@ -64,6 +65,9 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_FUNCTIONS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_METHODS));
overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_STRUCTURES));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_COMMENTS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_HEADERS));
+ overlayKeys.add(new OverlayPreferenceStore.OverlayKey(OverlayPreferenceStore.BOOLEAN, PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE));
return (OverlayKey[]) overlayKeys.toArray(new OverlayKey[overlayKeys.size()]);
}
@@ -88,6 +92,9 @@ public class DefaultCFoldingPreferenceBlock implements ICFoldingPreferenceBlock
addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.functions"), PreferenceConstants.EDITOR_FOLDING_FUNCTIONS, 0); //$NON-NLS-1$
addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.methods"), PreferenceConstants.EDITOR_FOLDING_METHODS, 0); //$NON-NLS-1$
addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.structures"), PreferenceConstants.EDITOR_FOLDING_STRUCTURES, 0); //$NON-NLS-1$
+ addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.comments"), PreferenceConstants.EDITOR_FOLDING_COMMENTS, 0); //$NON-NLS-1$
+ addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.headers"), PreferenceConstants.EDITOR_FOLDING_HEADERS, 0); //$NON-NLS-1$
+ addCheckBox(inner, FoldingMessages.getString("DefaultCFoldingPreferenceBlock.inactive_code"), PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, 0); //$NON-NLS-1$
return inner;
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java
index 9c732199450..7d93f398e07 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/DefaultCFoldingStructureProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2005 QNX Software Systems and others.
+ * Copyright (c) 2000, 2006 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,85 +7,344 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.text.folding;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Stack;
-import org.eclipse.cdt.core.model.CModelException;
-import org.eclipse.cdt.core.model.CoreModel;
-import org.eclipse.cdt.core.model.ElementChangedEvent;
-import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.model.ICElementDelta;
-import org.eclipse.cdt.core.model.IElementChangedListener;
-import org.eclipse.cdt.core.model.IParent;
-import org.eclipse.cdt.core.model.ISourceRange;
-import org.eclipse.cdt.core.model.ISourceReference;
-import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.internal.ui.editor.CEditor;
-import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.ui.IWorkingCopyManager;
-import org.eclipse.cdt.ui.PreferenceConstants;
-import org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.source.Annotation;
-import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.projection.IProjectionListener;
+import org.eclipse.jface.text.source.projection.IProjectionPosition;
import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.cdt.core.IPositionConverter;
+import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ElementChangedEvent;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICElementDelta;
+import org.eclipse.cdt.core.model.IElementChangedListener;
+import org.eclipse.cdt.core.model.IMember;
+import org.eclipse.cdt.core.model.IParent;
+import org.eclipse.cdt.core.model.ISourceRange;
+import org.eclipse.cdt.core.model.ISourceReference;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.PreferenceConstants;
+import org.eclipse.cdt.ui.text.ICPartitions;
+import org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider;
+
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+import org.eclipse.cdt.internal.ui.editor.CEditor;
+import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator;
+import org.eclipse.cdt.internal.ui.text.ICReconcilingListener;
+
/**
+ * Default implementation of a {@link ICFoldingStructureProvider}.
+ *
+ * Derived from JDT counterpart. + *
*/ -public class DefaultCFoldingStructureProvider implements IProjectionListener, ICFoldingStructureProvider { +public class DefaultCFoldingStructureProvider implements ICFoldingStructureProvider { + + /** + * Reconcile annotation positions from preprocessor branches. + */ + private class PreprocessorBranchesReconciler implements ICReconcilingListener { + + /* + * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled() + */ + public void aboutToBeReconciled() { + + } + + /* + * @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit, org.eclipse.cdt.core.IPositionConverter, org.eclipse.core.runtime.IProgressMonitor) + */ + public void reconciled(IASTTranslationUnit ast, IPositionConverter positionTracker, IProgressMonitor progressMonitor) { + FoldingStructureComputationContext ctx= createContext(fInitialASTReconcile); + fInitialASTReconcile= false; + if (fPreprocessorBranchFoldingEnabled) { + ctx.fAST= ast; + ctx.fASTPositionConverter= positionTracker; + } + update(ctx); + } + + } + + + /** + * A context that contains the information needed to compute the folding structure of an + * {@link ITranslationUnit}. Computed folding regions are collected via + * {@linkplain #addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) addProjectionRange}. + */ + protected final class FoldingStructureComputationContext { + private final ProjectionAnnotationModel fModel; + private final IDocument fDocument; + private final boolean fAllowCollapsing; + + private ISourceReference fFirstType; + private boolean fHasHeaderComment; + private LinkedHashMap fMap= new LinkedHashMap(); + private IASTTranslationUnit fAST; + private IPositionConverter fASTPositionConverter; + + FoldingStructureComputationContext(IDocument document, ProjectionAnnotationModel model, boolean allowCollapsing) { + Assert.isNotNull(document); + Assert.isNotNull(model); + fDocument= document; + fModel= model; + fAllowCollapsing= allowCollapsing; + } + + void setFirstType(ISourceReference reference) { + if (hasFirstType()) + throw new IllegalStateException(); + fFirstType= reference; + } + + boolean hasFirstType() { + return fFirstType != null; + } + + ISourceReference getFirstType() { + return fFirstType; + } + + boolean hasHeaderComment() { + return fHasHeaderComment; + } + + void setHasHeaderComment() { + fHasHeaderComment= true; + } + + /** + * Returnstrue
if newly created folding regions may be collapsed,
+ * false
if not. This is usually false
when updating the
+ * folding structure while typing; it may be true
when computing or restoring
+ * the initial folding structure.
+ *
+ * @return true
if newly created folding regions may be collapsed,
+ * false
if not
+ */
+ public boolean allowCollapsing() {
+ return fAllowCollapsing;
+ }
+
+ /**
+ * Returns the document which contains the code being folded.
+ *
+ * @return the document which contains the code being folded
+ */
+ IDocument getDocument() {
+ return fDocument;
+ }
+
+ ProjectionAnnotationModel getModel() {
+ return fModel;
+ }
+
+ /**
+ * Adds a projection (folding) region to this context. The created annotation / position
+ * pair will be added to the {@link ProjectionAnnotationModel} of the
+ * {@link ProjectionViewer} of the editor.
+ *
+ * @param annotation the annotation to add
+ * @param position the corresponding position
+ */
+ public void addProjectionRange(CProjectionAnnotation annotation, Position position) {
+ fMap.put(annotation, position);
+ }
+
+ /**
+ * Returns true
if header comments should be collapsed.
+ *
+ * @return true
if header comments should be collapsed
+ */
+ public boolean collapseHeaderComments() {
+ return fAllowCollapsing && fCollapseHeaderComments;
+ }
+
+ /**
+ * Returns true
if comments should be collapsed.
+ *
+ * @return true
if comments should be collapsed
+ */
+ public boolean collapseComments() {
+ return fAllowCollapsing && fCollapseComments;
+ }
+
+ /**
+ * Returns true
if functions should be collapsed.
+ *
+ * @return true
if functions should be collapsed
+ */
+ public boolean collapseFunctions() {
+ return fAllowCollapsing && fCollapseFunctions;
+ }
+
+ /**
+ * Returns true
if macros should be collapsed.
+ *
+ * @return true
if macros should be collapsed
+ */
+ public boolean collapseMacros() {
+ return fAllowCollapsing && fCollapseMacros;
+ }
+
+ /**
+ * Returns true
if methods should be collapsed.
+ *
+ * @return true
if methods should be collapsed
+ */
+ public boolean collapseMethods() {
+ return fAllowCollapsing && fCollapseMethods;
+ }
+
+ /**
+ * Returns true
if structures should be collapsed.
+ *
+ * @return true
if structures should be collapsed
+ */
+ public boolean collapseStructures() {
+ return fAllowCollapsing && fCollapseStructures;
+ }
+
+ /**
+ * Returns true
if inactive code should be collapsed.
+ *
+ * @return true
if inactive code should be collapsed
+ */
+ public boolean collapseInactiveCode() {
+ return fAllowCollapsing && fCollapseInactiveCode;
+ }
+
+ /**
+ * @return the converter for the current AST or null
+ */
+ public IPositionConverter getASTPositionConverter() {
+ return fASTPositionConverter;
+ }
+
+ /**
+ * @return the current AST or null
+ */
+ public IASTTranslationUnit getAST() {
+ return fAST;
+ }
+ }
+
private static class CProjectionAnnotation extends ProjectionAnnotation {
+
+ public final static int COMMENT= 1;
+ public final static int BRANCH= 2;
- private ICElement fCElement;
- private boolean fIsComment;
+ private Object fKey;
+ private int fCategory;
- public CProjectionAnnotation(ICElement element, boolean isCollapsed, boolean isComment) {
+ public CProjectionAnnotation(boolean isCollapsed, Object key, boolean isComment) {
+ this(isCollapsed, key, isComment ? COMMENT : 0);
+ }
+
+ public CProjectionAnnotation(boolean isCollapsed, Object key, int category) {
super(isCollapsed);
- fCElement= element;
- fIsComment= isComment;
+ fKey= key;
+ fCategory= category;
}
- public ICElement getElement() {
- return fCElement;
+ public Object getElement() {
+ return fKey;
}
- public void setElement(ICElement element) {
- fCElement= element;
+ public void setElement(Object element) {
+ fKey= element;
}
+ public int getCategory() {
+ return fCategory;
+ }
+
+ public void setCategory(int category) {
+ fCategory = category;
+ }
+
public boolean isComment() {
- return fIsComment;
+ return fCategory == COMMENT;
}
public void setIsComment(boolean isComment) {
- fIsComment= isComment;
+ fCategory= isComment ? COMMENT : 0;
+ }
+ /*
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return "CProjectionAnnotation:\n" + //$NON-NLS-1$
+ "\tkey: \t"+ fKey + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ "\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
+ "\tcomment: \t" + isComment() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
+
+ private static final class Tuple {
+ CProjectionAnnotation annotation;
+ Position position;
+ Tuple(CProjectionAnnotation annotation, Position position) {
+ this.annotation= annotation;
+ this.position= position;
+ }
+ }
+
+
private class ElementChangedListener implements IElementChangedListener {
/*
- * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
+ * @see org.eclipse.cdt.core.IElementChangedListener#elementChanged(org.eclipse.cdt.core.ElementChangedEvent)
*/
public void elementChanged(ElementChangedEvent e) {
ICElementDelta delta= findElement(fInput, e.getDelta());
if (delta != null)
- processDelta(delta);
+ update(createContext(false));
}
private ICElementDelta findElement(ICElement target, ICElementDelta delta) {
@@ -115,371 +374,1067 @@ public class DefaultCFoldingStructureProvider implements IProjectionListener, IC
}
}
+ /**
+ * Projection position that will return two foldable regions: one folding away
+ * the region from after the '/*' to the beginning of the content, the other
+ * from after the first content line until after the comment.
+ */
+ private static final class CommentPosition extends Position implements IProjectionPosition {
+ CommentPosition(int offset, int length) {
+ super(offset, length);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
+ */
+ public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
+ DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length);
+ int prefixEnd= 0;
+ int contentStart= findFirstContent(sequence, prefixEnd);
+
+ int firstLine= document.getLineOfOffset(offset + prefixEnd);
+ int captionLine= document.getLineOfOffset(offset + contentStart);
+ int lastLine= document.getLineOfOffset(offset + length);
+
+ Assert.isTrue(firstLine <= captionLine, "first folded line is greater than the caption line"); //$NON-NLS-1$
+ Assert.isTrue(captionLine <= lastLine, "caption line is greater than the last folded line"); //$NON-NLS-1$
+
+ IRegion preRegion;
+ if (firstLine < captionLine) {
+// preRegion= new Region(offset + prefixEnd, contentStart - prefixEnd);
+ int preOffset= document.getLineOffset(firstLine);
+ IRegion preEndLineInfo= document.getLineInformation(captionLine);
+ int preEnd= preEndLineInfo.getOffset();
+ preRegion= new Region(preOffset, preEnd - preOffset);
+ } else {
+ preRegion= null;
+ }
+
+ if (captionLine < lastLine) {
+ int postOffset= document.getLineOffset(captionLine + 1);
+ IRegion postRegion= new Region(postOffset, offset + length - postOffset);
+
+ if (preRegion == null)
+ return new IRegion[] { postRegion };
+
+ return new IRegion[] { preRegion, postRegion };
+ }
+
+ if (preRegion != null)
+ return new IRegion[] { preRegion };
+
+ return null;
+ }
+
+ /**
+ * Finds the offset of the first identifier part within content
.
+ * Returns 0 if none is found.
+ *
+ * @param content the content to search
+ * @return the first index of a unicode identifier part, or zero if none can
+ * be found
+ */
+ private int findFirstContent(final CharSequence content, int prefixEnd) {
+ int lenght= content.length();
+ for (int i= prefixEnd; i < lenght; i++) {
+ if (Character.isUnicodeIdentifierPart(content.charAt(i)))
+ return i;
+ }
+ return 0;
+ }
+
+// /**
+// * Finds the offset of the first identifier part within content
.
+// * Returns 0 if none is found.
+// *
+// * @param content the content to search
+// * @return the first index of a unicode identifier part, or zero if none can
+// * be found
+// */
+// private int findPrefixEnd(final CharSequence content) {
+// // return the index after the leading '/*' or '/**'
+// int len= content.length();
+// int i= 0;
+// while (i < len && isWhiteSpace(content.charAt(i)))
+// i++;
+// if (len >= i + 2 && content.charAt(i) == '/' && content.charAt(i + 1) == '*')
+// if (len >= i + 3 && content.charAt(i + 2) == '*')
+// return i + 3;
+// else
+// return i + 2;
+// else
+// return i;
+// }
+//
+// private boolean isWhiteSpace(char c) {
+// return c == ' ' || c == '\t';
+// }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
+ */
+ public int computeCaptionOffset(IDocument document) {
+// return 0;
+ DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length);
+ return findFirstContent(sequence, 0);
+ }
+ }
+
+ /**
+ * Projection position that will return two foldable regions: one folding away
+ * the lines before the one containing the simple name of the C element, one
+ * folding away any lines after the caption.
+ */
+ private static final class CElementPosition extends Position implements IProjectionPosition {
+
+ private IMember fMember;
+
+ public CElementPosition(int offset, int length, IMember member) {
+ super(offset, length);
+ Assert.isNotNull(member);
+ fMember= member;
+ }
+
+ public void setMember(IMember member) {
+ Assert.isNotNull(member);
+ fMember= member;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
+ */
+ public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException {
+ int nameStart= offset;
+ try {
+ /* The member's name range may not be correct. However,
+ * reconciling would trigger another element delta which would
+ * lead to reentrant situations. Therefore, we optimistically
+ * assume that the name range is correct, but double check the
+ * received lines below. */
+ ISourceRange sourceRange= fMember.getSourceRange();
+ if (sourceRange != null)
+ nameStart= sourceRange.getIdStartPos();
+
+ } catch (CModelException e) {
+ // ignore and use default
+ }
+
+ int firstLine= document.getLineOfOffset(offset);
+ int captionLine= document.getLineOfOffset(nameStart);
+ int lastLine= document.getLineOfOffset(offset + length);
+
+ /* see comment above - adjust the caption line to be inside the
+ * entire folded region, and rely on later element deltas to correct
+ * the name range. */
+ if (captionLine < firstLine)
+ captionLine= firstLine;
+ if (captionLine > lastLine)
+ captionLine= lastLine;
+
+ IRegion preRegion;
+ if (firstLine < captionLine) {
+ int preOffset= document.getLineOffset(firstLine);
+ IRegion preEndLineInfo= document.getLineInformation(captionLine);
+ int preEnd= preEndLineInfo.getOffset();
+ preRegion= new Region(preOffset, preEnd - preOffset);
+ } else {
+ preRegion= null;
+ }
+
+ if (captionLine < lastLine) {
+ int postOffset= document.getLineOffset(captionLine + 1);
+ IRegion postRegion= new Region(postOffset, offset + length - postOffset);
+
+ if (preRegion == null)
+ return new IRegion[] { postRegion };
+
+ return new IRegion[] { preRegion, postRegion };
+ }
+
+ if (preRegion != null)
+ return new IRegion[] { preRegion };
+
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
+ */
+ public int computeCaptionOffset(IDocument document) throws BadLocationException {
+ int nameStart= offset;
+ try {
+ // need a reconcile here?
+ ISourceRange sourceRange= fMember.getSourceRange();
+ if (sourceRange != null)
+ nameStart= sourceRange.getIdStartPos();
+ } catch (CModelException e) {
+ // ignore and use default
+ }
+
+ return nameStart - offset;
+ }
+
+ }
- private IDocument fCachedDocument;
-
+ /**
+ * Internal projection listener.
+ */
+ private final class ProjectionListener implements IProjectionListener {
+ private ProjectionViewer fViewer;
+
+ /**
+ * Registers the listener with the viewer.
+ *
+ * @param viewer the viewer to register a listener with
+ */
+ public ProjectionListener(ProjectionViewer viewer) {
+ Assert.isLegal(viewer != null);
+ fViewer= viewer;
+ fViewer.addProjectionListener(this);
+ }
+
+ /**
+ * Disposes of this listener and removes the projection listener from the viewer.
+ */
+ public void dispose() {
+ if (fViewer != null) {
+ fViewer.removeProjectionListener(this);
+ fViewer= null;
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
+ */
+ public void projectionEnabled() {
+ handleProjectionEnabled();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled()
+ */
+ public void projectionDisabled() {
+ handleProjectionDisabled();
+ }
+ }
+
+ /**
+ * Implementation of IRegion
that can be reused
+ * by setting the offset and the length.
+ */
+ private static class ModifiableRegion extends Position implements IRegion {
+ ModifiableRegion() {
+ super();
+ }
+ ModifiableRegion(int offset, int length) {
+ super(offset, length);
+ }
+ }
+
+ /**
+ * Representation of a preprocessor code branch.
+ */
+ private static class Branch extends ModifiableRegion {
+
+ private boolean fTaken;
+
+ /**
+ * @param offset
+ * @param taken
+ */
+ Branch(int offset, boolean taken) {
+ super(offset, 0);
+ fTaken= taken;
+ }
+
+ /**
+ * @param offset
+ * @param length
+ * @param taken
+ */
+ Branch(int offset, int length, boolean taken) {
+ super(offset, length);
+ fTaken= taken;
+ }
+
+ /**
+ * @param endOffset
+ */
+ public void setEndOffset(int endOffset) {
+ setLength(endOffset - getOffset());
+ }
+
+ public boolean taken() {
+ return fTaken;
+ }
+ }
+
+ private final static boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/folding")); //$NON-NLS-1$//$NON-NLS-2$;
+
private ITextEditor fEditor;
- private ProjectionViewer fViewer;
+ private ProjectionListener fProjectionListener;
protected ICElement fInput;
private IElementChangedListener fElementListener;
- private boolean fAllowCollapsing= false;
+ private boolean fCollapseHeaderComments= true;
+ private boolean fCollapseComments= false;
private boolean fCollapseMacros= false;
private boolean fCollapseFunctions= true;
private boolean fCollapseStructures= true;
private boolean fCollapseMethods= false;
+ private boolean fCollapseInactiveCode= true;
+ private int fMinCommentLines= 1;
+ private boolean fPreprocessorBranchFoldingEnabled= true;
+ private boolean fCommentFoldingEnabled= true;
+
+ private ICReconcilingListener fReconilingListener;
+ boolean fInitialASTReconcile= true;
+
+
+ /**
+ * Creates a new folding provider. It must be
+ * {@link #install(ITextEditor, ProjectionViewer) installed} on an editor/viewer pair before it
+ * can be used, and {@link #uninstall() uninstalled} when not used any longer.
+ * + * The projection state may be reset by calling {@link #initialize()}. + *
+ */ public DefaultCFoldingStructureProvider() { } + /* + * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#install(org.eclipse.ui.texteditor.ITextEditor, org.eclipse.jface.text.source.projection.ProjectionViewer) + */ public void install(ITextEditor editor, ProjectionViewer viewer) { + Assert.isLegal(editor != null); + Assert.isLegal(viewer != null); + + internalUninstall(); + if (editor instanceof CEditor) { fEditor= editor; - fViewer= viewer; - fViewer.addProjectionListener(this); + fProjectionListener= new ProjectionListener(viewer); } } - + + /* + * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#uninstall() + */ public void uninstall() { + internalUninstall(); + } + + /** + * Internal implementation of {@link #uninstall()}. + */ + private void internalUninstall() { if (isInstalled()) { - projectionDisabled(); - fViewer.removeProjectionListener(this); - fViewer= null; + handleProjectionDisabled(); + fProjectionListener.dispose(); + fProjectionListener= null; fEditor= null; } } - - protected boolean isInstalled() { + + /** + * Returnstrue
if the provider is installed, false
otherwise.
+ *
+ * @return true
if the provider is installed, false
otherwise
+ */
+ protected final boolean isInstalled() {
return fEditor != null;
}
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
+ /**
+ * Called whenever projection is enabled, for example when the viewer issues a
+ * {@link IProjectionListener#projectionEnabled() projectionEnabled} message. When the provider
+ * is already enabled when this method is called, it is first
+ * {@link #handleProjectionDisabled() disabled}.
+ * + * Subclasses may extend. + *
*/ - public void projectionEnabled() { + protected void handleProjectionEnabled() { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.handleProjectionEnabled()"); //$NON-NLS-1$ // http://home.ott.oti.com/teams/wswb/anon/out/vms/index.html // projectionEnabled messages are not always paired with projectionDisabled // i.e. multiple enabled messages may be sent out. // we have to make sure that we disable first when getting an enable // message. - projectionDisabled(); - + handleProjectionDisabled(); + if (fEditor instanceof CEditor) { + fInitialASTReconcile= true; initialize(); - fElementListener= new ElementChangedListener(); - CoreModel.getDefault().addElementChangedListener(fElementListener); + if (fPreprocessorBranchFoldingEnabled || fCommentFoldingEnabled) { + fReconilingListener= new PreprocessorBranchesReconciler(); + ((CEditor)fEditor).addReconcileListener(fReconilingListener); + } else { + fElementListener= new ElementChangedListener(); + CoreModel.getDefault().addElementChangedListener(fElementListener); + } } } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled() + + /** + * Called whenever projection is disabled, for example when the provider is + * {@link #uninstall() uninstalled}, when the viewer issues a + * {@link IProjectionListener#projectionDisabled() projectionDisabled} message and before + * {@link #handleProjectionEnabled() enabling} the provider. Implementations must be prepared to + * handle multiple calls to this method even if the provider is already disabled. + *+ * Subclasses may extend. + *
*/ - public void projectionDisabled() { - fCachedDocument= null; + protected void handleProjectionDisabled() { if (fElementListener != null) { CoreModel.getDefault().removeElementChangedListener(fElementListener); fElementListener= null; } - } - - public void initialize() { - - if (!isInstalled()) - return; - - initializePreferences(); - - try { - - IDocumentProvider provider= fEditor.getDocumentProvider(); - fCachedDocument= provider.getDocument(fEditor.getEditorInput()); - fAllowCollapsing= true; - - if (fEditor instanceof CEditor) { - IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager(); - fInput= manager.getWorkingCopy(fEditor.getEditorInput()); - } - - if (fInput != null) { - ProjectionAnnotationModel model= (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class); - if (model != null) { - - if (fInput instanceof IWorkingCopy) { - IWorkingCopy unit= (IWorkingCopy) fInput; - synchronized (unit) { - try { - unit.reconcile(); - } catch (CModelException x) { - } - } - } - - Map additions= computeAdditions((IParent) fInput); - model.removeAllAnnotations(); - model.replaceAnnotations(null, additions); - } - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - fCachedDocument= null; - fAllowCollapsing= false; + if (fReconilingListener != null) { + ((CEditor)fEditor).removeReconcileListener(fReconilingListener); + fReconilingListener= null; } } + /* + * @see org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider#initialize() + */ + public final void initialize() { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.initialize()"); //$NON-NLS-1$ + update(createInitialContext()); + } + + private FoldingStructureComputationContext createInitialContext() { + initializePreferences(); + fInput= getInputElement(); + if (fInput == null) + return null; + + return createContext(true); + } + + private FoldingStructureComputationContext createContext(boolean allowCollapse) { + if (!isInstalled()) + return null; + ProjectionAnnotationModel model= getModel(); + if (model == null) + return null; + IDocument doc= getDocument(); + if (doc == null) + return null; + + return new FoldingStructureComputationContext(doc, model, allowCollapse); + } + + private ICElement getInputElement() { + if (fEditor instanceof CEditor) { + return ((CEditor)fEditor).getInputCElement(); + } + return null; + } + private void initializePreferences() { IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); fCollapseFunctions= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_FUNCTIONS); fCollapseStructures= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_STRUCTURES); fCollapseMacros= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_MACROS); fCollapseMethods= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS); + fCollapseHeaderComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS); + fCollapseComments= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS); + fCollapseInactiveCode= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE); + fPreprocessorBranchFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED); + fCommentFoldingEnabled= store.getBoolean(PreferenceConstants.EDITOR_FOLDING_COMMENTS_ENABLED); } - private Map computeAdditions(IParent parent) { - Map map= new HashMap(); - try { - computeAdditions(parent.getChildren(), map); - } catch (CModelException x) { - } - return map; - } - - private void computeAdditions(ICElement[] elements, Map map) throws CModelException { - for (int i= 0; i < elements.length; i++) { - ICElement element= elements[i]; - - computeAdditions(element, map); - - if (element instanceof IParent) { - IParent parent= (IParent) element; - computeAdditions(parent.getChildren(), map); - } - } - } - - private void computeAdditions(ICElement element, Map map) { - - boolean createProjection= false; - - boolean collapse= false; - switch (element.getElementType()) { - - case ICElement.C_STRUCT: - case ICElement.C_CLASS: - case ICElement.C_UNION: - collapse= fAllowCollapsing && fCollapseStructures; - createProjection= true; - break; - case ICElement.C_MACRO: - collapse= fAllowCollapsing && fCollapseMacros; - createProjection= true; - break; - case ICElement.C_FUNCTION: - collapse= fAllowCollapsing && fCollapseFunctions; - createProjection= true; - break; - case ICElement.C_METHOD: - collapse= fAllowCollapsing && fCollapseMethods; - createProjection= true; - break; - } - - if (createProjection) { - Position position= createProjectionPosition(element); - if (position != null) { - map.put(new CProjectionAnnotation(element, collapse, false), position); - } - } - } - - private Position createProjectionPosition(ICElement element) { - - if (fCachedDocument == null) - return null; - - try { - if (element instanceof ISourceReference) { - ISourceReference reference= (ISourceReference) element; - ISourceRange range= reference.getSourceRange(); - - // We need to start at the id position if not code like this - // static int - // foo() - // { } - // will be fold at the wrong line. - - int start= fCachedDocument.getLineOfOffset(range.getIdStartPos()); - int end= fCachedDocument.getLineOfOffset(range.getStartPos() + range.getLength()); - if (start < end) { - int offset= fCachedDocument.getLineOffset(start); - int endOffset= fCachedDocument.getLineOffset(end + 1); - return new Position(offset, endOffset - offset); - } - } - } catch (BadLocationException x) { - } catch (CModelException e) { - } - return null; - } - - protected void processDelta(ICElementDelta delta) { - - if (!isInstalled()) + private void update(FoldingStructureComputationContext ctx) { + if (ctx == null) return; + + Map additions= new HashMap(); + List deletions= new ArrayList(); + List updates= new ArrayList(); - ProjectionAnnotationModel model= (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class); - if (model == null) - return; - - try { - - IDocumentProvider provider= fEditor.getDocumentProvider(); - fCachedDocument= provider.getDocument(fEditor.getEditorInput()); - fAllowCollapsing= false; - - Map additions= new HashMap(); - List deletions= new ArrayList(); - List updates= new ArrayList(); - - Map updated= computeAdditions((IParent) fInput); - Map previous= createAnnotationMap(model); - - - Iterator e= updated.keySet().iterator(); - while (e.hasNext()) { - CProjectionAnnotation annotation= (CProjectionAnnotation) e.next(); - ICElement element= annotation.getElement(); - Position position= (Position) updated.get(annotation); - - List annotations= (List) previous.get(element); - if (annotations == null) { - - additions.put(annotation, position); - - } else { - - Iterator x= annotations.iterator(); - while (x.hasNext()) { - CProjectionAnnotation a= (CProjectionAnnotation) x.next(); - if (annotation.isComment() == a.isComment()) { - Position p= model.getPosition(a); - if (p != null && !position.equals(p)) { - p.setOffset(position.getOffset()); - p.setLength(position.getLength()); - updates.add(a); - } - x.remove(); - break; + computeFoldingStructure(ctx); + Map updated= ctx.fMap; + Map previous= computeCurrentStructure(ctx); + + Iterator e= updated.keySet().iterator(); + while (e.hasNext()) { + CProjectionAnnotation newAnnotation= (CProjectionAnnotation) e.next(); + Object key= newAnnotation.getElement(); + Position newPosition= (Position) updated.get(newAnnotation); + + List annotations= (List) previous.get(key); + if (annotations == null) { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ + + additions.put(newAnnotation, newPosition); + + } else { + Iterator x= annotations.iterator(); + boolean matched= false; + while (x.hasNext()) { + Tuple tuple= (Tuple) x.next(); + CProjectionAnnotation existingAnnotation= tuple.annotation; + Position existingPosition= tuple.position; + if (newAnnotation.isComment() == existingAnnotation.isComment()) { + if (existingPosition != null && (!newPosition.equals(existingPosition) || ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed())) { + existingPosition.setOffset(newPosition.getOffset()); + existingPosition.setLength(newPosition.getLength()); + if (ctx.allowCollapsing() && existingAnnotation.isCollapsed() != newAnnotation.isCollapsed()) + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() change annotation " + newAnnotation); //$NON-NLS-1$ + if (newAnnotation.isCollapsed()) + existingAnnotation.markCollapsed(); + else + existingAnnotation.markExpanded(); + updates.add(existingAnnotation); } - } - - if (annotations.isEmpty()) - previous.remove(element); - } - } - - e= previous.values().iterator(); - while (e.hasNext()) { - List list= (List) e.next(); - int size= list.size(); - for (int i= 0; i < size; i++) - deletions.add(list.get(i)); - } - - match(model, deletions, additions, updates); - - Annotation[] removals= new Annotation[deletions.size()]; - deletions.toArray(removals); - Annotation[] changes= new Annotation[updates.size()]; - updates.toArray(changes); - model.modifyAnnotations(removals, additions, changes); - - } finally { - fCachedDocument= null; - fAllowCollapsing= true; - } - } - - private void match(ProjectionAnnotationModel model, List deletions, Map additions, List changes) { - if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty())) - return; - - List newDeletions= new ArrayList(); - List newChanges= new ArrayList(); - - Iterator deletionIterator= deletions.iterator(); - outer: while (deletionIterator.hasNext()) { - CProjectionAnnotation deleted= (CProjectionAnnotation) deletionIterator.next(); - Position deletedPosition= model.getPosition(deleted); - if (deletedPosition == null) - continue; - - Iterator changesIterator= changes.iterator(); - while (changesIterator.hasNext()) { - CProjectionAnnotation changed= (CProjectionAnnotation) changesIterator.next(); - if (deleted.isComment() == changed.isComment()) { - Position changedPosition= model.getPosition(changed); - if (changedPosition == null) - continue; - - if (deletedPosition.getOffset() == changedPosition.getOffset()) { - - deletedPosition.setLength(changedPosition.getLength()); - deleted.setElement(changed.getElement()); - - deletionIterator.remove(); - newChanges.add(deleted); - - changesIterator.remove(); - newDeletions.add(changed); - - continue outer; - } - } - } - - Iterator additionsIterator= additions.keySet().iterator(); - while (additionsIterator.hasNext()) { - CProjectionAnnotation added= (CProjectionAnnotation) additionsIterator.next(); - if (deleted.isComment() == added.isComment()) { - Position addedPosition= (Position) additions.get(added); - - if (deletedPosition.getOffset() == addedPosition.getOffset()) { - - deletedPosition.setLength(addedPosition.getLength()); - deleted.setElement(added.getElement()); - - deletionIterator.remove(); - newChanges.add(deleted); - - additionsIterator.remove(); - + matched= true; + x.remove(); break; } } + if (!matched) { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() new annotation " + newAnnotation); //$NON-NLS-1$ + + additions.put(newAnnotation, newPosition); + } + if (annotations.isEmpty()) + previous.remove(key); } } - + + e= previous.values().iterator(); + while (e.hasNext()) { + List list= (List) e.next(); + int size= list.size(); + for (int i= 0; i < size; i++) { + CProjectionAnnotation annotation= ((Tuple) list.get(i)).annotation; + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + annotation); //$NON-NLS-1$ + deletions.add(annotation); + } + } + + match(deletions, additions, updates, ctx); + + Annotation[] removals= new Annotation[deletions.size()]; + deletions.toArray(removals); + Annotation[] changes= new Annotation[updates.size()]; + updates.toArray(changes); + 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$ + ctx.getModel().modifyAnnotations(removals, additions, changes); + } + + /** + * Matches deleted annotations to changed or added ones. A deleted + * annotation/position tuple that has a matching addition / change + * is updated and marked as changed. The matching tuple is not added + * (for additions) or marked as deletion instead (for changes). The + * result is that more annotations are changed and fewer get + * deleted/re-added. + */ + private void match(List deletions, Map additions, List changes, FoldingStructureComputationContext ctx) { + if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty())) + return; + + List newDeletions= new ArrayList(); + List newChanges= new ArrayList(); + + Iterator deletionIterator= deletions.iterator(); + while (deletionIterator.hasNext()) { + CProjectionAnnotation deleted= (CProjectionAnnotation) deletionIterator.next(); + Position deletedPosition= ctx.getModel().getPosition(deleted); + if (deletedPosition == null) + continue; + + Tuple deletedTuple= new Tuple(deleted, deletedPosition); + + Tuple match= findMatch(deletedTuple, changes, null, ctx); + boolean addToDeletions= true; + if (match == null) { + match= findMatch(deletedTuple, additions.keySet(), additions, ctx); + addToDeletions= false; + } + + if (match != null) { + Object element= match.annotation.getElement(); + deleted.setElement(element); + deletedPosition.setLength(match.position.getLength()); + if (deletedPosition instanceof CElementPosition && element instanceof IMember) { + CElementPosition jep= (CElementPosition) deletedPosition; + jep.setMember((IMember) element); + } + + deletionIterator.remove(); + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() changed annotation " + deleted); //$NON-NLS-1$ + newChanges.add(deleted); + + if (addToDeletions) { + if (DEBUG) System.out.println("DefaultCFoldingStructureProvider.update() deleted annotation " + match.annotation); //$NON-NLS-1$ + newDeletions.add(match.annotation); + } + } + } + deletions.addAll(newDeletions); changes.addAll(newChanges); } - private Map createAnnotationMap(IAnnotationModel model) { + /** + * Finds a match fortuple
in a collection of
+ * annotations. The positions for the
+ * CProjectionAnnotation
instances in
+ * annotations
can be found in the passed
+ * positionMap
or fCachedModel
if
+ * positionMap
is null
.
+ * + * A tuple is said to match another if their annotations have the + * same comment flag and their position offsets are equal. + *
+ *
+ * If a match is found, the annotation gets removed from
+ * annotations
.
+ *
CProjectionAnnotation
+ * @param positionMap a Map<Annotation, Position>
+ * or null
+ * @return a matching tuple or null
for no match
+ */
+ private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap, FoldingStructureComputationContext ctx) {
+ Iterator it= annotations.iterator();
+ while (it.hasNext()) {
+ CProjectionAnnotation annotation= (CProjectionAnnotation) it.next();
+ if (tuple.annotation.isComment() == annotation.isComment()) {
+ Position position= positionMap == null ? ctx.getModel().getPosition(annotation) : (Position) positionMap.get(annotation);
+ if (position == null)
+ continue;
+
+ if (tuple.position.getOffset() == position.getOffset()) {
+ it.remove();
+ return new Tuple(annotation, position);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private Map computeCurrentStructure(FoldingStructureComputationContext ctx) {
+ boolean includeBranches= fPreprocessorBranchFoldingEnabled && ctx.fAST != null;
Map map= new HashMap();
+ ProjectionAnnotationModel model= ctx.getModel();
Iterator e= model.getAnnotationIterator();
while (e.hasNext()) {
Object annotation= e.next();
if (annotation instanceof CProjectionAnnotation) {
- CProjectionAnnotation c= (CProjectionAnnotation) annotation;
- List list= (List) map.get(c.getElement());
+ CProjectionAnnotation cAnnotation= (CProjectionAnnotation) annotation;
+ if (!includeBranches && cAnnotation.getCategory() == CProjectionAnnotation.BRANCH) {
+ continue;
+ }
+ Position position= model.getPosition(cAnnotation);
+ Assert.isNotNull(position);
+ List list= (List) map.get(cAnnotation.getElement());
if (list == null) {
list= new ArrayList(2);
- map.put(c.getElement(), list);
+ map.put(cAnnotation.getElement(), list);
}
- list.add(c);
+ list.add(new Tuple(cAnnotation, position));
}
}
+
+ Comparator comparator= new Comparator() {
+ public int compare(Object o1, Object o2) {
+ return ((Tuple) o1).position.getOffset() - ((Tuple) o2).position.getOffset();
+ }
+ };
+ for (Iterator it= map.values().iterator(); it.hasNext();) {
+ List list= (List) it.next();
+ Collections.sort(list, comparator);
+ }
return map;
}
+
+
+ private void computeFoldingStructure(FoldingStructureComputationContext ctx) {
+ if (fCommentFoldingEnabled) {
+ // compute comment positions from partitioning
+ try {
+ IDocument doc= ctx.getDocument();
+ ITypedRegion[] partitions = TextUtilities.computePartitioning(doc, ICPartitions.C_PARTITIONING, 0, doc.getLength(), false);
+ computeFoldingStructure(partitions, ctx);
+ } catch (BadLocationException e) {
+ // ignore
+ }
+ }
+ IParent parent= (IParent) fInput;
+ try {
+ computeFoldingStructure(parent.getChildren(), ctx);
+ } catch (CModelException x) {
+ }
+ if (fPreprocessorBranchFoldingEnabled) {
+ IASTTranslationUnit ast= ctx.getAST();
+ if (ast == null) {
+ ASTProvider astProvider= CUIPlugin.getDefault().getASTProvider();
+ ast= astProvider.getAST(getInputElement(), ASTProvider.WAIT_ACTIVE_ONLY, null);
+ if (ast != null) {
+ ctx.fAST= ast;
+ ctx.fASTPositionConverter= astProvider.getActivePositionConverter(getInputElement());
+ fInitialASTReconcile= false;
+ }
+ }
+ computeFoldingStructure(ast, ctx);
+ }
+ }
+
+ /**
+ * Compute folding structure of the preprocessor branches for the given AST.
+ *
+ * @param ast
+ * @param ctx
+ */
+ private void computeFoldingStructure(IASTTranslationUnit ast, FoldingStructureComputationContext ctx) {
+ if (ast == null) {
+ return;
+ }
+ String fileName = ast.getFilePath();
+ if (fileName == null) {
+ return;
+ }
+ IPositionConverter converter= ctx.getASTPositionConverter();
+ List branches= new ArrayList();
+ Stack branchStack = new Stack();
+
+ IASTPreprocessorStatement[] preprocStmts = ast.getAllPreprocessorStatements();
+
+ for (int i = 0; i < preprocStmts.length; i++) {
+ IASTPreprocessorStatement statement = preprocStmts[i];
+ if (!fileName.equals(statement.getContainingFilename())) {
+ // preprocessor directive is from a different file
+ continue;
+ }
+ IASTNodeLocation[] nodeLocations = statement.getNodeLocations();
+ if (nodeLocations.length != 1) {
+ continue;
+ }
+ IASTNodeLocation stmtLocation= nodeLocations[0];
+ if (statement instanceof IASTPreprocessorIfStatement) {
+ IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement;
+ branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifStmt.taken()));
+ } else if (statement instanceof IASTPreprocessorIfdefStatement) {
+ IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement;
+ branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifdefStmt.taken()));
+ } else if (statement instanceof IASTPreprocessorIfndefStatement) {
+ IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement;
+ branchStack.push(new Branch(stmtLocation.getNodeOffset(), ifndefStmt.taken()));
+ } else if (statement instanceof IASTPreprocessorElseStatement) {
+ if (branchStack.isEmpty()) {
+ // #else without #if
+ continue;
+ }
+ Branch branch= (Branch)branchStack.pop();
+ IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement;
+ branchStack.push(new Branch(stmtLocation.getNodeOffset(), elseStmt.taken()));
+ branch.setEndOffset(stmtLocation.getNodeOffset() + stmtLocation.getNodeLength());
+ IRegion converted= converter != null ? converter.historicToActual(branch) : branch;
+ branches.add(new Branch(converted.getOffset(), converted.getLength(), branch.taken()));
+ } else if (statement instanceof IASTPreprocessorElifStatement) {
+ if (branchStack.isEmpty()) {
+ // #elif without #if
+ continue;
+ }
+ Branch branch= (Branch)branchStack.pop();
+ IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement) statement;
+ branchStack.push(new Branch(stmtLocation.getNodeOffset(), elifStmt.taken()));
+ branch.setEndOffset(stmtLocation.getNodeOffset() + stmtLocation.getNodeLength());
+ IRegion converted= converter != null ? converter.historicToActual(branch) : branch;
+ branches.add(new Branch(converted.getOffset(), converted.getLength(), branch.taken()));
+ } else if (statement instanceof IASTPreprocessorEndifStatement) {
+ if (branchStack.isEmpty()) {
+ // #endif without #if
+ continue;
+ }
+ Branch branch= (Branch)branchStack.pop();
+ branch.setEndOffset(stmtLocation.getNodeOffset() + stmtLocation.getNodeLength());
+ IRegion converted= converter != null ? converter.historicToActual(branch) : branch;
+ branches.add(new Branch(converted.getOffset(), converted.getLength(), branch.taken()));
+ }
+ }
+ for (Iterator iter = branches.iterator(); iter.hasNext(); ) {
+ Branch branch= (Branch) iter.next();
+ IRegion aligned = alignRegion(branch, ctx);
+ if (aligned != null) {
+ Position alignedPos= new Position(aligned.getOffset(), aligned.getLength());
+ ctx.addProjectionRange(new CProjectionAnnotation(!branch.taken() && ctx.collapseInactiveCode(), computeKey(branch, ctx), false), alignedPos);
+ }
+ }
+ }
+
+ /**
+ * Compute a key for recognizing an annotation based on the given position.
+ *
+ * @param pos
+ * @param ctx
+ * @return a key to recognise an annotation position
+ */
+ private Object computeKey(Position pos, FoldingStructureComputationContext ctx) {
+ try {
+ return ctx.getDocument().get(pos.offset, Math.min(16, pos.length));
+ } catch (BadLocationException exc) {
+ return exc;
+ }
+ }
+
+ /**
+ * Compute folding structure based on partioning information.
+ *
+ * @param partitions array of document partitions
+ * @param ctx the folding structure context
+ * @throws BadLocationException
+ */
+ private void computeFoldingStructure(ITypedRegion[] partitions, FoldingStructureComputationContext ctx) throws BadLocationException {
+ boolean collapse = ctx.collapseComments();
+ IDocument doc= ctx.getDocument();
+ int startLine = -1;
+ int endLine = -1;
+ List comments= new ArrayList();
+ ModifiableRegion commentRange = new ModifiableRegion();
+ for (int i = 0; i < partitions.length; i++) {
+ ITypedRegion partition = partitions[i];
+ // TLETODO [folding] add support for Cppdoc comment?
+ boolean singleLine = ICPartitions.C_SINGLE_LINE_COMMENT.equals(partition.getType());
+ if (singleLine || ICPartitions.C_MULTI_LINE_COMMENT.equals(partition.getType())) {
+ Position position= singleLine ? null : createCommentPosition(alignRegion(partition, ctx));
+ if (position != null) {
+ comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(position.offset, Math.min(16, position.length)), true), position));
+ } else {
+ // if comment starts at column 0 and spans only one line
+ // and is adjacent to a previous line comment, add it
+ // to the commentRange
+ int lineNr = doc.getLineOfOffset(partition.getOffset());
+ IRegion lineRegion = doc.getLineInformation(lineNr);
+ boolean isLineStart = partition.getOffset() == lineRegion.getOffset();
+ if (!isLineStart) {
+ continue;
+ }
+ if (!singleLine) {
+ singleLine = lineRegion.getOffset() + lineRegion.getLength() >= partition.getOffset() + partition.getLength();
+ if (!singleLine) {
+ continue;
+ }
+ }
+ if (startLine < 0 || lineNr - endLine > 1) {
+ if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
+ Position projection = createCommentPosition(alignRegion(commentRange, ctx));
+ if (projection != null) {
+ comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
+ }
+ }
+ startLine = lineNr;
+ endLine = lineNr;
+ commentRange.offset = lineRegion.getOffset();
+ commentRange.length = lineRegion.getLength();
+ } else {
+ endLine = lineNr;
+ int delta = lineRegion.getOffset() + lineRegion.getLength() - commentRange.offset - commentRange.length;
+ commentRange.length += delta;
+ }
+ }
+ }
+ }
+ if (startLine >= 0 && endLine - startLine >= fMinCommentLines) {
+ Position projection = createCommentPosition(alignRegion(commentRange, ctx));
+ if (projection != null) {
+ comments.add(new Tuple(new CProjectionAnnotation(collapse, doc.get(projection.offset, Math.min(16, projection.length)), true), projection));
+ }
+ }
+ // first comment is header comment
+ Iterator iter = comments.iterator();
+ Tuple tuple = (Tuple) iter.next();
+ if (ctx.collapseHeaderComments()) {
+ tuple.annotation.markCollapsed();
+ } else {
+ tuple.annotation.markExpanded();
+ }
+ ctx.addProjectionRange(tuple.annotation, tuple.position);
+ while (iter.hasNext()) {
+ tuple = (Tuple) iter.next();
+ ctx.addProjectionRange(tuple.annotation, tuple.position);
+ }
+ }
+
+ private void computeFoldingStructure(ICElement[] elements, FoldingStructureComputationContext ctx) throws CModelException {
+ for (int i= 0; i < elements.length; i++) {
+ ICElement element= elements[i];
+
+ computeFoldingStructure(element, ctx);
+
+ if (element instanceof IParent) {
+ IParent parent= (IParent) element;
+ computeFoldingStructure(parent.getChildren(), ctx);
+ }
+ }
+ }
+
+ /**
+ * Computes the folding structure for a given {@link ICElement C element}. Computed
+ * projection annotations are
+ * {@link DefaultCFoldingStructureProvider.FoldingStructureComputationContext#addProjectionRange(DefaultCFoldingStructureProvider.CProjectionAnnotation, Position) added}
+ * to the computation context.
+ * + * Subclasses may extend or replace. The default implementation creates projection annotations + * for the following elements: + *
ISourceReference
. More than one
+ * range or none at all may be returned. If there are no foldable regions, an empty array is
+ * returned.
+ * + * The last region in the returned array (if not empty) describes the region for the C + * element that implements the source reference. Any preceding regions describe comments + * of that element. + *
+ * + * @param reference a C element that is a source reference + * @param ctx the folding context + * @return the regions to be folded + */ + protected final IRegion[] computeProjectionRanges(ISourceReference reference, FoldingStructureComputationContext ctx) { + try { + ISourceRange range= reference.getSourceRange(); + return new IRegion[] { + new Region(range.getStartPos(), range.getLength()) + }; + } catch (CModelException e) { + } + + return new IRegion[0]; + } + + /** + * Creates a comment folding position from an + * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext) aligned} + * region. + * + * @param aligned an aligned region + * @return a folding position corresponding toaligned
+ */
+ protected final Position createCommentPosition(IRegion aligned) {
+ if (aligned == null) {
+ return null;
+ }
+ return new CommentPosition(aligned.getOffset(), aligned.getLength());
+ }
+
+ /**
+ * Creates a folding position that remembers its member from an
+ * {@link #alignRegion(IRegion, DefaultCFoldingStructureProvider.FoldingStructureComputationContext) aligned}
+ * region.
+ *
+ * @param aligned an aligned region
+ * @param member the member to remember
+ * @return a folding position corresponding to aligned
+ */
+ protected final Position createMemberPosition(IRegion aligned, IMember member) {
+ return new CElementPosition(aligned.getOffset(), aligned.getLength(), member);
+ }
+
+ /**
+ * Aligns region
to start and end at a line offset. The region's start is
+ * decreased to the next line offset, and the end offset increased to the next line start or the
+ * end of the document. null
is returned if region
is
+ * null
itself or does not comprise at least one line delimiter, as a single line
+ * cannot be folded.
+ *
+ * @param region the region to align, may be null
+ * @param ctx the folding context
+ * @return a region equal or greater than region
that is aligned with line
+ * offsets, null
if the region is too small to be foldable (e.g. covers
+ * only one line)
+ */
+ protected final IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx) {
+ if (region == null)
+ return null;
+
+ IDocument document= ctx.getDocument();
+
+ try {
+
+ int start= document.getLineOfOffset(region.getOffset());
+ int end= document.getLineOfOffset(region.getOffset() + region.getLength());
+ if (start >= end)
+ return null;
+
+ int offset= document.getLineOffset(start);
+ int endOffset;
+ if (document.getNumberOfLines() > end + 1)
+ endOffset= document.getLineOffset(end + 1);
+ else
+ endOffset= document.getLineOffset(end) + document.getLineLength(end);
+
+ return new Region(offset, endOffset - offset);
+
+ } catch (BadLocationException x) {
+ // concurrent modification
+ return null;
+ }
+ }
+
+ private ProjectionAnnotationModel getModel() {
+ return (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
+ }
+
+ private IDocument getDocument() {
+ IDocumentProvider provider= fEditor.getDocumentProvider();
+ return provider.getDocument(fEditor.getEditorInput());
+ }
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.properties
index 8c37eb1079e..bb2b532e042 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/folding/FoldingMessages.properties
@@ -7,6 +7,7 @@
#
# Contributors:
# IBM Corporation - initial API and implementation
+# Anton Leherbauer (Wind River Systems)
###############################################################################
@@ -15,5 +16,8 @@ DefaultCFoldingPreferenceBlock.macros= &Macros
DefaultCFoldingPreferenceBlock.functions= &Functions
DefaultCFoldingPreferenceBlock.methods= &Methods
DefaultCFoldingPreferenceBlock.structures= &Structures
+DefaultCFoldingPreferenceBlock.comments= &Comments
+DefaultCFoldingPreferenceBlock.headers= &Header Comments
+DefaultCFoldingPreferenceBlock.inactive_code= &Inactive Preprocessor Branches
EmptyCFoldingPreferenceBlock.emptyCaption=
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
index 045dc052fd9..936b6f0edca 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java
@@ -9,6 +9,7 @@
* QNX Software Systems - Initial API and implementation
* IBM Corp. - Rational Software
* Markus Schorn (Wind River Systems)
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui;
@@ -435,6 +436,9 @@ public class CUIPlugin extends AbstractUIPlugin {
}
};
CCorePlugin.getDefault().getDOM().setWorkingCopyProvider(workingCopyProvider);
+
+ // init ast provider
+ getASTProvider();
}
/* (non-Javadoc)
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
index 8aad2f38231..b96fc576d80 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* QNX Software System
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.ui;
@@ -399,6 +400,56 @@ public class PreferenceConstants {
*/
public static final String EDITOR_FOLDING_MACROS= "editor_folding_default_macros"; //$NON-NLS-1$
+ /**
+ * A named preference that stores the value for comment folding for the default folding provider.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
+ * Value is of type Boolean
.
+ *
@@ -545,6 +596,11 @@ public class PreferenceConstants { store.setDefault(PreferenceConstants.EDITOR_FOLDING_STRUCTURES, true); store.setDefault(PreferenceConstants.EDITOR_FOLDING_METHODS, false); store.setDefault(PreferenceConstants.EDITOR_FOLDING_MACROS, true); + store.setDefault(PreferenceConstants.EDITOR_FOLDING_COMMENTS, false); + store.setDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS, true); + store.setDefault(PreferenceConstants.EDITOR_FOLDING_INACTIVE_CODE, true); + store.setDefault(PreferenceConstants.EDITOR_FOLDING_COMMENTS_ENABLED, false); + store.setDefault(PreferenceConstants.EDITOR_FOLDING_PREPROCESSOR_BRANCHES_ENABLED, false); store.setDefault(PreferenceConstants.EDITOR_CLOSE_STRINGS, true); store.setDefault(PreferenceConstants.EDITOR_CLOSE_BRACKETS, true);