diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF
index d4d49f138cd..b9814044cd5 100644
--- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF
+++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF
@@ -53,7 +53,7 @@ Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.internal.core.model.ext;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser;x-internal:=true,
org.eclipse.cdt.internal.core.parser.problem;x-internal:=true,
- org.eclipse.cdt.internal.core.parser.scanner;x-internal:=true,
+ org.eclipse.cdt.internal.core.parser.scanner;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser.scanner2;x-internal:=true,
org.eclipse.cdt.internal.core.parser.token;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser.util;x-internal:=true,
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java
index 1ba10b31de7..4968f3e77be 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/CodeFormatter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * Copyright (c) 2000, 2007 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Anton Leherbauer (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.formatter;
@@ -24,22 +25,22 @@ public abstract class CodeFormatter {
public static final String EMPTY_STRING = ""; //$NON-NLS-1$
/**
- * Unknown kind
+ * Unknown kind.
*/
public static final int K_UNKNOWN = 0x00;
/**
- * Kind used to format an expression
+ * Kind used to format an expression.
*/
public static final int K_EXPRESSION = 0x01;
/**
- * Kind used to format a set of statements
+ * Kind used to format a set of statements.
*/
public static final int K_STATEMENTS = 0x02;
/**
- * Kind used to format a set of class body declarations
+ * Kind used to format a set of class body declarations.
*/
public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
@@ -54,11 +55,11 @@ public abstract class CodeFormatter {
public static final int K_TRANSLATION_UNIT = 0x08;
/**
- * Kind used to format a single-line comment
+ * Kind used to format a single-line comment.
*/
public static final int K_SINGLE_LINE_COMMENT = 0x10;
/**
- * Kind used to format a multi-line comment
+ * Kind used to format a multi-line comment.
*/
public static final int K_MULTI_LINE_COMMENT = 0x20;
@@ -71,7 +72,7 @@ public abstract class CodeFormatter {
* caller to get rid of preceeding whitespaces.
*
* @param kind Use to specify the kind of the code snippet to format. It can be any of these:
- * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_COMPILATION_UNIT, K_UNKNOWN
+ * K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_TRANSLATION_UNIT, K_UNKNOWN
* @param file - file associated with this source (null if no file is associated)
* @param source the document to format
* @param offset the given offset to start recording the edits (inclusive).
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index fb51b89932c..18f0196d693 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -128,6 +128,11 @@ ActionDefinition.gotoMatchingBracket.description= Moves the cursor to the matchi
ActionDefinition.toggleSourceHeader.name= Toggle Source/Header
ActionDefinition.toggleSourceHeader.description= Toggles between corresponding source and header files
+ActionDefinition.backwardMacroExpansion.name= Backward Macro Expansion
+ActionDefinition.backwardMacroExpansion.description= Step backward in macro expansions
+ActionDefinition.forwardMacroExpansion.name= Forward Macro Expansion
+ActionDefinition.forwardMacroExpansion.description= Step forward in macro expansions
+
CEditor.name=C/C++ Editor
CPluginPreferencePage.name=C/C++
@@ -322,6 +327,8 @@ ViewCommand.typeHierarchy.description= Show the Type Hierarchy view
CEditorTextHoversName=C Editor Text Hovers
sourceHover= Source
sourceHoverDescription= Shows the source of the selected element.
+macroExpansionHover= Macro Expansion
+macroExpansionHoverDescription= Shows the expansion of the selected macro.
cdocHover= Documentation
cdocHoverDescription= Shows the documentation of the selected element.
sequentialHover= Combined Hover
@@ -437,4 +444,8 @@ TemplatePreferencePage.name=Template Default Values
Template.Engine.Wizard=template entries contributor
ConfigManager=Dialog for Configurations management
-HelpInfo=Allows contributing the map files to the map-file-based CDT CHelpProvider.
\ No newline at end of file
+HelpInfo=Allows contributing the map files to the map-file-based CDT CHelpProvider.
+
+# Macro Expansion Hover key binding context
+macroExpansionHoverScope.name= In Macro Expansion Hover
+macroExpansionHoverScope.description= In Macro Expansion Hover
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index 22a955db0a5..c7d13f480b6 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -179,6 +179,12 @@
class="org.eclipse.cdt.internal.ui.text.c.hover.CSourceHover"
id="org.eclipse.cdt.ui.CSourceHover">
+
- * Default does nothing.
- *
+ * The default is to return null
.
+ *
null
if
+ * nothing should be persisted
+ */
+ protected String getId() {
+ return null;
+ }
+
+ /**
+ * Returns the source viewer.
+ *
+ * @return the source viewer.
+ */
+ protected final ISourceViewer getSourceViewer() {
+ return fSourceViewer;
+ }
+
+ /**
+ * Returns true
if the control has a header, false
otherwise.
+ *
+ * The default is to return false
.
+ *
true
if the control has a header
+ */
+ protected boolean hasHeader() {
+ // default is to have no header
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInformation(String content) {
+ if (content == null) {
+ fSourceViewer.setDocument(null);
+ return;
+ }
+
+ IDocument doc= new Document(content);
+ CUIPlugin.getDefault().getTextTools().setupCDocument(doc);
+ fSourceViewer.setDocument(doc);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setInput(Object input) {
+ if (input instanceof String)
+ setInformation((String)input);
+ else
+ setInformation(null);
+ }
+
+ /**
+ * Fills the view menu.
+ * Clients can extend or override.
+ *
+ * @param viewMenu the menu manager that manages the menu
+ */
+ protected void fillViewMenu(IMenuManager viewMenu) {
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.PopupDialog#fillDialogMenu(IMenuManager)
+ */
+ protected void fillDialogMenu(IMenuManager dialogMenu) {
+ super.fillDialogMenu(dialogMenu);
+ fillViewMenu(dialogMenu);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setVisible(boolean visible) {
+ if (visible) {
+ open();
+ } else {
+ saveDialogBounds(getShell());
+ getShell().setVisible(false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void dispose() {
+ if (!fIsSystemBackgroundColor) {
+ fBackgroundColor.dispose();
+ }
+ close();
+ }
+
+ protected Point getInitialLocation(Point initialSize) {
+ if (!getPersistBounds()) {
+ Point size = new Point(400, 400);
+ Rectangle parentBounds = getParentShell().getBounds();
+ int x = parentBounds.x + parentBounds.width / 2 - size.x / 2;
+ int y = parentBounds.y + parentBounds.height / 2 - size.y / 2;
+ return new Point(x, y);
+ }
+ return super.getInitialLocation(initialSize);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @param event can be null
+ * + * Subclasses may extend. + *
+ */ + public void widgetDisposed(DisposeEvent event) { + fSourceViewer= null; + } + + /** + * {@inheritDoc} + */ + public boolean hasContents() { + return fSourceViewer != null && fSourceViewer.getDocument() != null; + } + + /** + * {@inheritDoc} + */ + public void setSizeConstraints(int maxWidth, int maxHeight) { + fMaxWidth= maxWidth; + fMaxHeight= maxHeight; + } + + /** + * {@inheritDoc} + */ + public Point computeSizeHint() { + // compute the preferred size + int x= SWT.DEFAULT; + int y= SWT.DEFAULT; + Point size= getShell().computeSize(x, y); + if (size.x > fMaxWidth) + x= fMaxWidth; + if (size.y > fMaxHeight) + y= fMaxHeight; + + // recompute using the constraints if the preferred size is larger than the constraints + if (x != SWT.DEFAULT || y != SWT.DEFAULT) + size= getShell().computeSize(x, y, false); + + return size; +// return getShell().getSize(); + } + + /** + * {@inheritDoc} + */ + public void setLocation(Point location) { + if (!getPersistBounds() || getDialogSettings() == null) + getShell().setLocation(location); + } + + /** + * {@inheritDoc} + */ + public void setSize(int width, int height) { + if (!getPersistBounds() || getDialogSettings() == null) { + getShell().setSize(width, height); + } + } + + /** + * {@inheritDoc} + */ + public void addDisposeListener(DisposeListener listener) { + getShell().addDisposeListener(listener); + } + + /** + * {@inheritDoc} + */ + public void removeDisposeListener(DisposeListener listener) { + getShell().removeDisposeListener(listener); + } + + /** + * {@inheritDoc} + */ + public void setForegroundColor(Color foreground) { + applyForegroundColor(foreground, getContents()); + } + + /** + * {@inheritDoc} + */ + public void setBackgroundColor(Color background) { + applyBackgroundColor(background, getContents()); + } + + /* + * @see org.eclipse.jface.dialogs.PopupDialog#getFocusControl() + */ + protected Control getFocusControl() { + return fSourceViewer.getTextWidget(); + } + + /** + * {@inheritDoc} + */ + public boolean isFocusControl() { + return fSourceViewer.getTextWidget().isFocusControl(); + } + + /** + * {@inheritDoc} + */ + public void setFocus() { + getShell().forceFocus(); + fSourceViewer.getTextWidget().setFocus(); + } + + /** + * {@inheritDoc} + */ + public void addFocusListener(FocusListener listener) { + getShell().addFocusListener(listener); + } + + /** + * {@inheritDoc} + */ + public void removeFocusListener(FocusListener listener) { + getShell().removeFocusListener(listener); + } + + /* + * @see org.eclipse.jface.dialogs.PopupDialog#getDialogSettings() + */ + protected IDialogSettings getDialogSettings() { + String sectionName= getId(); + if (sectionName == null) { + return null; + } + IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings().getSection(sectionName); + if (settings == null) + settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(sectionName); + + return settings; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java index c4053f5dfe9..c62a08c685a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.java @@ -1,91 +1,34 @@ /******************************************************************************* - * Copyright (c) 2002, 2006 QNX Software Systems and others. + * Copyright (c) 2002, 2007 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX Software Systems - Initial API and implementation + * QNX Software Systems - Initial API and implementation + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ - package org.eclipse.cdt.internal.ui.text.c.hover; -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import org.eclipse.osgi.util.NLS; +public final class CHoverMessages extends NLS { -/** - * CHoverMessages - */ -public class CHoverMessages { - - private static final String RESOURCE_BUNDLE= CHoverMessages.class.getName(); - - private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE); + private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.text.c.hover.CHoverMessages";//$NON-NLS-1$ private CHoverMessages() { + // Do not instantiate } - public static String getString(String key) { - try { - return fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ - } - } - /** - * Gets a string from the resource bundle and formats it with the argument - * - * @param key the string used to get the bundle value, must not be null - * @since 3.0 - */ - public static String getFormattedString(String key, Object arg) { - String format= null; - try { - format= fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ - } - if (arg == null) - arg= ""; //$NON-NLS-1$ - return MessageFormat.format(format, new Object[] { arg }); - } - /** - * Gets a string from the resource bundle and formats it with the arguments - * - * @param key the string used to get the bundle value, must not be null - * @since 3.0 - */ - public static String getFormattedString(String key, Object arg1, Object arg2) { - String format= null; - try { - format= fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ - } - if (arg1 == null) - arg1= ""; //$NON-NLS-1$ - if (arg2 == null) - arg2= ""; //$NON-NLS-1$ - return MessageFormat.format(format, new Object[] { arg1, arg2 }); - } - - /** - * Gets a string from the resource bundle and formats it with the argument - * - * @param key the string used to get the bundle value, must not be null - * @since 3.0 - */ - public static String getFormattedString(String key, boolean arg) { - String format= null; - try { - format= fgResourceBundle.getString(key); - } catch (MissingResourceException e) { - return "!" + key + "!";//$NON-NLS-2$ //$NON-NLS-1$ - } - return MessageFormat.format(format, new Object[] { new Boolean(arg) }); - } + public static String CMacroExpansionControl_statusText; -} + public static String CMacroExpansionControl_title_expansion; + public static String CMacroExpansionControl_title_fullyExpanded; + public static String CMacroExpansionControl_title_macroExpansion; + public static String CMacroExpansionControl_title_original; + + static { + NLS.initializeMessages(BUNDLE_NAME, CHoverMessages.class); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties index 673db3a7006..9193bc9a323 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CHoverMessages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2006 IBM Corporation and others. +# Copyright (c) 2000, 2007 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 @@ -7,12 +7,11 @@ # # Contributors: # IBM Corporation - initial API and implementation +# Anton Leherbauer (Wind River Systems) ############################################################################### -TypeHover.more_to_come=\ ... - -CTextHover.createTextHover= Could not create c text hover - -CTextHover.makeStickyHint= Press ''{0}'' for focus. - -NoBreakpointAnnotation.addBreakpoint= Add a breakpoint +CMacroExpansionControl_statusText=Press {0} or {1} to step through macro expansion +CMacroExpansionControl_title_expansion=Expansion \#{0) of {1} +CMacroExpansionControl_title_fullyExpanded=Fully Expanded +CMacroExpansionControl_title_macroExpansion=Macro Expansion +CMacroExpansionControl_title_original=Original 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 new file mode 100644 index 00000000000..4dd5d06bb6d --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionControl.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2007 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 java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.commands.IHandler; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.contexts.IContextActivation; +import org.eclipse.ui.contexts.IContextService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.keys.IBindingService; + +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl; + +/** + * Information control for macro expansion exploration. + * + * @since 5.0 + */ +public class CMacroExpansionControl extends AbstractSourceViewerInformationControl { + + private static final String COMMAND_ID_EXPANSION_BACK= "org.eclipse.cdt.ui.hover.backwardMacroExpansion"; //$NON-NLS-1$ + private static final String COMMAND_ID_EXPANSION_FORWARD= "org.eclipse.cdt.ui.hover.forwardMacroExpansion"; //$NON-NLS-1$ + private static final String CONTEXT_ID_MACRO_EXPANSION_HOVER= "org.eclipse.cdt.ui.macroExpansionHoverScope"; //$NON-NLS-1$ + + private IHandlerService fHandlerService; + private Collection fHandlerActivations; + private IContextService fContextService; + private IContextActivation fContextActivation; + private int fIndex; + private CMacroExpansionInput fInput; + + /** + * 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 style text viewer style bits + * @param input the input object, may benull
+ */
+ public CMacroExpansionControl(Shell parent, int shellStyle, int style, CMacroExpansionInput input) {
+ super(parent, shellStyle, style, true, false, true);
+ setMacroExpansionInput(input);
+ }
+
+ /**
+ * Creates a new control for use as a hover which does not take the focus.
+ *
+ * @param parent parent shell
+ * @param statusFieldText text to be displayed in the status field, may be null
+ */
+ public CMacroExpansionControl(Shell parent, String statusFieldText) {
+ super(parent, SWT.NO_TRIM | SWT.TOOL, SWT.NONE, false, false, false);
+ if (statusFieldText != null) {
+ setInfoText(statusFieldText);
+ }
+ setTitleText(CHoverMessages.CMacroExpansionControl_title_macroExpansion);
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl#hasHeader()
+ */
+ protected boolean hasHeader() {
+ return true;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.PopupDialog#open()
+ */
+ public int open() {
+ int result= super.open();
+
+ if (fInput != null) {
+ IHandler fBackwardHandler= new AbstractHandler() {
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ backward();
+ return null;
+ }
+ };
+ IHandler fForwardHandler= new AbstractHandler() {
+ public Object execute(ExecutionEvent event) throws ExecutionException {
+ forward();
+ return null;
+ }
+ };
+
+ IWorkbench workbench= PlatformUI.getWorkbench();
+ fHandlerService= (IHandlerService) workbench.getService(IHandlerService.class);
+ 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));
+
+ String infoText= getInfoText();
+ if (infoText != null) {
+ setInfoText(infoText);
+ }
+ }
+
+ return result;
+ }
+
+ protected void forward() {
+ ++fIndex;
+ if (fIndex >= fInput.fExpansions.length) {
+ fIndex= 0;
+ }
+ showExpansion(fIndex);
+ }
+
+ protected void backward() {
+ --fIndex;
+ if (fIndex < 0) {
+ fIndex += fInput.fExpansions.length;
+ }
+ showExpansion(fIndex);
+ }
+
+ /**
+ * Returns the text to be shown in the popups's information area.
+ * May return null
.
+ *
+ * @return The text to be shown in the popup's information area or null
+ */
+ protected String getInfoText() {
+ IWorkbench workbench= PlatformUI.getWorkbench();
+ IBindingService bindingService= (IBindingService) workbench.getService(IBindingService.class);
+ String formattedBindingBack= bindingService.getBestActiveBindingFormattedFor(COMMAND_ID_EXPANSION_BACK);
+ String formattedBindingForward= bindingService.getBestActiveBindingFormattedFor(COMMAND_ID_EXPANSION_FORWARD);
+
+ String infoText= null;
+ if (formattedBindingBack != null && formattedBindingForward != null) {
+ infoText= NLS.bind(CHoverMessages.CMacroExpansionControl_statusText, formattedBindingBack, formattedBindingForward);
+ }
+ return infoText;
+ }
+
+ /*
+ * @see org.eclipse.jface.dialogs.PopupDialog#close()
+ */
+ public boolean close() {
+ if (fHandlerService != null) {
+ fHandlerService.deactivateHandlers(fHandlerActivations);
+ fHandlerActivations.clear();
+ fHandlerService= null;
+ }
+ if (fContextActivation != null) {
+ fContextService.deactivateContext(fContextActivation);
+ }
+ return super.close();
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl#getId()
+ */
+ protected String getId() {
+ return "org.eclipse.cdt.ui.text.hover.CMacroExpansion"; //$NON-NLS-1$
+ }
+
+ /*
+ * @see org.eclipse.cdt.internal.ui.text.AbstractSourceViewerInformationControl#setInput(java.lang.Object)
+ */
+ public void setInput(Object input) {
+ if (input instanceof String && fInput == null) {
+ super.setInput(input);
+ return;
+ }
+ if (input instanceof CMacroExpansionInput) {
+ setMacroExpansionInput((CMacroExpansionInput) input);
+ }
+ }
+
+ /**
+ * Set the input for this information control.
+ * @param input
+ */
+ private void setMacroExpansionInput(CMacroExpansionInput input) {
+ fInput= input;
+ fIndex= input.fExpansions.length - 1;
+ showExpansion(fIndex);
+ }
+
+ private void showExpansion(int index) {
+ if (fIndex == 0) {
+ setTitleText(CHoverMessages.CMacroExpansionControl_title_original);
+ } else if (fIndex < fInput.fExpansions.length - 1) {
+ setTitleText(NLS.bind(CHoverMessages.CMacroExpansionControl_title_expansion,
+ String.valueOf(fIndex), String.valueOf(fInput.fExpansions.length - 1)));
+ } else {
+ setTitleText(CHoverMessages.CMacroExpansionControl_title_fullyExpanded);
+ }
+ IDocument document= getSourceViewer().getDocument();
+ if (document == null) {
+ document= new Document(fInput.fExpansions[index]);
+ CUIPlugin.getDefault().getTextTools().setupCDocument(document);
+ getSourceViewer().setDocument(document);
+ } else {
+ document.set(fInput.fExpansions[index]);
+ }
+ }
+}
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
new file mode 100644
index 00000000000..5e46a99574d
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionHover.java
@@ -0,0 +1,675 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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 java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+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.Document;
+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.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.information.IInformationProviderExtension2;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+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.IASTFunctionStyleMacroParameter;
+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.IASTPreprocessorFunctionStyleMacroDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
+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.parser.IScannerExtensionConfiguration;
+import org.eclipse.cdt.core.dom.parser.c.GCCScannerExtensionConfiguration;
+import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration;
+import org.eclipse.cdt.core.formatter.CodeFormatter;
+import org.eclipse.cdt.core.model.ICProject;
+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.core.parser.CodeReader;
+import org.eclipse.cdt.core.parser.EndOfFileException;
+import org.eclipse.cdt.core.parser.IGCCToken;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IToken;
+import org.eclipse.cdt.core.parser.ParserLanguage;
+import org.eclipse.cdt.core.parser.ParserUtil;
+import org.eclipse.cdt.core.parser.ScannerInfo;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.IWorkingCopyManager;
+
+import org.eclipse.cdt.internal.core.dom.NullCodeReaderFactory;
+import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
+import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor;
+import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil;
+
+import org.eclipse.cdt.internal.ui.editor.ASTProvider;
+
+/**
+ * A hover to explore macro expansion.
+ *
+ * @since 5.0
+ */
+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 IASTNode fEnclosingNode;
+ private Map fMacroDict;
+ private List fExpansionNodes= new ArrayList();
+
+ /**
+ * @param tUnit
+ * @param textRegion
+ */
+ private ComputeExpansionRegionRunnable(ITranslationUnit tUnit, IRegion textRegion) {
+ fTextRegion= new Position(textRegion.getOffset(), textRegion.getLength());
+ }
+
+ /*
+ * @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 object style macro expansion 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) {
+ IMacroBinding macroBinding= (IMacroBinding) binding;
+ if (!macroBinding.isFunctionStyle()) {
+ addExpansionNode(node);
+ buildMacroDictionary(ast);
+ return Status.OK_STATUS;
+ }
+ }
+ }
+ // function style macro or 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());
+ buildMacroDictionary(ast);
+ return Status.OK_STATUS;
+ }
+ }
+ }
+ return Status.CANCEL_STATUS;
+ }
+
+ private void buildMacroDictionary(IASTTranslationUnit ast) {
+ Map macroDict= new HashMap(500);
+ IASTPreprocessorMacroDefinition[] macroDefs;
+ final IASTPreprocessorMacroDefinition[] localMacroDefs= ast.getMacroDefinitions();
+ for (macroDefs= localMacroDefs; macroDefs != null; macroDefs= (macroDefs == localMacroDefs) ? ast.getBuiltinMacroDefinitions() : null) {
+ for (int i = 0; i < macroDefs.length; i++) {
+ IASTPreprocessorMacroDefinition macroDef= macroDefs[i];
+ StringBuffer macroName= new StringBuffer();
+ macroName.append(macroDef.getName().toCharArray());
+ if (macroDef instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
+ macroName.append('(');
+ IASTPreprocessorFunctionStyleMacroDefinition functionMacro= (IASTPreprocessorFunctionStyleMacroDefinition)macroDef;
+ IASTFunctionStyleMacroParameter[] macroParams= functionMacro.getParameters();
+ for (int j = 0; j < macroParams.length; j++) {
+ if (j > 0) {
+ macroName.append(',');
+ }
+ IASTFunctionStyleMacroParameter param= macroParams[j];
+ macroName.append(param.getParameter());
+ }
+ macroName.append(')');
+ }
+ macroDict.put(macroName.toString(), macroDef.getExpansion());
+ }
+ }
+ fMacroDict= macroDict;
+ }
+
+ 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;
+ }
+
+ Map getMacroDictionary() {
+ return fMacroDict;
+ }
+
+ IASTNode getEnclosingNode() {
+ return fEnclosingNode;
+ }
+ }
+
+ private static class Cache {
+ ComputeExpansionRegionRunnable fComputer;
+ IWorkingCopy fTranslationUnit;
+ String fExpansionText;
+ String fExpandedText;
+ }
+
+ private WeakReference 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) {
+ IEditorPart editor = getEditor();
+ if (editor == null || !(editor instanceof ITextEditor)) {
+ return null;
+ }
+ IEditorInput input= editor.getEditorInput();
+ IWorkingCopyManager manager= CUIPlugin.getDefault().getWorkingCopyManager();
+ IWorkingCopy tu = manager.getWorkingCopy(input);
+ if (tu == null) {
+ return null;
+ }
+
+ IProgressMonitor monitor= new NullProgressMonitor();
+ ComputeExpansionRegionRunnable computer= new ComputeExpansionRegionRunnable(tu, hoverRegion);
+ 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;
+ }
+ ITextEditor textEditor= (ITextEditor)editor;
+ IDocument document= textEditor.getDocumentProvider().getDocument(input);
+ region= alignRegion(region, document);
+
+ String expansionText;
+ try {
+ expansionText= document.get(region.getOffset(), region.getLength());
+ } catch (BadLocationException exc) {
+ CUIPlugin.getDefault().log(exc);
+ return null;
+ }
+ // expand
+ String expandedText= expandMacros(computer.getMacroDictionary(), expansionText, tu.isCXXLanguage());
+
+ // format
+ final String lineDelimiter= TextUtilities.getDefaultLineDelimiter(document);
+ final int nodeKind = getNodeKind(computer.getEnclosingNode());
+ String formattedText= formatSource(nodeKind, expandedText, lineDelimiter, tu.getCProject());
+
+ // cache objects for later macro exploration
+ Cache cache= new Cache();
+ cache.fComputer= computer;
+ cache.fExpansionText= expansionText;
+ cache.fTranslationUnit= tu;
+ cache.fExpandedText= formattedText;
+ fCache= new WeakReference(cache);
+ return formattedText;
+ }
+
+ private static int getNodeKind(IASTNode node) {
+ if (node instanceof IASTDeclaration) {
+ return CodeFormatter.K_TRANSLATION_UNIT;
+ }
+ if (node instanceof IASTStatement) {
+ return CodeFormatter.K_STATEMENTS;
+ }
+ if (node instanceof IASTExpression) {
+ return CodeFormatter.K_EXPRESSION;
+ }
+ if (node instanceof IASTTranslationUnit) {
+ return CodeFormatter.K_TRANSLATION_UNIT;
+ }
+ return CodeFormatter.K_UNKNOWN;
+ }
+
+ 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;
+ }
+ }
+
+ /**
+ * Format given source content according given options.
+ *
+ * @param kind
+ * one of {@link CodeFormatter#K_TRANSLATION_UNIT},
+ * {@link CodeFormatter#K_STATEMENTS},
+ * {@link CodeFormatter#K_EXPRESSION}
+ * @param content
+ * the source content
+ * @param lineDelimiter
+ * the line delimiter to be used
+ * @param project
+ * @return the formatted source text or the original if the text could not
+ * be formatted successfully
+ */
+ private static String formatSource(int kind, String content, String lineDelimiter, ICProject project) {
+ TextEdit edit= CodeFormatterUtil.format(kind, content, 0, lineDelimiter, project.getOptions(true));
+ if (edit != null) {
+ IDocument doc= new Document(content);
+ try {
+ edit.apply(doc);
+ content= doc.get().trim();
+ } catch (MalformedTreeException exc) {
+ CUIPlugin.getDefault().log(exc);
+ } catch (BadLocationException exc) {
+ CUIPlugin.getDefault().log(exc);
+ }
+ }
+ return content;
+ }
+
+ private String expandMacros(Map macroDict, String expansionText, boolean isCpp) {
+ final IScannerInfo scannerInfo= new ScannerInfo(macroDict);
+ final CodeReader codeReader= new CodeReader(expansionText.toCharArray());
+ final IScannerExtensionConfiguration configuration;
+ final ParserLanguage parserLanguage;
+ if (isCpp) {
+ configuration= new GPPScannerExtensionConfiguration();
+ parserLanguage= ParserLanguage.CPP;
+ } else {
+ configuration= new GCCScannerExtensionConfiguration();
+ parserLanguage= ParserLanguage.C;
+ }
+ CPreprocessor preprocessor= new CPreprocessor(codeReader, scannerInfo, parserLanguage, ParserUtil.getParserLogService(), configuration, NullCodeReaderFactory.getInstance());
+ StringBuffer expandedText= new StringBuffer(expansionText.length());
+ IToken token= null;
+ IToken prevToken;
+ while (true) {
+ try {
+ prevToken= token;
+ token= preprocessor.nextToken();
+ } catch (EndOfFileException exc) {
+ break;
+ }
+ if (requireSpace(prevToken, token)) {
+ expandedText.append(' ');
+ }
+ expandedText.append(token.getImage());
+ }
+ return expandedText.toString();
+ }
+
+ private static boolean requireSpace(IToken prevToken, IToken token) {
+ if (prevToken == null) {
+ return false;
+ }
+ if (prevToken.isOperator() && token.isOperator()) {
+ return true;
+ }
+ switch (prevToken.getType()) {
+ case IToken.tLPAREN: case IToken.tLBRACKET:
+ return false;
+
+ // bit operations
+ case IToken.tAMPERASSIGN:
+ case IToken.tBITOR: case IToken.tBITORASSIGN:
+ case IToken.tSHIFTL: case IToken.tSHIFTLASSIGN:
+ case IToken.tSHIFTR: case IToken.tSHIFTRASSIGN:
+ case IToken.tXOR: case IToken.tXORASSIGN:
+
+ // logical operations
+ case IToken.tAND: case IToken.tOR:
+
+ // arithmetic
+ case IToken.tDIV: case IToken.tDIVASSIGN:
+ case IToken.tMINUS: case IToken.tMINUSASSIGN:
+ case IToken.tMOD: case IToken.tMODASSIGN:
+ case IToken.tPLUS: case IToken.tPLUSASSIGN:
+ case IToken.tSTARASSIGN:
+ case IGCCToken.tMAX: case IGCCToken.tMIN:
+
+ // comparison
+ case IToken.tEQUAL: case IToken.tNOTEQUAL:
+ case IToken.tGT: case IToken.tGTEQUAL:
+ case IToken.tLT: case IToken.tLTEQUAL:
+
+ // other
+ case IToken.tASSIGN: case IToken.tCOMMA:
+ return true;
+ }
+
+ switch (token.getType()) {
+ case IToken.tRPAREN: case IToken.tRBRACKET:
+ return false;
+
+ // bit operations
+ case IToken.tAMPER: case IToken.tAMPERASSIGN:
+ case IToken.tBITOR: case IToken.tBITORASSIGN:
+ case IToken.tSHIFTL: case IToken.tSHIFTLASSIGN:
+ case IToken.tSHIFTR: case IToken.tSHIFTRASSIGN:
+ case IToken.tXOR: case IToken.tXORASSIGN:
+
+ // logical operations
+ case IToken.tAND: case IToken.tOR:
+
+ // arithmetic
+ case IToken.tDIV: case IToken.tDIVASSIGN:
+ case IToken.tMINUS: case IToken.tMINUSASSIGN:
+ case IToken.tMOD: case IToken.tMODASSIGN:
+ case IToken.tPLUS: case IToken.tPLUSASSIGN:
+ case IToken.tSTAR: case IToken.tSTARASSIGN:
+ case IGCCToken.tMAX: case IGCCToken.tMIN:
+
+ // comparison
+ case IToken.tEQUAL: case IToken.tNOTEQUAL:
+ case IToken.tGT: case IToken.tGTEQUAL:
+ case IToken.tLT: case IToken.tLTEQUAL:
+ return true;
+
+ // other
+ case IToken.tASSIGN:
+ return true;
+
+ case IToken.tCOMMA:
+ return false;
+ }
+
+ char lastChar= prevToken.getCharImage()[prevToken.getLength() - 1];
+ char nextChar= token.getCharImage()[0];
+ if (Character.isJavaIdentifierPart(lastChar) && Character.isJavaIdentifierPart(nextChar)) {
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
+ */
+ public IInformationControlCreator getHoverControlCreator() {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new CMacroExpansionControl(parent, getTooltipAffordanceString());
+ }
+ };
+ }
+
+ /*
+ * @see IInformationProviderExtension2#getInformationPresenterControlCreator()
+ */
+ public IInformationControlCreator getInformationPresenterControlCreator() {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ int shellStyle= SWT.RESIZE;
+ int style= SWT.V_SCROLL | SWT.H_SCROLL;
+ return new CMacroExpansionControl(parent, shellStyle, style, createMacroExpansionInput());
+ }
+ };
+ }
+
+ protected CMacroExpansionInput createMacroExpansionInput() {
+ // TODO compute all expansion steps
+ Cache cache= (Cache) fCache.get();
+ fCache= null;
+ if (cache != null) {
+ CMacroExpansionInput input= new CMacroExpansionInput();
+ input.fExpansions= new String[] { cache.fExpansionText, cache.fExpandedText };
+ return input;
+ }
+ return null;
+ }
+
+}
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
new file mode 100644
index 00000000000..586d4bcb1e6
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/CMacroExpansionInput.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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;
+
+/**
+ * An input object to the {@link CMacroExpansionControl}.
+ *
+ * @since 5.0
+ */
+public class CMacroExpansionInput {
+ String[] fExpansions;
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/SourceViewerInformationControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/SourceViewerInformationControl.java
index e596d103986..62e9128a851 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/SourceViewerInformationControl.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/c/hover/SourceViewerInformationControl.java
@@ -193,7 +193,7 @@ public class SourceViewerInformationControl implements IInformationControl, IInf
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas);
fStatusField.setFont(fStatusTextFont);
- GridData gd2= new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING);
+ GridData gd2= new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING);
fStatusField.setLayoutData(gd2);
// Regarding the color see bug 41128
@@ -245,7 +245,7 @@ public class SourceViewerInformationControl implements IInformationControl, IInf
* or null
if the status field should be hidden
* @since 3.0
*/
- public SourceViewerInformationControl(Shell parent,int style, String statusFieldText) {
+ public SourceViewerInformationControl(Shell parent, int style, String statusFieldText) {
this(parent, SWT.NO_TRIM | SWT.TOOL, style, statusFieldText);
}
@@ -313,7 +313,7 @@ public class SourceViewerInformationControl implements IInformationControl, IInf
* @see IInformationControl#setVisible(boolean)
*/
public void setVisible(boolean visible) {
- fShell.setVisible(visible);
+ fShell.setVisible(visible);
}
/**