diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index bc002fb1ff5..208a3c7409b 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -125,6 +125,9 @@ ActionDefinition.backwardMacroExpansion.description= Step backward in macro expa
ActionDefinition.forwardMacroExpansion.name= Forward Macro Expansion
ActionDefinition.forwardMacroExpansion.description= Step forward in macro expansions
+ActionDefinition.showMacroExplorer.name= Explore Macro Expansion
+ActionDefinition.showMacroExplorer.description= Opens a quick view for macro expansion exploration
+
CEditor.name=C/C++ Editor
CPluginPreferencePage.name=C/C++
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index fa05c7398bd..515eec9cd18 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -1480,6 +1480,16 @@
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.edit.text.c.toggleMarkOccurrences"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
+
+
@@ -1638,6 +1648,11 @@
description="%toggleMarkOccurrences.description"
categoryId="org.eclipse.cdt.ui.category.source"
id="org.eclipse.cdt.ui.edit.text.c.toggleMarkOccurrences"/>
+
"org.eclipse.cdt.ui.edit.open.quick.macro.explorer").
+ * @since 5.0
+ */
+ public static final String OPEN_QUICK_MACRO_EXPLORER = "org.eclipse.cdt.ui.edit.open.quick.macro.explorer"; //$NON-NLS-1$
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
index bba98eaa0c0..fd83c63a055 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java
@@ -85,6 +85,8 @@ import org.eclipse.cdt.internal.ui.editor.CElementHyperlinkDetector;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverDescriptor;
import org.eclipse.cdt.internal.ui.text.c.hover.CEditorTextHoverProxy;
import org.eclipse.cdt.internal.ui.text.c.hover.CInformationProvider;
+import org.eclipse.cdt.internal.ui.text.c.hover.CMacroExpansionExplorationControl;
+import org.eclipse.cdt.internal.ui.text.c.hover.CMacroExpansionInformationProvider;
import org.eclipse.cdt.internal.ui.text.contentassist.CContentAssistProcessor;
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
import org.eclipse.cdt.internal.ui.text.correction.CCorrectionAssistant;
@@ -230,8 +232,8 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
}
/**
- * Creates outline presenter.
- * @return Presenter with outline view.
+ * Creates type hierarchy presenter.
+ * @return Presenter with type hierarchy view.
*/
public IInformationPresenter getHierarchyPresenter(ISourceViewer sourceViewer) {
final IInformationControlCreator hierarchyControlCreator = getHierarchyControlCreator();
@@ -833,4 +835,44 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
fCodeScanner= null;
fPreprocessorScanner= null;
}
+
+ /**
+ * Creates macro exploration presenter.
+ * @param sourceViewer
+ * @return Presenter with macro exploration view.
+ *
+ * @since 5.0
+ */
+ public IInformationPresenter getMacroExplorationPresenter(ISourceViewer sourceViewer) {
+ final IInformationControlCreator controlCreator= getMacroExplorationControlCreator();
+ final InformationPresenter presenter = new InformationPresenter(controlCreator);
+ presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
+ presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL);
+ final IInformationProvider provider = new CMacroExpansionInformationProvider(getEditor());
+ presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE);
+ presenter.setInformationProvider(provider, ICPartitions.C_MULTI_LINE_COMMENT);
+ presenter.setInformationProvider(provider, ICPartitions.C_SINGLE_LINE_COMMENT);
+ presenter.setInformationProvider(provider, ICPartitions.C_STRING);
+ presenter.setInformationProvider(provider, ICPartitions.C_CHARACTER);
+ presenter.setInformationProvider(provider, ICPartitions.C_PREPROCESSOR);
+ presenter.setSizeConstraints(50, 20, true, false);
+ return presenter;
+ }
+
+ /**
+ * Creates control for macro exploration in editor.
+ * @return Control.
+ */
+ private IInformationControlCreator getMacroExplorationControlCreator() {
+ final IInformationControlCreator conrolCreator = new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ int shellStyle= SWT.RESIZE;
+ int textStyle= SWT.V_SCROLL | SWT.H_SCROLL;
+ return new CMacroExpansionExplorationControl(parent, shellStyle, textStyle);
+ }
+ };
+ return conrolCreator;
+ }
+
+
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroCompareViewer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroCompareViewer.java
index 56c1f702712..4e2ffd22053 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroCompareViewer.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroCompareViewer.java
@@ -51,20 +51,17 @@ class CMacroCompareViewer extends CMergeViewer {
fBefore= before;
}
- public void setReplaceEdits(ReplaceEdit[] edits) {
- int[] deltas= new int[edits.length];
- if (fBefore) {
- for (int i= 1; i < edits.length; i++) {
- ReplaceEdit edit= edits[i-1];
- deltas[i]= deltas[i-1] + (edit.getText().length() - edit.getLength());
- }
- }
+ public void setReplaceEdits(int prefixLength, ReplaceEdit[] edits) {
fStarts= new int[edits.length];
fLengths= new int[edits.length];
+ int delta= 0;
for (int i= 0; i < edits.length; i++) {
ReplaceEdit edit= edits[i];
- fStarts[i]= edit.getOffset() + deltas[i];
+ fStarts[i]= prefixLength + edit.getOffset() + delta;
fLengths[i]= fBefore ? edit.getLength() : edit.getText().length();
+ if (!fBefore) {
+ delta += edit.getText().length() - edit.getLength();
+ }
}
}
@@ -79,81 +76,6 @@ class CMacroCompareViewer extends CMergeViewer {
}
-// private class MacroExpansionComparator implements ITokenComparator {
-//
-// private final int[] fStarts;
-// private final int[] fLengths;
-// private int fCount;
-//
-// public MacroExpansionComparator(String text, ReplaceEdit[] edits, boolean before) {
-// int[] deltas= new int[edits.length];
-// if (before) {
-// for (int i= 1; i < edits.length; i++) {
-// ReplaceEdit edit= edits[i-1];
-// deltas[i]= deltas[i-1] + (edit.getText().length() - edit.getLength());
-// }
-// }
-// fStarts= new int[edits.length * 2 + 1];
-// fLengths= new int[edits.length * 2 + 1];
-// int offset= 0;
-// int i= 0;
-// for (; i < edits.length; i++) {
-// if (offset >= text.length()) {
-// break;
-// }
-// fStarts[2*i]= offset;
-// ReplaceEdit edit= edits[i];
-// fLengths[2*i]= edit.getOffset() + deltas[i] - offset;
-// fStarts[2*i+1]= edit.getOffset() + deltas[i];
-// fLengths[2*i+1]= before ? edit.getLength() : edit.getText().length();
-// offset= fStarts[2*i+1] + fLengths[2*i+1];
-// }
-// fCount= 2*i;
-//
-// if (offset < text.length()) {
-// fStarts[fCount]= offset;
-// fLengths[fCount]= text.length() - offset;
-// fCount++;
-// }
-// }
-//
-// /*
-// * @see org.eclipse.compare.contentmergeviewer.ITokenComparator#getTokenLength(int)
-// */
-// public int getTokenLength(int index) {
-// return fLengths[index];
-// }
-//
-// /*
-// * @see org.eclipse.compare.contentmergeviewer.ITokenComparator#getTokenStart(int)
-// */
-// public int getTokenStart(int index) {
-// return fStarts[index];
-// }
-//
-// /*
-// * @see org.eclipse.compare.rangedifferencer.IRangeComparator#getRangeCount()
-// */
-// public int getRangeCount() {
-// return fCount;
-// }
-//
-// /*
-// * @see org.eclipse.compare.rangedifferencer.IRangeComparator#rangesEqual(int, org.eclipse.compare.rangedifferencer.IRangeComparator, int)
-// */
-// public boolean rangesEqual(int thisIndex, IRangeComparator other, int otherIndex) {
-// return thisIndex == otherIndex && thisIndex % 2 == 0;
-// }
-//
-// /*
-// * @see org.eclipse.compare.rangedifferencer.IRangeComparator#skipRangeComparison(int, int, org.eclipse.compare.rangedifferencer.IRangeComparator)
-// */
-// public boolean skipRangeComparison(int length, int maxLength, IRangeComparator other) {
-// return false;
-// }
-//
-// }
-
/**
* A dummy {@link ITokenComparator}.
*/
@@ -175,16 +97,19 @@ class CMacroCompareViewer extends CMergeViewer {
}
}
- TextViewer fLeftViewer;
- TextViewer fRightViewer;
- TextViewer fTopViewer;
+ private final ReplaceEditsHighlighter fLeftHighlighter;
+ private final ReplaceEditsHighlighter fRightHighlighter;
+ private Color fChangeBackground;
+
+ private TextViewer fLeftViewer;
+ private TextViewer fRightViewer;
+ private TextViewer fTopViewer;
- int fIndex;
+ private int fViewerIndex;
+
private CMacroExpansionInput fInput;
private int fStepIndex;
- private ReplaceEditsHighlighter fLeftHighlighter;
- private ReplaceEditsHighlighter fRightHighlighter;
- private Color fChangeBackground;
+ private int fPrefixLength;
public CMacroCompareViewer(Composite parent, int styles, CompareConfiguration mp) {
super(parent, styles, mp);
@@ -196,7 +121,7 @@ class CMacroCompareViewer extends CMergeViewer {
fChangeBackground= new Color(parent.getDisplay(), CHANGE_COLOR);
fLeftViewer.addTextPresentationListener(fLeftHighlighter= new ReplaceEditsHighlighter(fChangeBackground, true));
fRightViewer.addTextPresentationListener(fRightHighlighter= new ReplaceEditsHighlighter(fChangeBackground, false));
- fIndex= 0;
+ fViewerIndex= 0;
}
/*
@@ -221,7 +146,7 @@ class CMacroCompareViewer extends CMergeViewer {
super.configureTextViewer(textViewer);
// hack: gain access to text viewers
- switch (fIndex++) {
+ switch (fViewerIndex++) {
case 0:
fTopViewer= textViewer;
break;
@@ -237,20 +162,17 @@ class CMacroCompareViewer extends CMergeViewer {
* @see org.eclipse.compare.contentmergeviewer.TextMergeViewer#createTokenComparator(java.lang.String)
*/
protected ITokenComparator createTokenComparator(String line) {
-// boolean before= fIndex++ % 2 != 0;
-// final IMacroExpansionStep step;
-// if (fStepIndex < fInput.fExplorer.getExpansionStepCount()) {
-// step= fInput.fExplorer.getExpansionStep(fStepIndex);
-// } else {
-// before= !before;
-// step= fInput.fExplorer.getFullExpansion();
-// }
-// return new MacroExpansionComparator(line, step.getReplacements(), before);
return new NullTokenComparator();
}
+ /**
+ * Set the macro expansion input.
+ *
+ * @param input
+ */
public void setMacroExpansionInput(CMacroExpansionInput input) {
fInput= input;
+ fPrefixLength= fInput.getPrefix().length();
}
/*
@@ -261,25 +183,29 @@ class CMacroCompareViewer extends CMergeViewer {
fRightViewer.setRedraw(false);
final ReplaceEdit[] edits;
+
try {
+ final IMacroExpansionStep step;
if (fStepIndex < fInput.fExplorer.getExpansionStepCount()) {
- final IMacroExpansionStep step;
step= fInput.fExplorer.getExpansionStep(fStepIndex);
- edits= step.getReplacements();
} else {
- edits= new ReplaceEdit[0];
+ step= fInput.fExplorer.getFullExpansion();
}
- fLeftHighlighter.setReplaceEdits(edits);
- fRightHighlighter.setReplaceEdits(edits);
+ edits= step.getReplacements();
+
+ fLeftHighlighter.setReplaceEdits(fPrefixLength, edits);
+ fRightHighlighter.setReplaceEdits(fPrefixLength, edits);
super.setInput(input);
+
} finally {
fLeftViewer.setRedraw(true);
fRightViewer.setRedraw(true);
}
if (edits.length > 0) {
- fLeftViewer.revealRange(edits[0].getOffset(), edits[0].getLength());
- fRightViewer.revealRange(edits[0].getOffset(), edits[0].getText().length());
+ final int firstDiffOffset= fPrefixLength + edits[0].getOffset();
+ fLeftViewer.revealRange(firstDiffOffset, edits[0].getLength());
+ fRightViewer.revealRange(firstDiffOffset, edits[0].getText().length());
}
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionControl.java
index 178a17d1b07..2c1b85bc781 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionControl.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionControl.java
@@ -17,7 +17,7 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl;
/**
- * Information control for macro expansion exploration.
+ * Information control for macro expansion.
*
* @since 5.0
*/
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionExplorationControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionExplorationControl.java
index 59273b99963..f9601cde7b1 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionExplorationControl.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionExplorationControl.java
@@ -110,6 +110,17 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
setMacroExpansionInput(input);
}
+ /**
+ * Creates a new control for use as a "quick view" where the control immediately takes the focus.
+ *
+ * @param parent parent shell
+ * @param shellStyle shell style bits
+ * @param textStyle text viewer style bits
+ */
+ public CMacroExpansionExplorationControl(Shell parent, int shellStyle, int textStyle) {
+ this(parent, shellStyle, textStyle, null);
+ }
+
/*
* @see org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl#hasHeader()
*/
@@ -171,13 +182,13 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
int result= super.open();
if (fInput != null) {
- IHandler fBackwardHandler= new AbstractHandler() {
+ IHandler backwardHandler= new AbstractHandler() {
public Object execute(ExecutionEvent event) throws ExecutionException {
backward();
return null;
}
};
- IHandler fForwardHandler= new AbstractHandler() {
+ IHandler forwardHandler= new AbstractHandler() {
public Object execute(ExecutionEvent event) throws ExecutionException {
forward();
return null;
@@ -189,8 +200,8 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
fContextService= (IContextService) workbench.getService(IContextService.class);
fContextActivation= fContextService.activateContext(CONTEXT_ID_MACRO_EXPANSION_HOVER);
fHandlerActivations= new ArrayList();
- fHandlerActivations.add(fHandlerService.activateHandler(COMMAND_ID_EXPANSION_BACK, fBackwardHandler));
- fHandlerActivations.add(fHandlerService.activateHandler(COMMAND_ID_EXPANSION_FORWARD, fForwardHandler));
+ fHandlerActivations.add(fHandlerService.activateHandler(COMMAND_ID_EXPANSION_BACK, backwardHandler));
+ fHandlerActivations.add(fHandlerService.activateHandler(COMMAND_ID_EXPANSION_FORWARD, forwardHandler));
String infoText= getInfoText();
if (infoText != null) {
@@ -202,8 +213,8 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
}
protected void forward() {
- ++fIndex;
- if (fIndex > fInput.fExplorer.getExpansionStepCount()) {
+ fIndex= fixIndex(fIndex + 1);
+ if (fIndex > getStepCount()) {
fIndex= 0;
}
showExpansion();
@@ -212,7 +223,7 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
protected void backward() {
--fIndex;
if (fIndex < 0) {
- fIndex = fInput.fExplorer.getExpansionStepCount();
+ fIndex= fixIndex(getStepCount());
}
showExpansion();
}
@@ -278,37 +289,45 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
*/
private void setMacroExpansionInput(CMacroExpansionInput input) {
fInput= input;
- fIndex= 0;
- if (fMacroCompareViewer != null) {
- fMacroCompareViewer.setMacroExpansionInput(fInput);
+ if (fInput != null) {
+ fIndex= fixIndex(input.fStartWithFullExpansion ? getStepCount() : 0);
+ showExpansion();
}
- showExpansion();
+ }
+
+ private int fixIndex(int index) {
+ if (getStepCount() == 1 && index == 1) {
+ return 0;
+ }
+ return index;
+ }
+
+ private int getStepCount() {
+ return fInput.fExplorer.getExpansionStepCount();
}
private void showExpansion() {
- final int idxLeft= fIndex;
- final int idxRight= (fIndex + 1) % (fInput.fExplorer.getExpansionStepCount() + 1);
+ final int idxLeft= fIndex == getStepCount() ? 0 : fIndex;
+ final int idxRight= fIndex + 1;
CompareConfiguration config= getCompareConfiguration();
- config.setAncestorLabel(getLabelForIndex(0));
config.setLeftLabel(getLabelForIndex(idxLeft));
config.setRightLabel(getLabelForIndex(idxRight));
- final ITypedElement original= getContentForIndex(0);
- final ITypedElement left= getContentForIndex(idxLeft);
- final ITypedElement right= getContentForIndex(idxRight);
+ final ITypedElement left= getContentForIndex(fIndex, true);
+ final ITypedElement right= getContentForIndex(fIndex, false);
setTitleText(CHoverMessages.CMacroExpansionControl_title_macroExpansion);
fMacroViewer.getDocument().set(getMacroText(fIndex));
- setInput(createCompareInput(original, left, right));
+ setInput(createCompareInput(null, left, right));
}
private String getLabelForIndex(int index) {
if (index == 0) {
return CHoverMessages.CMacroExpansionControl_title_original;
- } else if (index < fInput.fExplorer.getExpansionStepCount()) {
+ } else if (index < getStepCount()) {
return NLS.bind(CHoverMessages.CMacroExpansionControl_title_expansion,
- String.valueOf(index), String.valueOf(fInput.fExplorer.getExpansionStepCount()));
+ String.valueOf(index), String.valueOf(getStepCount()));
} else {
return CHoverMessages.CMacroExpansionControl_title_fullyExpanded;
}
@@ -318,12 +337,20 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
return d.findDifferences(false, new NullProgressMonitor(), null, original, left, right);
}
- private ITypedElement getContentForIndex(int index) {
- final String text;
- if (index < fInput.fExplorer.getExpansionStepCount()) {
- text= fInput.fExplorer.getExpansionStep(index).getCodeBeforeStep();
+ private ITypedElement getContentForIndex(int index, boolean before) {
+ final IMacroExpansionStep expansionStep;
+ if (index < getStepCount()) {
+ expansionStep= fInput.fExplorer.getExpansionStep(index);
} else {
- text= fInput.fExplorer.getFullExpansion().getCodeAfterStep();
+ expansionStep= fInput.fExplorer.getFullExpansion();
+ }
+ final String text;
+ final String prefix = fInput.getPrefix();
+ final String postfix = fInput.getPostfix();
+ if (before) {
+ text= prefix + expansionStep.getCodeBeforeStep() + postfix;
+ } else {
+ text= prefix + expansionStep.getCodeAfterStep() + postfix;
}
final Document doc= new Document(text);
CUIPlugin.getDefault().getTextTools().setupCDocument(doc);
@@ -332,7 +359,8 @@ public class CMacroExpansionExplorationControl extends AbstractCompareViewerInfo
private String getMacroText(int index) {
final String text;
- if (index < fInput.fExplorer.getExpansionStepCount()) {
+ final int count= getStepCount();
+ if (index < count) {
final IMacroExpansionStep expansionStep= fInput.fExplorer.getExpansionStep(index);
IMacroBinding binding= expansionStep.getExpandedMacro();
StringBuffer buffer= new StringBuffer();
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionHover.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionHover.java
index a1e52cfab38..05d437847b8 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionHover.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionHover.java
@@ -13,55 +13,19 @@ package org.eclipse.cdt.internal.ui.text.c.hover;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.information.IInformationProviderExtension2;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Shell;
-import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.texteditor.ITextEditor;
-
-import org.eclipse.cdt.core.dom.ast.ASTVisitor;
-import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
-import org.eclipse.cdt.core.dom.ast.IASTExpression;
-import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
-import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
-import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.core.dom.ast.IASTNode;
-import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
-import org.eclipse.cdt.core.dom.ast.IASTStatement;
-import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-import org.eclipse.cdt.core.dom.ast.IBinding;
-import org.eclipse.cdt.core.dom.ast.IMacroBinding;
-import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
-import org.eclipse.cdt.core.model.ILanguage;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.cdt.core.model.IWorkingCopy;
-import org.eclipse.cdt.ui.CUIPlugin;
-import org.eclipse.cdt.ui.IWorkingCopyManager;
-
-import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
-
-import org.eclipse.cdt.internal.ui.editor.ASTProvider;
/**
* A hover to explore macro expansion.
@@ -70,353 +34,26 @@ import org.eclipse.cdt.internal.ui.editor.ASTProvider;
*/
public class CMacroExpansionHover extends AbstractCEditorTextHover implements IInformationProviderExtension2 {
- /**
- * AST visitor to find a node (declaration, statement or expression) enclosing a given source range.
- */
- private static class FindEnclosingNodeAction extends ASTVisitor {
- {
- shouldVisitTranslationUnit= true;
- shouldVisitDeclarations = true;
- shouldVisitStatements = true;
- shouldVisitExpressions = true;
- }
-
- private final int fOffset;
- private final int fEndOffset;
- private final String fFilePath;
- private IASTNode fBestMatch= null;
- private int fBestOffset= -1;
- private int fBestEndOffset= Integer.MAX_VALUE;
-
- public FindEnclosingNodeAction(String filePath, int offset, int length) {
- fFilePath= filePath;
- fOffset= offset;
- fEndOffset= offset + length;
- }
-
- private int processNode(IASTNode node) {
- IASTFileLocation location= node.getFileLocation();
- if (location != null && fFilePath.equals(location.getFileName())) {
- final int startOffset = location.getNodeOffset();
- if (startOffset <= fOffset) {
- int endOffset= startOffset + location.getNodeLength();
- if (endOffset >= fEndOffset) {
- if (startOffset > fBestOffset || endOffset < fBestEndOffset) {
- fBestMatch= node;
- fBestOffset= startOffset;
- fBestEndOffset= endOffset;
- boolean isPerfectMatch= startOffset == fOffset || endOffset == fEndOffset;
- if (isPerfectMatch) {
- return PROCESS_ABORT;
- }
- }
- } else {
- return PROCESS_SKIP;
- }
- } else {
- return PROCESS_ABORT;
- }
- }
- return PROCESS_CONTINUE;
- }
-
- public int visit(IASTTranslationUnit tu) {
- return processNode(tu);
- }
-
- public int visit(IASTDeclaration declaration) {
- return processNode(declaration);
- }
-
- public int visit(IASTExpression expression) {
- return processNode(expression);
- }
-
- public int visit(IASTStatement statement) {
- return processNode(statement);
- }
-
- public IASTNode getNode() {
- return fBestMatch;
- }
- }
-
- /**
- * AST visitor to collect nodes (declaration, statement or expression) enclosed in a given source range.
- */
- private static class CollectEnclosedNodesAction extends ASTVisitor {
- {
- shouldVisitDeclarations = true;
- shouldVisitStatements = true;
- shouldVisitExpressions = true;
- }
-
- private final int fOffset;
- private final int fEndOffset;
- private final String fFilePath;
- private List fMatches= new ArrayList();
-
- public CollectEnclosedNodesAction(String filePath, int offset, int length) {
- fFilePath= filePath;
- fOffset= offset;
- fEndOffset= offset + length;
- }
-
- private int processNode(IASTNode node) {
- IASTFileLocation location= node.getFileLocation();
- if (location != null && fFilePath.equals(location.getFileName())) {
- final int startOffset = location.getNodeOffset();
- if (startOffset >= fOffset) {
- int endOffset= startOffset + location.getNodeLength();
- if (endOffset <= fEndOffset) {
- fMatches.add(node);
- } else {
- return PROCESS_SKIP;
- }
- } else if (startOffset >= fEndOffset) {
- return PROCESS_ABORT;
- }
- }
- return PROCESS_CONTINUE;
- }
-
- public int visit(IASTTranslationUnit tu) {
- return processNode(tu);
- }
-
- public int visit(IASTDeclaration declaration) {
- return processNode(declaration);
- }
-
- public int visit(IASTExpression expression) {
- return processNode(expression);
- }
-
- public int visit(IASTStatement statement) {
- return processNode(statement);
- }
-
- public Collection getNodes() {
- return fMatches;
- }
- }
-
- /**
- * Computes the source location for a given identifier.
- */
- private static class ComputeExpansionRegionRunnable implements ASTRunnable {
- private final Position fTextRegion;
- private final boolean fAllowSelection;
- private IASTNode fEnclosingNode;
- private List fExpansionNodes= new ArrayList();
- private MacroExpansionExplorer fExplorer;
-
- private ComputeExpansionRegionRunnable(ITranslationUnit tUnit, IRegion textRegion, boolean allowSelection) {
- fTextRegion= new Position(textRegion.getOffset(), textRegion.getLength());
- fAllowSelection= allowSelection;
- }
-
- /*
- * @see org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable#runOnAST(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit)
- */
- public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
- if (ast != null) {
- // try macro name match first
- IASTNode node= ast.selectNodeForLocation(ast.getFilePath(), fTextRegion.getOffset(), fTextRegion.getLength());
- if (node instanceof IASTName) {
- IASTName macroName= (IASTName) node;
- IBinding binding= macroName.getBinding();
- if (binding instanceof IMacroBinding) {
- addExpansionNode(node);
- createMacroExpansionExplorer(ast, getExpansionRegion());
- return Status.OK_STATUS;
- }
- }
- if (fAllowSelection) {
- // selection
- FindEnclosingNodeAction nodeFinder= new FindEnclosingNodeAction(ast.getFilePath(), fTextRegion.getOffset(), fTextRegion.getLength());
- ast.accept(nodeFinder);
- fEnclosingNode= nodeFinder.getNode();
- if (fEnclosingNode != null) {
- boolean macroOccurrence= false;
- IASTNodeLocation[] locations= fEnclosingNode.getNodeLocations();
- for (int i = 0; i < locations.length; i++) {
- IASTNodeLocation location= locations[i];
- if (location instanceof IASTMacroExpansion) {
- IASTFileLocation fileLocation= location.asFileLocation();
- if (fileLocation != null && ast.getFilePath().equals(fileLocation.getFileName())) {
- if (fTextRegion.overlapsWith(fileLocation.getNodeOffset(), fileLocation.getNodeLength())) {
- nodeFinder= new FindEnclosingNodeAction(ast.getFilePath(), fileLocation.getNodeOffset(), fileLocation.getNodeLength());
- ast.accept(nodeFinder);
- addExpansionNode(nodeFinder.getNode());
- macroOccurrence= true;
- }
- }
- }
- }
- if (macroOccurrence) {
- CollectEnclosedNodesAction nodeCollector= new CollectEnclosedNodesAction(ast.getFilePath(), fTextRegion.getOffset(), fTextRegion.getLength());
- ast.accept(nodeCollector);
- fExpansionNodes.addAll(nodeCollector.getNodes());
- createMacroExpansionExplorer(ast, getExpansionRegion());
- return Status.OK_STATUS;
- }
- }
- }
- }
- return Status.CANCEL_STATUS;
- }
-
- private void createMacroExpansionExplorer(IASTTranslationUnit ast, IRegion region) {
- if (region != null) {
- fExplorer= MacroExpansionExplorer.create(ast, region);
- }
- }
-
- private void addExpansionNode(IASTNode node) {
- if (node != null) {
- fEnclosingNode= computeCommonAncestor(node, fEnclosingNode);
- fExpansionNodes.add(node);
- }
- }
-
- private IASTNode computeCommonAncestor(IASTNode node, IASTNode other) {
- if (node == null) {
- return null;
- }
- if (other == null) {
- return node;
- }
- if (node == other) {
- return other;
- }
- List ancestors= new ArrayList();
- while (node != null) {
- node= node.getParent();
- ancestors.add(node);
- }
- while (other != null) {
- if (ancestors.contains(other)) {
- return other;
- }
- other= other.getParent();
- }
- return null;
- }
-
- IRegion getExpansionRegion() {
- if (fEnclosingNode != null) {
- int startOffset= Integer.MAX_VALUE;
- int endOffset= 0;
- for (Iterator it= fExpansionNodes.iterator(); it.hasNext(); ) {
- IASTNode node= (IASTNode) it.next();
- if (node != fEnclosingNode) {
- while (node != null && node.getParent() != fEnclosingNode) {
- node= node.getParent();
- }
- }
- if (node != null) {
- IASTFileLocation location= node.getFileLocation();
- if (location != null) {
- startOffset= Math.min(startOffset, location.getNodeOffset());
- endOffset= Math.max(endOffset, location.getNodeOffset() + location.getNodeLength());
- }
- }
- }
- if (endOffset > startOffset) {
- return new Region(startOffset, endOffset - startOffset);
- }
- }
- return null;
- }
-
- IASTNode getEnclosingNode() {
- return fEnclosingNode;
- }
-
- MacroExpansionExplorer getMacroExpansionExplorer() {
- return fExplorer;
- }
- }
-
private Reference fCache;
/*
* @see org.eclipse.cdt.internal.ui.text.c.hover.AbstractCEditorTextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
*/
public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
- CMacroExpansionInput input= createMacroExpansionInput(getEditor(), hoverRegion, true);
+ CMacroExpansionInput input= CMacroExpansionInput.create(getEditor(), hoverRegion, false);
if (input == null) {
return null;
}
+ input.fStartWithFullExpansion= true;
fCache= new SoftReference(input);
- return input.fExplorer.getFullExpansion().getCodeAfterStep();
+ String result= input.fExplorer.getFullExpansion().getCodeAfterStep();
+ if (result.length() == 0) {
+ // expansion is empty - hover should show empty string
+ result= "/* EMPTY */"; //$NON-NLS-1$
+ }
+ return result;
}
- public static CMacroExpansionInput createMacroExpansionInput(IEditorPart editor, IRegion hoverRegion, boolean allowSelection) {
- if (editor == null || !(editor instanceof ITextEditor)) {
- return null;
- }
- IEditorInput editorInput= editor.getEditorInput();
- IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager();
- IWorkingCopy tu = manager.getWorkingCopy(editorInput);
- if (tu == null) {
- return null;
- }
-
- IProgressMonitor monitor= new NullProgressMonitor();
- ComputeExpansionRegionRunnable computer= new ComputeExpansionRegionRunnable(tu, hoverRegion, allowSelection);
- IStatus status= ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_ACTIVE_ONLY, monitor, computer);
- if (!status.isOK()) {
- return null;
- }
- IRegion region= computer.getExpansionRegion();
- if (region == null) {
- return null;
- }
- MacroExpansionExplorer explorer= computer.getMacroExpansionExplorer();
- if (explorer == null) {
- return null;
- }
- ITextEditor textEditor= (ITextEditor)editor;
- IDocument document= textEditor.getDocumentProvider().getDocument(editorInput);
- region= alignRegion(region, document);
-
- CMacroExpansionInput input= new CMacroExpansionInput();
- input.fExplorer= explorer;
- input.fDocument= document;
- input.fRegion= region;
- return input;
- }
-
- private static final IRegion alignRegion(IRegion region, IDocument document) {
- try {
- int start= document.getLineOfOffset(region.getOffset());
- int end= document.getLineOfOffset(region.getOffset() + region.getLength());
- if (start == end) {
- return region;
- }
- int offset= document.getLineOffset(start);
- if (document.get(offset, region.getOffset()- offset).trim().length() > 0) {
- offset= region.getOffset();
- }
- int endOffset;
- if (document.getNumberOfLines() > end + 1) {
- endOffset= document.getLineOffset(end + 1);
- } else {
- endOffset= document.getLineOffset(end) + document.getLineLength(end);
- }
- int oldEndOffset= region.getOffset() + region.getLength();
- if (document.get(oldEndOffset, endOffset - oldEndOffset).trim().length() > 0) {
- endOffset= oldEndOffset;
- }
- return new Region(offset, endOffset - offset);
-
- } catch (BadLocationException x) {
- return region;
- }
- }
-
/*
* @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
*/
@@ -436,12 +73,12 @@ public class CMacroExpansionHover extends AbstractCEditorTextHover implements II
public IInformationControl createInformationControl(Shell parent) {
int shellStyle= SWT.RESIZE;
int style= SWT.V_SCROLL | SWT.H_SCROLL;
- return new CMacroExpansionExplorationControl(parent, shellStyle, style, getMacroExpansionInput());
+ return new CMacroExpansionExplorationControl(parent, shellStyle, style, getCachedMacroExpansionInput());
}
};
}
- protected CMacroExpansionInput getMacroExpansionInput() {
+ protected CMacroExpansionInput getCachedMacroExpansionInput() {
if (fCache == null) {
return null;
}
@@ -455,7 +92,8 @@ public class CMacroExpansionHover extends AbstractCEditorTextHover implements II
if (selection instanceof ITextSelection) {
ITextSelection textSelection= (ITextSelection) selection;
IRegion region= new Region(textSelection.getOffset(), textSelection.getLength());
- input= createMacroExpansionInput(editor, region, true);
+ input= CMacroExpansionInput.create(editor, region, true);
+ input.fStartWithFullExpansion= true;
}
}
}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInformationProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInformationProvider.java
new file mode 100644
index 00000000000..8fc07a87837
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInformationProvider.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Anton Leherbauer (Wind River Systems) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.text.c.hover;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.IInformationProviderExtension;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+
+/**
+ * Information provider for macro exploration.
+ *
+ * @since 5.0
+ */
+public class CMacroExpansionInformationProvider implements IInformationProvider, IInformationProviderExtension {
+
+ private final ITextEditor fEditor;
+
+ public CMacroExpansionInformationProvider(ITextEditor editor) {
+ fEditor= editor;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
+ */
+ public String getInformation(ITextViewer textViewer, IRegion subject) {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer, int)
+ */
+ public IRegion getSubject(ITextViewer textViewer, int offset) {
+ Point selection= textViewer.getSelectedRange();
+ return new Region(selection.x, selection.y);
+ }
+
+ /*
+ * @see org.eclipse.jface.text.information.IInformationProviderExtension#getInformation2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
+ */
+ public Object getInformation2(ITextViewer textViewer, IRegion subject) {
+ return CMacroExpansionInput.create(fEditor, subject, true);
+ }
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java
index 35273705a69..92712588fa2 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java
@@ -11,18 +11,362 @@
package org.eclipse.cdt.internal.ui.text.c.hover;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.cdt.core.dom.ast.ASTVisitor;
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
+import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.rewrite.MacroExpansionExplorer;
+import org.eclipse.cdt.core.model.ILanguage;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.cdt.core.model.IWorkingCopy;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
+
+import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
+
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
/**
* An input object to the {@link CMacroExpansionExplorationControl}.
*
* @since 5.0
*/
-class CMacroExpansionInput {
+public class CMacroExpansionInput {
+
+ /**
+ * AST visitor to find a node (declaration, statement or expression) enclosing a given source range.
+ */
+ private static class FindEnclosingNodeAction extends ASTVisitor {
+ {
+ shouldVisitTranslationUnit= true;
+ shouldVisitDeclarations = true;
+ shouldVisitStatements = true;
+ shouldVisitExpressions = true;
+ }
+
+ private final int fOffset;
+ private final int fEndOffset;
+ private final String fFilePath;
+ private IASTNode fBestMatch= null;
+ private int fBestOffset= -1;
+ private int fBestEndOffset= Integer.MAX_VALUE;
+
+ public FindEnclosingNodeAction(String filePath, int offset, int length) {
+ fFilePath= filePath;
+ fOffset= offset;
+ fEndOffset= offset + length;
+ }
+
+ private int processNode(IASTNode node) {
+ IASTFileLocation location= node.getFileLocation();
+ if (location != null && fFilePath.equals(location.getFileName())) {
+ final int startOffset = location.getNodeOffset();
+ if (startOffset <= fOffset) {
+ int endOffset= startOffset + location.getNodeLength();
+ if (endOffset >= fEndOffset) {
+ if (startOffset > fBestOffset || endOffset < fBestEndOffset) {
+ fBestMatch= node;
+ fBestOffset= startOffset;
+ fBestEndOffset= endOffset;
+ boolean isPerfectMatch= startOffset == fOffset || endOffset == fEndOffset;
+ if (isPerfectMatch) {
+ return PROCESS_ABORT;
+ }
+ }
+ } else {
+ return PROCESS_SKIP;
+ }
+ } else {
+ return PROCESS_ABORT;
+ }
+ }
+ return PROCESS_CONTINUE;
+ }
+
+ public int visit(IASTTranslationUnit tu) {
+ return processNode(tu);
+ }
+
+ public int visit(IASTDeclaration declaration) {
+ return processNode(declaration);
+ }
+
+ public int visit(IASTExpression expression) {
+ return processNode(expression);
+ }
+
+ public int visit(IASTStatement statement) {
+ return processNode(statement);
+ }
+
+ public IASTNode getNode() {
+ return fBestMatch;
+ }
+ }
+
+ /**
+ * Computes the expansion region for a selection.
+ */
+ private static class ExpansionRegionComputer implements ASTRunnable {
+ private final Position fTextRegion;
+ private final boolean fAllowSelection;
+ private IASTNode fEnclosingNode;
+ private List fExpansionNodes= new ArrayList();
+ private MacroExpansionExplorer fExplorer;
+ private IRegion fExpansionRegion;
+
+ private ExpansionRegionComputer(ITranslationUnit tUnit, IRegion textRegion, boolean allowSelection) {
+ fTextRegion= new Position(textRegion.getOffset(), textRegion.getLength());
+ fAllowSelection= allowSelection;
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable#runOnAST(org.eclipse.cdt.core.dom.ast.IASTTranslationUnit)
+ */
+ public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) {
+ if (ast != null) {
+ // try macro name match first
+ IASTNode node= ast.selectNodeForLocation(ast.getFilePath(), fTextRegion.getOffset(), fTextRegion.getLength());
+ if (node instanceof IASTName) {
+ IASTName macroName= (IASTName) node;
+ IBinding binding= macroName.getBinding();
+ if (binding instanceof IMacroBinding && !macroName.isDefinition()) {
+ addExpansionNode(node);
+ createMacroExpansionExplorer(ast);
+ return Status.OK_STATUS;
+ }
+ }
+ if (fAllowSelection) {
+ // selection
+ FindEnclosingNodeAction nodeFinder= new FindEnclosingNodeAction(ast.getFilePath(), fTextRegion.getOffset(), fTextRegion.getLength());
+ ast.accept(nodeFinder);
+ fEnclosingNode= nodeFinder.getNode();
+ if (fEnclosingNode != null) {
+ boolean macroOccurrence= false;
+ IASTNodeLocation[] locations= fEnclosingNode.getNodeLocations();
+ for (int i = 0; i < locations.length; i++) {
+ IASTNodeLocation location= locations[i];
+ if (location instanceof IASTMacroExpansion) {
+ IASTFileLocation fileLocation= location.asFileLocation();
+ if (fileLocation != null && ast.getFilePath().equals(fileLocation.getFileName())) {
+ if (fTextRegion.overlapsWith(fileLocation.getNodeOffset(), fileLocation.getNodeLength())) {
+ nodeFinder= new FindEnclosingNodeAction(ast.getFilePath(), fileLocation.getNodeOffset(), fileLocation.getNodeLength());
+ ast.accept(nodeFinder);
+ addExpansionNode(nodeFinder.getNode());
+ macroOccurrence= true;
+ }
+ }
+ }
+ }
+ if (macroOccurrence) {
+ createMacroExpansionExplorer(ast);
+ return Status.OK_STATUS;
+ }
+ }
+ }
+ }
+ return Status.CANCEL_STATUS;
+ }
+
+ private void createMacroExpansionExplorer(IASTTranslationUnit ast) {
+ IRegion region= getExpansionRegion();
+ if (region != null) {
+ fExplorer= MacroExpansionExplorer.create(ast, region);
+ int length= fExplorer.getExpansionStep(0).getCodeAfterStep().length();
+ if (region.getLength() < length) {
+ region= new Region(region.getOffset(), length);
+ }
+ fExpansionRegion= region;
+ }
+ }
+
+ private void addExpansionNode(IASTNode node) {
+ if (node != null) {
+ fEnclosingNode= computeCommonAncestor(node, fEnclosingNode);
+ fExpansionNodes.add(node);
+ }
+ }
+
+ private IASTNode computeCommonAncestor(IASTNode node, IASTNode other) {
+ if (node == null) {
+ return null;
+ }
+ if (other == null) {
+ return node;
+ }
+ if (node == other) {
+ return other;
+ }
+ List ancestors= new ArrayList();
+ while (node != null) {
+ node= node.getParent();
+ ancestors.add(node);
+ }
+ while (other != null) {
+ if (ancestors.contains(other)) {
+ return other;
+ }
+ other= other.getParent();
+ }
+ return null;
+ }
+
+ IRegion getExpansionRegion() {
+ if (fExpansionRegion != null)
+ return fExpansionRegion;
+ if (fEnclosingNode != null) {
+ int startOffset= Integer.MAX_VALUE;
+ int endOffset= fTextRegion.getOffset() + fTextRegion.getLength();
+ for (Iterator it= fExpansionNodes.iterator(); it.hasNext(); ) {
+ IASTNode node= (IASTNode) it.next();
+ if (node != fEnclosingNode) {
+ while (node != null && node.getParent() != fEnclosingNode) {
+ node= node.getParent();
+ }
+ }
+ if (node != null) {
+ IASTFileLocation location= node.getFileLocation();
+ if (location != null) {
+ startOffset= Math.min(startOffset, location.getNodeOffset());
+ endOffset= Math.max(endOffset, location.getNodeOffset() + location.getNodeLength());
+ }
+ }
+ }
+ if (endOffset > startOffset) {
+ startOffset= Math.min(startOffset, fTextRegion.getOffset());
+ return new Region(startOffset, endOffset - startOffset);
+ }
+ }
+ return null;
+ }
+
+ IASTNode getEnclosingNode() {
+ return fEnclosingNode;
+ }
+
+ MacroExpansionExplorer getMacroExpansionExplorer() {
+ return fExplorer;
+ }
+ }
+
MacroExpansionExplorer fExplorer;
IDocument fDocument;
IRegion fRegion;
+ boolean fStartWithFullExpansion;
+
+ private int fPrefixLength;
+ private int fPostfixLength;
+
+ private CMacroExpansionInput() {
+ // forbidden
+ }
+
+ String getPrefix() {
+ try {
+ return fDocument.get(fRegion.getOffset() - fPrefixLength, fPrefixLength);
+ } catch (BadLocationException exc) {
+ fPrefixLength= 0;
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ String getPostfix() {
+ try {
+ return fDocument.get(fRegion.getOffset() + fRegion.getLength(), fPostfixLength);
+ } catch (BadLocationException exc) {
+ fPostfixLength= 0;
+ return ""; //$NON-NLS-1$
+ }
+ }
+
+ public static CMacroExpansionInput create(IEditorPart editor, IRegion hoverRegion, boolean allowSelection) {
+ if (editor == null || !(editor instanceof ITextEditor)) {
+ return null;
+ }
+ IEditorInput editorInput= editor.getEditorInput();
+ IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager();
+ IWorkingCopy tu = manager.getWorkingCopy(editorInput);
+ if (tu == null) {
+ return null;
+ }
+
+ IProgressMonitor monitor= new NullProgressMonitor();
+ ExpansionRegionComputer computer= new ExpansionRegionComputer(tu, hoverRegion, allowSelection);
+ IStatus status= ASTProvider.getASTProvider().runOnAST(tu, ASTProvider.WAIT_ACTIVE_ONLY, monitor, computer);
+ if (!status.isOK()) {
+ return null;
+ }
+ IRegion region= computer.getExpansionRegion();
+ if (region == null) {
+ return null;
+ }
+ MacroExpansionExplorer explorer= computer.getMacroExpansionExplorer();
+ if (explorer == null) {
+ return null;
+ }
+ ITextEditor textEditor= (ITextEditor)editor;
+ IDocument document= textEditor.getDocumentProvider().getDocument(editorInput);
+
+ CMacroExpansionInput input= new CMacroExpansionInput();
+ input.fExplorer= explorer;
+ input.fDocument= document;
+ input.fRegion= region;
+
+ // add context lines
+// IRegion contextRegion= expandRegion(region, document, 2);
+// input.fPrefixLength= region.getOffset() - contextRegion.getOffset();
+// input.fPostfixLength= contextRegion.getOffset() + contextRegion.getLength() - (region.getOffset() + region.getLength());
+ return input;
+ }
+
+ public static final IRegion expandRegion(IRegion region, IDocument document, int contextLines) {
+ try {
+ int start= document.getLineOfOffset(region.getOffset());
+ start= Math.max(start - contextLines, 0);
+ int offset= document.getLineOffset(start);
+ CHeuristicScanner scanner= new CHeuristicScanner(document);
+ offset= scanner.findNonWhitespaceForward(offset, region.getOffset() + 1);
+
+ int end= document.getLineOfOffset(region.getOffset() + region.getLength());
+ end= Math.min(end + contextLines, document.getNumberOfLines() - 1);
+
+ final 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) {
+ return region;
+ }
+ }
+
}