mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
23540: Macro-expansion hover
This commit is contained in:
parent
90a4f3e836
commit
1d35805d67
14 changed files with 1484 additions and 213 deletions
|
@ -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.model.ext;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.parser;x-internal:=true,
|
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.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.scanner2;x-internal:=true,
|
||||||
org.eclipse.cdt.internal.core.parser.token;x-friends:="org.eclipse.cdt.ui",
|
org.eclipse.cdt.internal.core.parser.token;x-friends:="org.eclipse.cdt.ui",
|
||||||
org.eclipse.cdt.internal.core.parser.util;x-internal:=true,
|
org.eclipse.cdt.internal.core.parser.util;x-internal:=true,
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Corporation - initial API and implementation
|
* IBM Corporation - initial API and implementation
|
||||||
|
* Anton Leherbauer (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.formatter;
|
package org.eclipse.cdt.core.formatter;
|
||||||
|
|
||||||
|
@ -24,22 +25,22 @@ public abstract class CodeFormatter {
|
||||||
public static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
public static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unknown kind
|
* Unknown kind.
|
||||||
*/
|
*/
|
||||||
public static final int K_UNKNOWN = 0x00;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
public static final int K_MULTI_LINE_COMMENT = 0x20;
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ public abstract class CodeFormatter {
|
||||||
* caller to get rid of preceeding whitespaces.
|
* 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:
|
* @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 file - file associated with this source (null if no file is associated)
|
||||||
* @param source the document to format
|
* @param source the document to format
|
||||||
* @param offset the given offset to start recording the edits (inclusive).
|
* @param offset the given offset to start recording the edits (inclusive).
|
||||||
|
|
|
@ -128,6 +128,11 @@ ActionDefinition.gotoMatchingBracket.description= Moves the cursor to the matchi
|
||||||
ActionDefinition.toggleSourceHeader.name= Toggle Source/Header
|
ActionDefinition.toggleSourceHeader.name= Toggle Source/Header
|
||||||
ActionDefinition.toggleSourceHeader.description= Toggles between corresponding source and header files
|
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
|
CEditor.name=C/C++ Editor
|
||||||
|
|
||||||
CPluginPreferencePage.name=C/C++
|
CPluginPreferencePage.name=C/C++
|
||||||
|
@ -322,6 +327,8 @@ ViewCommand.typeHierarchy.description= Show the Type Hierarchy view
|
||||||
CEditorTextHoversName=C Editor Text Hovers
|
CEditorTextHoversName=C Editor Text Hovers
|
||||||
sourceHover= Source
|
sourceHover= Source
|
||||||
sourceHoverDescription= Shows the source of the selected element.
|
sourceHoverDescription= Shows the source of the selected element.
|
||||||
|
macroExpansionHover= Macro Expansion
|
||||||
|
macroExpansionHoverDescription= Shows the expansion of the selected macro.
|
||||||
cdocHover= Documentation
|
cdocHover= Documentation
|
||||||
cdocHoverDescription= Shows the documentation of the selected element.
|
cdocHoverDescription= Shows the documentation of the selected element.
|
||||||
sequentialHover= Combined Hover
|
sequentialHover= Combined Hover
|
||||||
|
@ -438,3 +445,7 @@ Template.Engine.Wizard=template entries contributor
|
||||||
ConfigManager=Dialog for Configurations management
|
ConfigManager=Dialog for Configurations management
|
||||||
|
|
||||||
HelpInfo=Allows contributing the map files to the map-file-based CDT CHelpProvider.
|
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
|
||||||
|
|
|
@ -179,6 +179,12 @@
|
||||||
class="org.eclipse.cdt.internal.ui.text.c.hover.CSourceHover"
|
class="org.eclipse.cdt.internal.ui.text.c.hover.CSourceHover"
|
||||||
id="org.eclipse.cdt.ui.CSourceHover">
|
id="org.eclipse.cdt.ui.CSourceHover">
|
||||||
</hover>
|
</hover>
|
||||||
|
<hover
|
||||||
|
label="%macroExpansionHover"
|
||||||
|
description="%macroExpansionHoverDescription"
|
||||||
|
class="org.eclipse.cdt.internal.ui.text.c.hover.CMacroExpansionHover"
|
||||||
|
id="org.eclipse.cdt.ui.CMacroExpansionHover">
|
||||||
|
</hover>
|
||||||
<!--hover
|
<!--hover
|
||||||
label="%problemHover"
|
label="%problemHover"
|
||||||
description="%problemHoverDescription"
|
description="%problemHoverDescription"
|
||||||
|
@ -1287,7 +1293,14 @@
|
||||||
id="org.eclipse.cdt.ui.cViewScope"
|
id="org.eclipse.cdt.ui.cViewScope"
|
||||||
parentId="org.eclipse.ui.contexts.window"
|
parentId="org.eclipse.ui.contexts.window"
|
||||||
/>
|
/>
|
||||||
|
<context
|
||||||
|
name="%macroExpansionHoverScope.name"
|
||||||
|
description="%macroExpansionHoverScope.description"
|
||||||
|
id="org.eclipse.cdt.ui.macroExpansionHoverScope"
|
||||||
|
parentId="org.eclipse.ui.contexts.dialogAndWindow"
|
||||||
|
/>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
<extension point="org.eclipse.ui.bindings">
|
<extension point="org.eclipse.ui.bindings">
|
||||||
<!-- win32: M1=CTRL, M2=SHIFT, M3=ALT, M4=-
|
<!-- win32: M1=CTRL, M2=SHIFT, M3=ALT, M4=-
|
||||||
carbon: M1=COMMAND, M2=SHIFT, M3=ALT, M4=CTRL -->
|
carbon: M1=COMMAND, M2=SHIFT, M3=ALT, M4=CTRL -->
|
||||||
|
@ -1437,6 +1450,16 @@
|
||||||
contextId="org.eclipse.cdt.ui.cEditorScope"
|
contextId="org.eclipse.cdt.ui.cEditorScope"
|
||||||
commandId="org.eclipse.cdt.ui.edit.text.c.toggle.source.header"
|
commandId="org.eclipse.cdt.ui.edit.text.c.toggle.source.header"
|
||||||
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
|
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
|
||||||
|
<key
|
||||||
|
sequence="M3+ARROW_LEFT"
|
||||||
|
contextId="org.eclipse.cdt.ui.macroExpansionHoverScope"
|
||||||
|
commandId="org.eclipse.cdt.ui.hover.backwardMacroExpansion"
|
||||||
|
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
|
||||||
|
<key
|
||||||
|
sequence="M3+ARROW_RIGHT"
|
||||||
|
contextId="org.eclipse.cdt.ui.macroExpansionHoverScope"
|
||||||
|
commandId="org.eclipse.cdt.ui.hover.forwardMacroExpansion"
|
||||||
|
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"/>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.ui.commands">
|
point="org.eclipse.ui.commands">
|
||||||
|
@ -1580,6 +1603,16 @@
|
||||||
categoryId="org.eclipse.cdt.ui.category.source"
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
id="org.eclipse.cdt.ui.edit.text.c.toggle.source.header">
|
id="org.eclipse.cdt.ui.edit.text.c.toggle.source.header">
|
||||||
</command>
|
</command>
|
||||||
|
<command
|
||||||
|
name="%ActionDefinition.backwardMacroExpansion.name"
|
||||||
|
description="%ActionDefinition.backwardMacroExpansion.description"
|
||||||
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
|
id="org.eclipse.cdt.ui.hover.backwardMacroExpansion"/>
|
||||||
|
<command
|
||||||
|
name="%ActionDefinition.forwardMacroExpansion.name"
|
||||||
|
description="%ActionDefinition.forwardMacroExpansion.description"
|
||||||
|
categoryId="org.eclipse.cdt.ui.category.source"
|
||||||
|
id="org.eclipse.cdt.ui.hover.forwardMacroExpansion"/>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
id="pdomSearchPage"
|
id="pdomSearchPage"
|
||||||
|
|
|
@ -129,7 +129,25 @@ public class CodeFormatterUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextEdit format(int kind, String source, int indentationLevel, String lineSeparator, Map options) {
|
public static TextEdit format(int kind, String source, int indentationLevel, String lineSeparator, Map options) {
|
||||||
return format(kind, source, 0, source.length(), indentationLevel, lineSeparator, options);
|
String prefix= ""; //$NON-NLS-1$
|
||||||
|
String suffix= ""; //$NON-NLS-1$
|
||||||
|
switch (kind) {
|
||||||
|
case CodeFormatter.K_EXPRESSION:
|
||||||
|
prefix= "int __dummy__="; //$NON-NLS-1$
|
||||||
|
suffix= ";"; //$NON-NLS-1$
|
||||||
|
break;
|
||||||
|
case CodeFormatter.K_STATEMENTS:
|
||||||
|
prefix= "void __dummy__() {"; //$NON-NLS-1$
|
||||||
|
suffix= "}"; //$NON-NLS-1$
|
||||||
|
--indentationLevel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String tuSource= prefix + source + suffix;
|
||||||
|
TextEdit edit= format(CodeFormatter.K_TRANSLATION_UNIT, tuSource, prefix.length(), source.length(), indentationLevel, lineSeparator, options);
|
||||||
|
if (edit != null && prefix.length() > 0) {
|
||||||
|
edit.moveTree(-prefix.length());
|
||||||
|
}
|
||||||
|
return edit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -398,7 +398,7 @@ public final class IndentUtil {
|
||||||
int minIndent= Integer.MAX_VALUE;
|
int minIndent= Integer.MAX_VALUE;
|
||||||
for (int line= 0; line < numberOfLines; line++) {
|
for (int line= 0; line < numberOfLines; line++) {
|
||||||
int length= computeVisualLength(getCurrentIndent(document, line + first, indentInsideLineComments), tabSize);
|
int length= computeVisualLength(getCurrentIndent(document, line + first, indentInsideLineComments), tabSize);
|
||||||
if (length < minIndent) {
|
if (length < minIndent && document.getLineLength(line + first) > 0) {
|
||||||
minIndent= length;
|
minIndent= length;
|
||||||
minLine= line;
|
minLine= line;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -11,8 +11,6 @@
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.jface.action.Action;
|
|
||||||
import org.eclipse.jface.action.IAction;
|
|
||||||
import org.eclipse.jface.action.IMenuManager;
|
import org.eclipse.jface.action.IMenuManager;
|
||||||
import org.eclipse.jface.dialogs.Dialog;
|
import org.eclipse.jface.dialogs.Dialog;
|
||||||
import org.eclipse.jface.dialogs.IDialogSettings;
|
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||||
|
@ -48,7 +46,6 @@ import org.eclipse.swt.layout.GridData;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
import org.eclipse.swt.widgets.Item;
|
import org.eclipse.swt.widgets.Item;
|
||||||
import org.eclipse.swt.widgets.Label;
|
|
||||||
import org.eclipse.swt.widgets.Shell;
|
import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.swt.widgets.Text;
|
import org.eclipse.swt.widgets.Text;
|
||||||
import org.eclipse.swt.widgets.Tree;
|
import org.eclipse.swt.widgets.Tree;
|
||||||
|
@ -112,8 +109,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
private TreeViewer fTreeViewer;
|
private TreeViewer fTreeViewer;
|
||||||
/** The current string matcher */
|
/** The current string matcher */
|
||||||
protected StringMatcher fStringMatcher;
|
protected StringMatcher fStringMatcher;
|
||||||
// private ICommand fInvokingCommand;
|
|
||||||
// private KeySequence[] fInvokingCommandKeySequences;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fields that support the dialog menu
|
* Fields that support the dialog menu
|
||||||
|
@ -123,11 +118,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
|
|
||||||
private CustomFiltersActionGroup fCustomFiltersActionGroup;
|
private CustomFiltersActionGroup fCustomFiltersActionGroup;
|
||||||
|
|
||||||
// private IKeyBindingService fKeyBindingService;
|
|
||||||
// private String[] fKeyBindingScopes;
|
|
||||||
private IAction fShowViewMenuAction;
|
|
||||||
// private HandlerSubmission fShowViewMenuHandlerSubmission;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field for tree style since it must be remembered by the instance.
|
* Field for tree style since it must be remembered by the instance.
|
||||||
*/
|
*/
|
||||||
|
@ -145,15 +135,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
*/
|
*/
|
||||||
public AbstractInformationControl(Shell parent, int shellStyle, int treeStyle, String invokingCommandId, boolean showStatusField) {
|
public AbstractInformationControl(Shell parent, int shellStyle, int treeStyle, String invokingCommandId, boolean showStatusField) {
|
||||||
super(parent, shellStyle, true, true, true, true, null, null);
|
super(parent, shellStyle, true, true, true, true, null, null);
|
||||||
if (invokingCommandId != null) {
|
|
||||||
// ICommandManager commandManager= PlatformUI.getWorkbench().getCommandSupport().getCommandManager();
|
|
||||||
// fInvokingCommand= commandManager.getCommand(invokingCommandId);
|
|
||||||
// if (fInvokingCommand != null && !fInvokingCommand.isDefined())
|
|
||||||
// fInvokingCommand= null;
|
|
||||||
// else
|
|
||||||
// // Pre-fetch key sequence - do not change because scope will change later.
|
|
||||||
// getInvokingCommandKeySequences();
|
|
||||||
}
|
|
||||||
fTreeStyle= treeStyle;
|
fTreeStyle= treeStyle;
|
||||||
// Title and status text must be set to get the title label created, so force empty values here.
|
// Title and status text must be set to get the title label created, so force empty values here.
|
||||||
if (hasHeader())
|
if (hasHeader())
|
||||||
|
@ -329,24 +310,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
return fFilterText;
|
return fFilterText;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createHorizontalSeparator(Composite parent) {
|
|
||||||
Label separator= new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT);
|
|
||||||
separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateStatusFieldText() {
|
|
||||||
setInfoText(getStatusFieldText());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles click in status field.
|
|
||||||
* <p>
|
|
||||||
* Default does nothing.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
protected void handleStatusFieldClicked() {
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getStatusFieldText() {
|
protected String getStatusFieldText() {
|
||||||
return ""; //$NON-NLS-1$
|
return ""; //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
@ -514,13 +477,10 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
*/
|
*/
|
||||||
public void setVisible(boolean visible) {
|
public void setVisible(boolean visible) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
addHandlerAndKeyBindingSupport();
|
|
||||||
open();
|
open();
|
||||||
} else {
|
} else {
|
||||||
removeHandlerAndKeyBindingSupport();
|
|
||||||
saveDialogBounds(getShell());
|
saveDialogBounds(getShell());
|
||||||
getShell().setVisible(false);
|
getShell().setVisible(false);
|
||||||
removeHandlerAndKeyBindingSupport();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,42 +499,8 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void widgetDisposed(DisposeEvent event) {
|
public void widgetDisposed(DisposeEvent event) {
|
||||||
removeHandlerAndKeyBindingSupport();
|
|
||||||
fTreeViewer= null;
|
fTreeViewer= null;
|
||||||
fFilterText= null;
|
fFilterText= null;
|
||||||
// fKeyBindingService= null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds handler and key binding support.
|
|
||||||
*/
|
|
||||||
protected void addHandlerAndKeyBindingSupport() {
|
|
||||||
// // Remember current scope and then set window context.
|
|
||||||
// if (fKeyBindingScopes == null && fKeyBindingService != null) {
|
|
||||||
// fKeyBindingScopes= fKeyBindingService.getScopes();
|
|
||||||
// fKeyBindingService.setScopes(new String[] { IWorkbenchContextSupport.CONTEXT_ID_WINDOW });
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Register action with command support
|
|
||||||
// if (fShowViewMenuHandlerSubmission == null) {
|
|
||||||
// fShowViewMenuHandlerSubmission= new HandlerSubmission(null, getShell(), null, fShowViewMenuAction.getActionDefinitionId(), new ActionHandler(fShowViewMenuAction), Priority.MEDIUM);
|
|
||||||
// PlatformUI.getWorkbench().getCommandSupport().addHandlerSubmission(fShowViewMenuHandlerSubmission);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes handler and key binding support.
|
|
||||||
*/
|
|
||||||
protected void removeHandlerAndKeyBindingSupport() {
|
|
||||||
// // Remove handler submission
|
|
||||||
// if (fShowViewMenuHandlerSubmission != null)
|
|
||||||
// PlatformUI.getWorkbench().getCommandSupport().removeHandlerSubmission(fShowViewMenuHandlerSubmission);
|
|
||||||
//
|
|
||||||
// // Restore editor's key binding scope
|
|
||||||
// if (fKeyBindingService != null && fKeyBindingScopes != null) {
|
|
||||||
// fKeyBindingService.setScopes(fKeyBindingScopes);
|
|
||||||
// fKeyBindingScopes= null;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -683,26 +609,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
getShell().removeFocusListener(listener);
|
getShell().removeFocusListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
// final protected ICommand getInvokingCommand() {
|
|
||||||
// return fInvokingCommand;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// final protected KeySequence[] getInvokingCommandKeySequences() {
|
|
||||||
// if (fInvokingCommandKeySequences == null) {
|
|
||||||
// if (getInvokingCommand() != null) {
|
|
||||||
// List list= getInvokingCommand().getKeySequenceBindings();
|
|
||||||
// if (!list.isEmpty()) {
|
|
||||||
// fInvokingCommandKeySequences= new KeySequence[list.size()];
|
|
||||||
// for (int i= 0; i < fInvokingCommandKeySequences.length; i++) {
|
|
||||||
// fInvokingCommandKeySequences[i]= ((IKeySequenceBinding) list.get(i)).getKeySequence();
|
|
||||||
// }
|
|
||||||
// return fInvokingCommandKeySequences;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return fInvokingCommandKeySequences;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.jface.dialogs.PopupDialog#getDialogSettings()
|
* @see org.eclipse.jface.dialogs.PopupDialog#getDialogSettings()
|
||||||
*/
|
*/
|
||||||
|
@ -729,26 +635,6 @@ public abstract class AbstractInformationControl extends PopupDialog implements
|
||||||
fFilterText= createFilterText(parent);
|
fFilterText= createFilterText(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a key binding for showing the dialog menu
|
|
||||||
// Key binding service
|
|
||||||
// IWorkbenchPart part= CUIPlugin.getActivePage().getActivePart();
|
|
||||||
// IWorkbenchPartSite site= part.getSite();
|
|
||||||
// fKeyBindingService= site.getKeyBindingService();
|
|
||||||
|
|
||||||
// Create show view menu action
|
|
||||||
fShowViewMenuAction= new Action("showViewMenu") { //$NON-NLS-1$
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.action.Action#run()
|
|
||||||
*/
|
|
||||||
public void run() {
|
|
||||||
showDialogMenu();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fShowViewMenuAction.setEnabled(true);
|
|
||||||
fShowViewMenuAction.setActionDefinitionId("org.eclipse.ui.window.showViewMenu"); //$NON-NLS-1$
|
|
||||||
|
|
||||||
addHandlerAndKeyBindingSupport();
|
|
||||||
|
|
||||||
return fViewMenuButtonComposite;
|
return fViewMenuButtonComposite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,460 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jface.action.IMenuManager;
|
||||||
|
import org.eclipse.jface.dialogs.IDialogSettings;
|
||||||
|
import org.eclipse.jface.dialogs.PopupDialog;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.preference.PreferenceConverter;
|
||||||
|
import org.eclipse.jface.resource.JFaceResources;
|
||||||
|
import org.eclipse.jface.text.Document;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IInformationControl;
|
||||||
|
import org.eclipse.jface.text.IInformationControlExtension;
|
||||||
|
import org.eclipse.jface.text.IInformationControlExtension2;
|
||||||
|
import org.eclipse.jface.text.source.ISourceViewer;
|
||||||
|
import org.eclipse.jface.text.source.SourceViewer;
|
||||||
|
import org.eclipse.jface.viewers.Viewer;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.StyledText;
|
||||||
|
import org.eclipse.swt.events.DisposeEvent;
|
||||||
|
import org.eclipse.swt.events.DisposeListener;
|
||||||
|
import org.eclipse.swt.events.FocusListener;
|
||||||
|
import org.eclipse.swt.events.KeyEvent;
|
||||||
|
import org.eclipse.swt.events.KeyListener;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.graphics.Font;
|
||||||
|
import org.eclipse.swt.graphics.Point;
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
import org.eclipse.swt.graphics.Rectangle;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.CSourceViewer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for "quick" views in light-weight controls.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSourceViewerInformationControl extends PopupDialog implements IInformationControl, IInformationControlExtension, IInformationControlExtension2, DisposeListener {
|
||||||
|
|
||||||
|
private int fTextStyle;
|
||||||
|
|
||||||
|
private ISourceViewer fSourceViewer;
|
||||||
|
|
||||||
|
private Color fBackgroundColor;
|
||||||
|
|
||||||
|
private boolean fIsSystemBackgroundColor;
|
||||||
|
|
||||||
|
private int fMaxWidth;
|
||||||
|
|
||||||
|
private int fMaxHeight;
|
||||||
|
|
||||||
|
private List fColorExclusionControls= new ArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a source viewer information control with the given shell as parent. The given
|
||||||
|
* styles are applied to the shell and the source viewer.
|
||||||
|
*
|
||||||
|
* @param parent the parent shell
|
||||||
|
* @param shellStyle the additional styles for the shell
|
||||||
|
* @param textStyle the additional styles for the source viewer
|
||||||
|
* @param takeFocus flag indicating whether to take the focus
|
||||||
|
* @param showViewMenu flag indicating whether to show the "view" menu
|
||||||
|
* @param persistBounds flag indicating whether control size and location should be persisted
|
||||||
|
*/
|
||||||
|
public AbstractSourceViewerInformationControl(Shell parent, int shellStyle, int textStyle, boolean takeFocus, boolean showViewMenu, boolean persistBounds) {
|
||||||
|
super(parent, shellStyle, takeFocus, persistBounds, showViewMenu, false, null, null);
|
||||||
|
fTextStyle= textStyle;
|
||||||
|
// Title and status text must be set to get the title label created, so force empty values here.
|
||||||
|
if (hasHeader())
|
||||||
|
setTitleText(""); //$NON-NLS-1$
|
||||||
|
setInfoText(""); // //$NON-NLS-1$
|
||||||
|
|
||||||
|
// Create all controls
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeColors() {
|
||||||
|
RGB bgRGB= getHoverBackgroundColorRGB();
|
||||||
|
if (bgRGB != null) {
|
||||||
|
fBackgroundColor= new Color(getShell().getDisplay(), bgRGB);
|
||||||
|
fIsSystemBackgroundColor= false;
|
||||||
|
} else {
|
||||||
|
fBackgroundColor= getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
|
||||||
|
fIsSystemBackgroundColor= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RGB getHoverBackgroundColorRGB() {
|
||||||
|
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
return store.getBoolean(PreferenceConstants.EDITOR_SOURCE_HOVER_BACKGROUND_COLOR_SYSTEM_DEFAULT)
|
||||||
|
? null
|
||||||
|
: PreferenceConverter.getColor(store, PreferenceConstants.EDITOR_SOURCE_HOVER_BACKGROUND_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.dialogs.PopupDialog#createContents(org.eclipse.swt.widgets.Composite)
|
||||||
|
*/
|
||||||
|
protected Control createContents(Composite parent) {
|
||||||
|
Control contents= super.createContents(parent);
|
||||||
|
for (Iterator it= fColorExclusionControls.iterator(); it.hasNext(); ) {
|
||||||
|
Control ctrl = (Control) it.next();
|
||||||
|
ctrl.setBackground(fBackgroundColor);
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the main content for this information control.
|
||||||
|
*
|
||||||
|
* @param parent The parent composite
|
||||||
|
* @return The control representing the main content.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected Control createDialogArea(Composite parent) {
|
||||||
|
fSourceViewer= createSourceViewer(parent, fTextStyle);
|
||||||
|
|
||||||
|
final StyledText text= fSourceViewer.getTextWidget();
|
||||||
|
text.addKeyListener(new KeyListener() {
|
||||||
|
public void keyPressed(KeyEvent e) {
|
||||||
|
if (e.character == 0x1B) // ESC
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
public void keyReleased(KeyEvent e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addDisposeListener(this);
|
||||||
|
return ((Viewer)fSourceViewer).getControl();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ISourceViewer createSourceViewer(Composite parent, int style) {
|
||||||
|
IPreferenceStore store= CUIPlugin.getDefault().getCombinedPreferenceStore();
|
||||||
|
SourceViewer sourceViewer= new CSourceViewer(parent, null, null, false, style, store);
|
||||||
|
CTextTools tools= CUIPlugin.getDefault().getTextTools();
|
||||||
|
sourceViewer.configure(new SimpleCSourceViewerConfiguration(tools.getColorManager(), store, null, ICPartitions.C_PARTITIONING, false));
|
||||||
|
sourceViewer.setEditable(false);
|
||||||
|
|
||||||
|
StyledText styledText= sourceViewer.getTextWidget();
|
||||||
|
GridData gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
|
||||||
|
styledText.setLayoutData(gd);
|
||||||
|
initializeColors();
|
||||||
|
styledText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
|
||||||
|
styledText.setBackground(fBackgroundColor);
|
||||||
|
fColorExclusionControls.add(styledText);
|
||||||
|
|
||||||
|
Font font= JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT);
|
||||||
|
styledText.setFont(font);
|
||||||
|
|
||||||
|
return sourceViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.dialogs.PopupDialog#createInfoTextArea(org.eclipse.swt.widgets.Composite)
|
||||||
|
*/
|
||||||
|
protected Control createInfoTextArea(Composite parent) {
|
||||||
|
Control infoText= super.createInfoTextArea(parent);
|
||||||
|
fColorExclusionControls.add(infoText);
|
||||||
|
return infoText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.dialogs.PopupDialog#createTitleControl(org.eclipse.swt.widgets.Composite)
|
||||||
|
*/
|
||||||
|
protected Control createTitleControl(Composite parent) {
|
||||||
|
Control titleText= super.createTitleControl(parent);
|
||||||
|
fColorExclusionControls.add(titleText);
|
||||||
|
return titleText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.dialogs.PopupDialog#getBackgroundColorExclusions()
|
||||||
|
*/
|
||||||
|
protected List getBackgroundColorExclusions() {
|
||||||
|
List exclusions= super.getBackgroundColorExclusions();
|
||||||
|
exclusions.addAll(fColorExclusionControls);
|
||||||
|
return exclusions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.dialogs.PopupDialog#getForegroundColorExclusions()
|
||||||
|
*/
|
||||||
|
protected List getForegroundColorExclusions() {
|
||||||
|
List exclusions= super.getForegroundColorExclusions();
|
||||||
|
exclusions.addAll(fColorExclusionControls);
|
||||||
|
return exclusions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the dialog settings section.
|
||||||
|
* <p>
|
||||||
|
* The default is to return <code>null</code>.
|
||||||
|
* </p>
|
||||||
|
* @return the name of the dialog settings section or <code>null</code> 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 <code>true</code> if the control has a header, <code>false</code> otherwise.
|
||||||
|
* <p>
|
||||||
|
* The default is to return <code>false</code>.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return <code>true</code> 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
|
||||||
|
* <p>
|
||||||
|
* Subclasses may extend.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* 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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -7,85 +7,28 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* 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;
|
package org.eclipse.cdt.internal.ui.text.c.hover;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import org.eclipse.osgi.util.NLS;
|
||||||
import java.util.MissingResourceException;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
|
public final class CHoverMessages extends NLS {
|
||||||
|
|
||||||
/**
|
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.text.c.hover.CHoverMessages";//$NON-NLS-1$
|
||||||
* CHoverMessages
|
|
||||||
*/
|
|
||||||
public class CHoverMessages {
|
|
||||||
|
|
||||||
private static final String RESOURCE_BUNDLE= CHoverMessages.class.getName();
|
|
||||||
|
|
||||||
private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);
|
|
||||||
|
|
||||||
private CHoverMessages() {
|
private CHoverMessages() {
|
||||||
|
// Do not instantiate
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(String key) {
|
public static String CMacroExpansionControl_statusText;
|
||||||
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 });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
public static String CMacroExpansionControl_title_expansion;
|
||||||
* Gets a string from the resource bundle and formats it with the argument
|
public static String CMacroExpansionControl_title_fullyExpanded;
|
||||||
*
|
public static String CMacroExpansionControl_title_macroExpansion;
|
||||||
* @param key the string used to get the bundle value, must not be null
|
public static String CMacroExpansionControl_title_original;
|
||||||
* @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) });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
NLS.initializeMessages(BUNDLE_NAME, CHoverMessages.class);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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
|
# All rights reserved. This program and the accompanying materials
|
||||||
# are made available under the terms of the Eclipse Public License v1.0
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
# which accompanies this distribution, and is available at
|
# which accompanies this distribution, and is available at
|
||||||
|
@ -7,12 +7,11 @@
|
||||||
#
|
#
|
||||||
# Contributors:
|
# Contributors:
|
||||||
# IBM Corporation - initial API and implementation
|
# IBM Corporation - initial API and implementation
|
||||||
|
# Anton Leherbauer (Wind River Systems)
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
TypeHover.more_to_come=\ ...
|
CMacroExpansionControl_statusText=Press {0} or {1} to step through macro expansion
|
||||||
|
CMacroExpansionControl_title_expansion=Expansion \#{0) of {1}
|
||||||
CTextHover.createTextHover= Could not create c text hover
|
CMacroExpansionControl_title_fullyExpanded=Fully Expanded
|
||||||
|
CMacroExpansionControl_title_macroExpansion=Macro Expansion
|
||||||
CTextHover.makeStickyHint= Press ''{0}'' for focus.
|
CMacroExpansionControl_title_original=Original
|
||||||
|
|
||||||
NoBreakpointAnnotation.addBreakpoint= Add a breakpoint
|
|
||||||
|
|
|
@ -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 be <code>null</code>
|
||||||
|
*/
|
||||||
|
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 <code>null</code>
|
||||||
|
*/
|
||||||
|
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 <code>null</code>.
|
||||||
|
*
|
||||||
|
* @return The text to be shown in the popup's information area or <code>null</code>
|
||||||
|
*/
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -193,7 +193,7 @@ public class SourceViewerInformationControl implements IInformationControl, IInf
|
||||||
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
|
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
|
||||||
fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas);
|
fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas);
|
||||||
fStatusField.setFont(fStatusTextFont);
|
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);
|
fStatusField.setLayoutData(gd2);
|
||||||
|
|
||||||
// Regarding the color see bug 41128
|
// Regarding the color see bug 41128
|
||||||
|
@ -245,7 +245,7 @@ public class SourceViewerInformationControl implements IInformationControl, IInf
|
||||||
* or <code>null</code> if the status field should be hidden
|
* or <code>null</code> if the status field should be hidden
|
||||||
* @since 3.0
|
* @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);
|
this(parent, SWT.NO_TRIM | SWT.TOOL, style, statusFieldText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue